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, string source, string destination, bool customJob)\r
98         {\r
99             Job newJob = new Job\r
100                              {\r
101                                  Id = this.nextJobId++, \r
102                                  Query = query, \r
103                                  Source = source, \r
104                                  Destination = destination, \r
105                                  CustomQuery = customJob\r
106                              };\r
107 \r
108             this.queue.Add(newJob);\r
109             this.WriteQueueStateToFile("hb_queue_recovery.xml");\r
110         }\r
111 \r
112         /// <summary>\r
113         /// Removes an item from the queue.\r
114         /// </summary>\r
115         /// <param name="index">The zero-based location of the job in the queue.</param>\r
116         public void Remove(int index)\r
117         {\r
118             this.queue.RemoveAt(index);\r
119             this.WriteQueueStateToFile("hb_queue_recovery.xml");\r
120         }\r
121 \r
122         /// <summary>\r
123         /// Retrieve a job from the queue\r
124         /// </summary>\r
125         /// <param name="index">the job id</param>\r
126         /// <returns>A job for the given index or blank job object</returns>\r
127         public Job GetJob(int index)\r
128         {\r
129             if (this.queue.Count >= (index + 1))\r
130                 return this.queue[index];\r
131 \r
132             return new Job();\r
133         }\r
134 \r
135         /// <summary>\r
136         /// Moves an item up one position in the queue.\r
137         /// </summary>\r
138         /// <param name="index">The zero-based location of the job in the queue.</param>\r
139         public void MoveUp(int index)\r
140         {\r
141             if (index > 0)\r
142             {\r
143                 Job item = queue[index];\r
144 \r
145                 queue.RemoveAt(index);\r
146                 queue.Insert((index - 1), item);\r
147             }\r
148 \r
149             WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file\r
150         }\r
151 \r
152         /// <summary>\r
153         /// Moves an item down one position in the queue.\r
154         /// </summary>\r
155         /// <param name="index">The zero-based location of the job in the queue.</param>\r
156         public void MoveDown(int index)\r
157         {\r
158             if (index < this.queue.Count - 1)\r
159             {\r
160                 Job item = this.queue[index];\r
161 \r
162                 this.queue.RemoveAt(index);\r
163                 this.queue.Insert((index + 1), item);\r
164             }\r
165 \r
166             this.WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file\r
167         }\r
168 \r
169         /// <summary>\r
170         /// Writes the current state of the queue to a file.\r
171         /// </summary>\r
172         /// <param name="file">The location of the file to write the queue to.</param>\r
173         public void WriteQueueStateToFile(string file)\r
174         {\r
175             string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), \r
176                                               @"HandBrake\hb_queue_recovery.xml");\r
177             string tempPath = file == "hb_queue_recovery.xml" ? appDataPath : file;\r
178 \r
179             try\r
180             {\r
181                 using (FileStream strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write))\r
182                 {\r
183                     if (serializer == null)\r
184                         serializer = new XmlSerializer(typeof (List<Job>));\r
185                     serializer.Serialize(strm, queue);\r
186                     strm.Close();\r
187                     strm.Dispose();\r
188                 }\r
189             }\r
190             catch (Exception)\r
191             {\r
192                 return;\r
193             }\r
194         }\r
195 \r
196         /// <summary>\r
197         /// Writes the current state of the queue in the form of a batch (.bat) file.\r
198         /// </summary>\r
199         /// <param name="file">The location of the file to write the batch file to.</param>\r
200         public void WriteBatchScriptToFile(string file)\r
201         {\r
202             string queries = string.Empty;\r
203             foreach (Job queueItem in this.queue)\r
204             {\r
205                 string qItem = queueItem.Query;\r
206                 string fullQuery = '"' + Application.StartupPath + "\\HandBrakeCLI.exe" + '"' + qItem;\r
207 \r
208                 if (queries == string.Empty)\r
209                     queries = queries + fullQuery;\r
210                 else\r
211                     queries = queries + " && " + fullQuery;\r
212             }\r
213             string strCmdLine = queries;\r
214 \r
215             if (file != string.Empty)\r
216             {\r
217                 try\r
218                 {\r
219                     // Create a StreamWriter and open the file, Write the batch file query to the file and \r
220                     // Close the stream\r
221                     using (StreamWriter line = new StreamWriter(file))\r
222                     {\r
223                         line.WriteLine(strCmdLine);\r
224                     }\r
225 \r
226                     MessageBox.Show("Your batch script has been sucessfully saved.", "Status", MessageBoxButtons.OK, \r
227                                     MessageBoxIcon.Asterisk);\r
228                 }\r
229                 catch (Exception)\r
230                 {\r
231                     MessageBox.Show(\r
232                         "Unable to write to the file. Please make sure that the location has the correct permissions for file writing.", \r
233                         "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);\r
234                 }\r
235             }\r
236         }\r
237 \r
238         /// <summary>\r
239         /// Reads a serialized XML file that represents a queue of encoding jobs.\r
240         /// </summary>\r
241         /// <param name="file">The location of the file to read the queue from.</param>\r
242         public void LoadQueueFromFile(string file)\r
243         {\r
244             string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), \r
245                                               @"HandBrake\hb_queue_recovery.xml");\r
246             string tempPath = file == "hb_queue_recovery.xml" ? appDataPath : file;\r
247 \r
248             if (File.Exists(tempPath))\r
249             {\r
250                 using (FileStream strm = new FileStream(tempPath, FileMode.Open, FileAccess.Read))\r
251                 {\r
252                     if (strm.Length != 0)\r
253                     {\r
254                         if (serializer == null)\r
255                             serializer = new XmlSerializer(typeof (List<Job>));\r
256 \r
257                         List<Job> list = serializer.Deserialize(strm) as List<Job>;\r
258 \r
259                         if (list != null)\r
260                             foreach (Job item in list)\r
261                                 this.queue.Add(item);\r
262 \r
263                         if (file != "hb_queue_recovery.xml")\r
264                             this.WriteQueueStateToFile("hb_queue_recovery.xml");\r
265                     }\r
266                 }\r
267             }\r
268         }\r
269 \r
270         /// <summary>\r
271         /// Checks the current queue for an existing instance of the specified destination.\r
272         /// </summary>\r
273         /// <param name="destination">The destination of the encode.</param>\r
274         /// <returns>Whether or not the supplied destination is already in the queue.</returns>\r
275         public bool CheckForDestinationDuplicate(string destination)\r
276         {\r
277             foreach (Job checkItem in this.queue)\r
278             {\r
279                 if (checkItem.Destination.Contains(destination.Replace("\\\\", "\\")))\r
280                     return true;\r
281             }\r
282 \r
283             return false;\r
284         }\r
285 \r
286         #endregion\r
287 \r
288         #region Encoding\r
289 \r
290         /// <summary>\r
291         /// Gets or sets the last encode that was processed.\r
292         /// </summary>\r
293         /// <returns></returns> \r
294         public Job LastEncode { get; set; }\r
295 \r
296         /// <summary>\r
297         /// Gets a value indicating whether Request Pause\r
298         /// </summary>\r
299         public bool PauseRequested { get; private set; }\r
300 \r
301         /// <summary>\r
302         /// Starts encoding the first job in the queue and continues encoding until all jobs\r
303         /// have been encoded.\r
304         /// </summary>\r
305         public void Start()\r
306         {\r
307             if (this.Count != 0)\r
308             {\r
309                 if (this.PauseRequested)\r
310                     this.PauseRequested = false;\r
311                 else\r
312                 {\r
313                     this.PauseRequested = false;\r
314                     try\r
315                     {\r
316                         Thread theQueue = new Thread(this.StartQueue) {IsBackground = true};\r
317                         theQueue.Start();\r
318                     }\r
319                     catch (Exception exc)\r
320                     {\r
321                         MessageBox.Show(exc.ToString());\r
322                     }\r
323                 }\r
324             }\r
325         }\r
326 \r
327         /// <summary>\r
328         /// Requests a pause of the encode queue.\r
329         /// </summary>\r
330         public void Pause()\r
331         {\r
332             this.PauseRequested = true;\r
333 \r
334             if (this.QueuePauseRequested != null)\r
335                 this.QueuePauseRequested(this, new EventArgs());\r
336         }\r
337 \r
338         /// <summary>\r
339         /// Run through all the jobs on the queue.\r
340         /// </summary>\r
341         /// <param name="state">Object State</param>\r
342         private void StartQueue(object state)\r
343         {\r
344             // Run through each item on the queue\r
345             while (this.Count != 0)\r
346             {\r
347                 Job encJob = this.GetNextJob();\r
348                 this.WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file\r
349 \r
350                 Run(encJob);\r
351 \r
352                 if (HbProcess == null)\r
353                 {\r
354                     return;\r
355                 }\r
356                 HbProcess.WaitForExit();\r
357 \r
358                 AddCLIQueryToLog(encJob);\r
359                 this.CopyLog(this.LastEncode.Destination);\r
360 \r
361                 HbProcess.Close();\r
362                 HbProcess.Dispose();\r
363 \r
364                 IsEncoding = false;\r
365 \r
366                 // Growl\r
367                 if (Properties.Settings.Default.growlEncode)\r
368                     GrowlCommunicator.Notify("Encode Completed", \r
369                                              "Put down that cocktail...\nyour Handbrake encode is done.");\r
370 \r
371                 while (this.PauseRequested) // Need to find a better way of doing this.\r
372                 {\r
373                     Thread.Sleep(2000);\r
374                 }\r
375             }\r
376             this.LastEncode = new Job();\r
377 \r
378             if (this.QueueCompleted != null)\r
379                 this.QueueCompleted(this, new EventArgs());\r
380 \r
381             // After the encode is done, we may want to shutdown, suspend etc.\r
382             Finish();\r
383         }\r
384 \r
385         #endregion\r
386     }\r
387 }