OSDN Git Service

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