OSDN Git Service

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