OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / win / C# / Services / Queue.cs
1 /*  Queue.cs $\r
2     This file is part of the HandBrake source code.\r
3     Homepage: <http://handbrake.fr/>.\r
4     It may be used under the terms of the GNU General Public License. */\r
5 \r
6 namespace Handbrake.Services\r
7 {\r
8     using System;\r
9     using System.Collections.Generic;\r
10     using System.Collections.ObjectModel;\r
11     using System.IO;\r
12     using System.Threading;\r
13     using System.Windows.Forms;\r
14     using System.Xml.Serialization;\r
15     using Functions;\r
16     using Model;\r
17 \r
18     /// <summary>\r
19     /// The HandBrake Queue\r
20     /// </summary>\r
21     public class Queue : Encode\r
22     {\r
23         /// <summary>\r
24         /// The Queue Job List\r
25         /// </summary>\r
26         private readonly List<Job> queue = new List<Job>();\r
27 \r
28         /// <summary>\r
29         /// An XML Serializer\r
30         /// </summary>\r
31         private static XmlSerializer serializer;\r
32 \r
33         /// <summary>\r
34         /// The Next Job ID\r
35         /// </summary>\r
36         private int nextJobId;\r
37 \r
38         /// <summary>\r
39         /// Fires when a pause to the encode queue has been requested.\r
40         /// </summary>\r
41         public event EventHandler QueuePauseRequested;\r
42 \r
43         /// <summary>\r
44         /// Fires when the entire encode queue has completed.\r
45         /// </summary>\r
46         public event EventHandler QueueCompleted;\r
47 \r
48         #region Queue\r
49 \r
50         /// <summary>\r
51         /// Gets and removes the next job in the queue.\r
52         /// </summary>\r
53         /// <returns>The job that was removed from the queue.</returns>\r
54         private Job GetNextJob()\r
55         {\r
56             Job job = this.queue[0];\r
57             this.LastEncode = job;\r
58             this.Remove(0); // Remove the item which we are about to pass out.\r
59 \r
60             this.WriteQueueStateToFile("hb_queue_recovery.xml");\r
61 \r
62             return job;\r
63         }\r
64 \r
65         /// <summary>\r
66         /// Gets the current state of the encode queue.\r
67         /// </summary>\r
68         public ReadOnlyCollection<Job> CurrentQueue\r
69         {\r
70             get { return this.queue.AsReadOnly(); }\r
71         }\r
72 \r
73         /// <summary>\r
74         /// Gets the number of items in the queue.\r
75         /// </summary>\r
76         public int Count\r
77         {\r
78             get { return this.queue.Count; }\r
79         }\r
80 \r
81         /// <summary>\r
82         /// Adds an item to the queue.\r
83         /// </summary>\r
84         /// <param name="query">\r
85         /// The query that will be passed to the HandBrake CLI.\r
86         /// </param>\r
87         /// <param name="title">\r
88         /// The title.\r
89         /// </param>\r
90         /// <param name="source">\r
91         /// The location of the source video.\r
92         /// </param>\r
93         /// <param name="destination">\r
94         /// The location where the encoded video will be.\r
95         /// </param>\r
96         /// <param name="customJob">\r
97         /// Custom job\r
98         /// </param>\r
99         public void Add(string query, int title, string source, string destination, bool customJob)\r
100         {\r
101             Job newJob = new Job\r
102                              {\r
103                                  Id = this.nextJobId++,\r
104                                  Title = title,\r
105                                  Query = query, \r
106                                  Source = source, \r
107                                  Destination = destination, \r
108                                  CustomQuery = customJob\r
109                              };\r
110 \r
111             this.queue.Add(newJob);\r
112             this.WriteQueueStateToFile("hb_queue_recovery.xml");\r
113         }\r
114 \r
115         /// <summary>\r
116         /// Removes an item from the queue.\r
117         /// </summary>\r
118         /// <param name="index">The zero-based location of the job in the queue.</param>\r
119         public void Remove(int index)\r
120         {\r
121             this.queue.RemoveAt(index);\r
122             this.WriteQueueStateToFile("hb_queue_recovery.xml");\r
123         }\r
124 \r
125         /// <summary>\r
126         /// Retrieve a job from the queue\r
127         /// </summary>\r
128         /// <param name="index">the job id</param>\r
129         /// <returns>A job for the given index or blank job object</returns>\r
130         public Job GetJob(int index)\r
131         {\r
132             if (this.queue.Count >= (index + 1))\r
133                 return this.queue[index];\r
134 \r
135             return new Job();\r
136         }\r
137 \r
138         /// <summary>\r
139         /// Moves an item up one position in the queue.\r
140         /// </summary>\r
141         /// <param name="index">The zero-based location of the job in the queue.</param>\r
142         public void MoveUp(int index)\r
143         {\r
144             if (index > 0)\r
145             {\r
146                 Job item = queue[index];\r
147 \r
148                 queue.RemoveAt(index);\r
149                 queue.Insert((index - 1), item);\r
150             }\r
151 \r
152             WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file\r
153         }\r
154 \r
155         /// <summary>\r
156         /// Moves an item down one position in the queue.\r
157         /// </summary>\r
158         /// <param name="index">The zero-based location of the job in the queue.</param>\r
159         public void MoveDown(int index)\r
160         {\r
161             if (index < this.queue.Count - 1)\r
162             {\r
163                 Job item = this.queue[index];\r
164 \r
165                 this.queue.RemoveAt(index);\r
166                 this.queue.Insert((index + 1), item);\r
167             }\r
168 \r
169             this.WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file\r
170         }\r
171 \r
172         /// <summary>\r
173         /// Writes the current state of the queue to a file.\r
174         /// </summary>\r
175         /// <param name="file">The location of the file to write the queue to.</param>\r
176         public void WriteQueueStateToFile(string file)\r
177         {\r
178             string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), \r
179                                               @"HandBrake\hb_queue_recovery.xml");\r
180             string tempPath = file == "hb_queue_recovery.xml" ? appDataPath : file;\r
181 \r
182             try\r
183             {\r
184                 using (FileStream strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write))\r
185                 {\r
186                     if (serializer == null)\r
187                         serializer = new XmlSerializer(typeof (List<Job>));\r
188                     serializer.Serialize(strm, queue);\r
189                     strm.Close();\r
190                     strm.Dispose();\r
191                 }\r
192             }\r
193             catch (Exception)\r
194             {\r
195                 return;\r
196             }\r
197         }\r
198 \r
199         /// <summary>\r
200         /// Writes the current state of the queue in the form of a batch (.bat) file.\r
201         /// </summary>\r
202         /// <param name="file">The location of the file to write the batch file to.</param>\r
203         public void WriteBatchScriptToFile(string file)\r
204         {\r
205             string queries = string.Empty;\r
206             foreach (Job queueItem in this.queue)\r
207             {\r
208                 string qItem = queueItem.Query;\r
209                 string fullQuery = '"' + Application.StartupPath + "\\HandBrakeCLI.exe" + '"' + qItem;\r
210 \r
211                 if (queries == string.Empty)\r
212                     queries = queries + fullQuery;\r
213                 else\r
214                     queries = queries + " && " + fullQuery;\r
215             }\r
216             string strCmdLine = queries;\r
217 \r
218             if (file != string.Empty)\r
219             {\r
220                 try\r
221                 {\r
222                     // Create a StreamWriter and open the file, Write the batch file query to the file and \r
223                     // Close the stream\r
224                     using (StreamWriter line = new StreamWriter(file))\r
225                     {\r
226                         line.WriteLine(strCmdLine);\r
227                     }\r
228 \r
229                     MessageBox.Show("Your batch script has been sucessfully saved.", "Status", MessageBoxButtons.OK, \r
230                                     MessageBoxIcon.Asterisk);\r
231                 }\r
232                 catch (Exception)\r
233                 {\r
234                     MessageBox.Show(\r
235                         "Unable to write to the file. Please make sure that the location has the correct permissions for file writing.", \r
236                         "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);\r
237                 }\r
238             }\r
239         }\r
240 \r
241         /// <summary>\r
242         /// Reads a serialized XML file that represents a queue of encoding jobs.\r
243         /// </summary>\r
244         /// <param name="file">The location of the file to read the queue from.</param>\r
245         public void LoadQueueFromFile(string file)\r
246         {\r
247             string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), \r
248                                               @"HandBrake\hb_queue_recovery.xml");\r
249             string tempPath = file == "hb_queue_recovery.xml" ? appDataPath : file;\r
250 \r
251             if (File.Exists(tempPath))\r
252             {\r
253                 using (FileStream strm = new FileStream(tempPath, FileMode.Open, FileAccess.Read))\r
254                 {\r
255                     if (strm.Length != 0)\r
256                     {\r
257                         if (serializer == null)\r
258                             serializer = new XmlSerializer(typeof (List<Job>));\r
259 \r
260                         List<Job> list = serializer.Deserialize(strm) as List<Job>;\r
261 \r
262                         if (list != null)\r
263                             foreach (Job item in list)\r
264                                 this.queue.Add(item);\r
265 \r
266                         if (file != "hb_queue_recovery.xml")\r
267                             this.WriteQueueStateToFile("hb_queue_recovery.xml");\r
268                     }\r
269                 }\r
270             }\r
271         }\r
272 \r
273         /// <summary>\r
274         /// Checks the current queue for an existing instance of the specified destination.\r
275         /// </summary>\r
276         /// <param name="destination">The destination of the encode.</param>\r
277         /// <returns>Whether or not the supplied destination is already in the queue.</returns>\r
278         public bool CheckForDestinationDuplicate(string destination)\r
279         {\r
280             foreach (Job checkItem in this.queue)\r
281             {\r
282                 if (checkItem.Destination.Contains(destination.Replace("\\\\", "\\")))\r
283                     return true;\r
284             }\r
285 \r
286             return false;\r
287         }\r
288 \r
289         #endregion\r
290 \r
291         #region Encoding\r
292 \r
293         /// <summary>\r
294         /// Gets or sets the last encode that was processed.\r
295         /// </summary>\r
296         /// <returns></returns> \r
297         public Job LastEncode { get; set; }\r
298 \r
299         /// <summary>\r
300         /// Gets a value indicating whether Request Pause\r
301         /// </summary>\r
302         public bool PauseRequested { get; private set; }\r
303 \r
304         /// <summary>\r
305         /// Starts encoding the first job in the queue and continues encoding until all jobs\r
306         /// have been encoded.\r
307         /// </summary>\r
308         public void Start()\r
309         {\r
310             if (this.Count != 0)\r
311             {\r
312                 if (this.PauseRequested)\r
313                     this.PauseRequested = false;\r
314                 else\r
315                 {\r
316                     this.PauseRequested = false;\r
317                     try\r
318                     {\r
319                         Thread theQueue = new Thread(this.StartQueue) {IsBackground = true};\r
320                         theQueue.Start();\r
321                     }\r
322                     catch (Exception exc)\r
323                     {\r
324                         MessageBox.Show(exc.ToString());\r
325                     }\r
326                 }\r
327             }\r
328         }\r
329 \r
330         /// <summary>\r
331         /// Requests a pause of the encode queue.\r
332         /// </summary>\r
333         public void Pause()\r
334         {\r
335             this.PauseRequested = true;\r
336 \r
337             if (this.QueuePauseRequested != null)\r
338                 this.QueuePauseRequested(this, new EventArgs());\r
339         }\r
340 \r
341         /// <summary>\r
342         /// Run through all the jobs on the queue.\r
343         /// </summary>\r
344         /// <param name="state">Object State</param>\r
345         private void StartQueue(object state)\r
346         {\r
347             // Run through each item on the queue\r
348             while (this.Count != 0)\r
349             {\r
350                 Job encJob = this.GetNextJob();\r
351                 this.WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file\r
352 \r
353                 Run(encJob);\r
354 \r
355                 if (HbProcess == null)\r
356                 {\r
357                     return;\r
358                 }\r
359                 HbProcess.WaitForExit();\r
360 \r
361                 AddCLIQueryToLog(encJob);\r
362                 this.CopyLog(this.LastEncode.Destination);\r
363 \r
364                 HbProcess.Close();\r
365                 HbProcess.Dispose();\r
366 \r
367                 // Growl\r
368                 if (Properties.Settings.Default.growlEncode)\r
369                     GrowlCommunicator.Notify("Encode Completed", \r
370                                              "Put down that cocktail...\nyour Handbrake encode is done.");\r
371 \r
372                 while (this.PauseRequested) // Need to find a better way of doing this.\r
373                 {\r
374                     Thread.Sleep(2000);\r
375                 }\r
376             }\r
377             this.LastEncode = new Job();\r
378 \r
379             if (this.QueueCompleted != null)\r
380                 this.QueueCompleted(this, new EventArgs());\r
381 \r
382             // After the encode is done, we may want to shutdown, suspend etc.\r
383             Finish();\r
384         }\r
385 \r
386         #endregion\r
387     }\r
388 }