OSDN Git Service

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