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