OSDN Git Service

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