OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / win / C# / frmQueue.cs
1 /*  frmQueue.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\r
7 {\r
8     using System;\r
9     using System.Collections.Generic;\r
10     using System.Collections.ObjectModel;\r
11     using System.ComponentModel;\r
12     using System.IO;\r
13     using System.Linq;\r
14     using System.Windows.Forms;\r
15     using Functions;\r
16 \r
17     using HandBrake.ApplicationServices.Model;\r
18     using HandBrake.ApplicationServices.Model.Encoding;\r
19     using HandBrake.ApplicationServices.Services;\r
20     using HandBrake.ApplicationServices.Services.Interfaces;\r
21 \r
22     using Model;\r
23 \r
24     /// <summary>\r
25     /// The Queue Window\r
26     /// </summary>\r
27     public partial class frmQueue : Form\r
28     {\r
29         /// <summary>\r
30         /// Update Handler Delegate\r
31         /// </summary>\r
32         private delegate void UpdateHandler();\r
33 \r
34         /// <summary>\r
35         /// An instance of the Queue service\r
36         /// </summary>\r
37         private readonly IQueueProcessor queue;\r
38 \r
39         /// <summary>\r
40         /// A reference to the main application window\r
41         /// </summary>\r
42         private readonly frmMain mainWindow;\r
43 \r
44         /// <summary>\r
45         /// Initializes a new instance of the <see cref="frmQueue"/> class.\r
46         /// </summary>\r
47         /// <param name="q">\r
48         /// An instance of the queue service.\r
49         /// </param>\r
50         /// <param name="mw">\r
51         /// The main window.\r
52         /// </param>\r
53         public frmQueue(IQueueProcessor q, frmMain mw)\r
54         {\r
55             InitializeComponent();\r
56 \r
57             this.mainWindow = mw;\r
58 \r
59             this.queue = q;\r
60             queue.EncodeService.EncodeStarted += this.QueueOnEncodeStart;\r
61             queue.QueueCompleted += this.QueueOnQueueFinished;\r
62             queue.QueuePaused += this.QueueOnPaused;\r
63             queue.QueueManager.QueueChanged += new EventHandler(queue_QueueListChanged);\r
64 \r
65             queue.EncodeService.EncodeStarted += this.queue_EncodeStarted;\r
66             queue.EncodeService.EncodeCompleted += this.queue_EncodeEnded;\r
67 \r
68             drp_completeOption.Text = Properties.Settings.Default.CompletionOption;\r
69         }\r
70 \r
71         /// <summary>\r
72         /// Queue Changed\r
73         /// </summary>\r
74         /// <param name="sender">\r
75         /// The sender.\r
76         /// </param>\r
77         /// <param name="e">\r
78         /// The e.\r
79         /// </param>\r
80         private void queue_QueueListChanged(object sender, EventArgs e)\r
81         {\r
82             UpdateUiElementsOnQueueChange();\r
83         }\r
84 \r
85         /// <summary>\r
86         /// Encode Ended\r
87         /// </summary>\r
88         /// <param name="sender">\r
89         /// The sender.\r
90         /// </param>\r
91         /// <param name="e">\r
92         /// The e.\r
93         /// </param>\r
94         private void queue_EncodeEnded(object sender, EventArgs e)\r
95         {\r
96             queue.EncodeService.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;\r
97             ResetEncodeText();\r
98         }\r
99 \r
100         /// <summary>\r
101         /// Queue Started\r
102         /// </summary>\r
103         /// <param name="sender">\r
104         /// The sender.\r
105         /// </param>\r
106         /// <param name="e">\r
107         /// The e.\r
108         /// </param>\r
109         private void queue_EncodeStarted(object sender, EventArgs e)\r
110         {\r
111             this.SetCurrentEncodeInformation();\r
112             queue.EncodeService.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;        \r
113         }\r
114 \r
115         /// <summary>\r
116         /// Display the Encode Status\r
117         /// </summary>\r
118         /// <param name="sender">\r
119         /// The sender.\r
120         /// </param>\r
121         /// <param name="e">\r
122         /// The e.\r
123         /// </param>\r
124         private void EncodeQueue_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EventArgs.EncodeProgressEventArgs e)\r
125         {\r
126             if (this.InvokeRequired)\r
127             {\r
128                 this.BeginInvoke(new EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });\r
129                 return;\r
130             }\r
131 \r
132             lbl_encodeStatus.Text =\r
133                 string.Format(\r
134                 "Encoding: Pass {0} of {1}, {2:00.00}% Time Remaining: {3}",\r
135                 e.Task,\r
136                 e.TaskCount,\r
137                 e.PercentComplete,\r
138                 e.EstimatedTimeLeft);\r
139         }\r
140 \r
141         /// <summary>\r
142         /// Handle the Queue Paused event\r
143         /// </summary>\r
144         /// <param name="sender">\r
145         /// The sender.\r
146         /// </param>\r
147         /// <param name="e">\r
148         /// The EventArgs.\r
149         /// </param>\r
150         private void QueueOnPaused(object sender, EventArgs e)\r
151         {\r
152             SetUiEncodeFinished();\r
153             UpdateUiElementsOnQueueChange();\r
154         }\r
155 \r
156         /// <summary>\r
157         /// Handle the Queue Finished event.\r
158         /// </summary>\r
159         /// <param name="sender">\r
160         /// The sender.\r
161         /// </param>\r
162         /// <param name="e">\r
163         /// The EventArgs.\r
164         /// </param>\r
165         private void QueueOnQueueFinished(object sender, EventArgs e)\r
166         {\r
167             SetUiEncodeFinished();\r
168             ResetQueue(); // Reset the Queue Window\r
169         }\r
170 \r
171         /// <summary>\r
172         /// Handle the Encode Started event\r
173         /// </summary>\r
174         /// <param name="sender">\r
175         /// The sender.\r
176         /// </param>\r
177         /// <param name="e">\r
178         /// The e.\r
179         /// </param>\r
180         private void QueueOnEncodeStart(object sender, EventArgs e)\r
181         {\r
182             SetUiEncodeStarted(); // make sure the UI is set correctly\r
183             UpdateUiElementsOnQueueChange(); // Redraw the Queue, a new encode has started.\r
184         }\r
185 \r
186         /// <summary>\r
187         /// Initializes the Queue list with the Arraylist from the Queue class\r
188         /// </summary>\r
189         public void SetQueue()\r
190         {\r
191             UpdateUiElementsOnQueueChange();\r
192         }\r
193 \r
194         /// <summary>\r
195         /// Initializes the Queue list, then shows and activates the window\r
196         /// </summary>\r
197         public new void Show()\r
198         {\r
199             Show(true);\r
200         }\r
201 \r
202         /// <summary>\r
203         /// Initializes the Queue list only if doSetQueue is true, then shows and activates the window\r
204         /// </summary>\r
205         /// <param name="doSetQueue">Indicates whether to call setQueue() before showing the window</param>\r
206         public void Show(bool doSetQueue)\r
207         {\r
208             if (doSetQueue) SetQueue();\r
209             base.Show();\r
210         }\r
211 \r
212         /// <summary>\r
213         /// Handle the Encode button Click event\r
214         /// </summary>\r
215         /// <param name="sender">The sender</param>\r
216         /// <param name="e">the EventArgs</param>\r
217         private void BtnEncodeClick(object sender, EventArgs e)\r
218         {\r
219             if (!queue.IsProcessing)\r
220             {\r
221                 SetUiEncodeStarted();\r
222             }\r
223 \r
224             lbl_encodeStatus.Text = "Encoding ...";\r
225             queue.Start();\r
226         }\r
227 \r
228         /// <summary>\r
229         /// Handle the Pause button click event.\r
230         /// </summary>\r
231         /// <param name="sender">\r
232         /// The sender.\r
233         /// </param>\r
234         /// <param name="e">\r
235         /// The EventArgs.\r
236         /// </param>\r
237         private void BtnPauseClick(object sender, EventArgs e)\r
238         {\r
239             queue.Pause();\r
240             MessageBox.Show(\r
241                 "No further items on the queue will start. The current encode process will continue until it is finished. \nClick 'Encode' when you wish to continue encoding the queue.",\r
242                 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
243         }\r
244 \r
245         // UI Work\r
246 \r
247         /// <summary>\r
248         /// Setup the UI to show that an encode has started\r
249         /// </summary>\r
250         private void SetUiEncodeStarted()\r
251         {\r
252             if (InvokeRequired)\r
253             {\r
254                 BeginInvoke(new UpdateHandler(SetUiEncodeStarted));\r
255                 return;\r
256             }\r
257             btn_encode.Enabled = false;\r
258             btn_pause.Visible = true;\r
259         }\r
260 \r
261         /// <summary>\r
262         /// Setup the UI to indicate that an encode has finished.\r
263         /// </summary>\r
264         private void SetUiEncodeFinished()\r
265         {\r
266             if (InvokeRequired)\r
267             {\r
268                 BeginInvoke(new UpdateHandler(SetUiEncodeFinished));\r
269                 return;\r
270             }\r
271             btn_pause.Visible = false;\r
272             btn_encode.Enabled = true;\r
273         }\r
274 \r
275         /// <summary>\r
276         /// Reset the Queue Window display\r
277         /// </summary>\r
278         private void ResetQueue()\r
279         {\r
280             if (InvokeRequired)\r
281             {\r
282                 BeginInvoke(new UpdateHandler(ResetQueue));\r
283                 return;\r
284             }\r
285             btn_pause.Visible = false;\r
286             btn_encode.Enabled = true;\r
287 \r
288             ResetEncodeText();\r
289         }\r
290 \r
291         /// <summary>\r
292         /// Reset the current job text\r
293         /// </summary>\r
294         private void ResetEncodeText()\r
295         {\r
296             if (InvokeRequired)\r
297             {\r
298                 BeginInvoke(new UpdateHandler(ResetEncodeText));\r
299                 return;\r
300             }\r
301             lbl_encodeStatus.Text = "Ready";\r
302 \r
303             lbl_source.Text = "-";\r
304             lbl_dest.Text = "-";\r
305             lbl_encodeOptions.Text = "-";\r
306 \r
307             lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
308         }\r
309 \r
310         /// <summary>\r
311         /// Redraw the Queue window with the latest information about HandBrakes status\r
312         /// </summary>\r
313         private void RedrawQueue()\r
314         {\r
315             if (InvokeRequired)\r
316             {\r
317                 BeginInvoke(new UpdateHandler(RedrawQueue));\r
318                 return;\r
319             }\r
320 \r
321             list_queue.Items.Clear();\r
322             ReadOnlyCollection<QueueTask> theQueue = queue.QueueManager.Queue;\r
323             foreach (QueueTask queueItem in theQueue)\r
324             {\r
325                 string qItem = queueItem.Query;\r
326                 QueryParser parsed = QueryParser.Parse(qItem);\r
327 \r
328                 // Get the DVD Title\r
329                 string title = parsed.Title == 0 ? "Auto" : parsed.Title.ToString();\r
330 \r
331                 // Get the DVD Chapters\r
332                 string chapters;\r
333                 if (parsed.ChapterStart == 0)\r
334                     chapters = "Auto";\r
335                 else\r
336                 {\r
337                     chapters = parsed.ChapterStart.ToString();\r
338                     if (parsed.ChapterFinish != 0)\r
339                         chapters = chapters + " - " + parsed.ChapterFinish;\r
340                 }\r
341 \r
342                 ListViewItem item = new ListViewItem { Tag = queueItem, Text = title };\r
343                 item.SubItems.Add(chapters); // Chapters\r
344                 item.SubItems.Add(queueItem.Source); // Source\r
345                 item.SubItems.Add(queueItem.Destination); // Destination\r
346                 item.SubItems.Add(parsed.VideoEncoder); // Video\r
347 \r
348                 // Display The Audio Track Information\r
349                 string audio = string.Empty;\r
350                 foreach (AudioTrack track in parsed.AudioInformation)\r
351                 {\r
352                     if (audio != string.Empty)\r
353                         audio += ", " + track.Encoder;\r
354                     else\r
355                         audio = track.Encoder;\r
356                 }\r
357                 item.SubItems.Add(audio); // Audio\r
358 \r
359                 list_queue.Items.Add(item);\r
360             }\r
361         }\r
362 \r
363         /// <summary>\r
364         /// Update the UI elements\r
365         /// </summary>\r
366         private void UpdateUiElementsOnQueueChange()\r
367         {\r
368             if (InvokeRequired)\r
369             {\r
370                 BeginInvoke(new UpdateHandler(UpdateUiElementsOnQueueChange));\r
371                 return;\r
372             }\r
373 \r
374             RedrawQueue();\r
375             lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
376         }\r
377 \r
378         /// <summary>\r
379         /// Set the window up with the current encode information\r
380         /// </summary>\r
381         private void SetCurrentEncodeInformation()\r
382         {\r
383             try\r
384             {\r
385                 if (InvokeRequired)\r
386                 {\r
387                     BeginInvoke(new UpdateHandler(SetCurrentEncodeInformation));\r
388                 }\r
389 \r
390                 QueryParser parsed = QueryParser.Parse(queue.QueueManager.LastProcessedJob.Query);\r
391 \r
392                 // Get title and chapters\r
393                 string title = parsed.Title == 0 ? "Auto" : parsed.Title.ToString();\r
394                 string chapterlbl;\r
395                 if (Equals(parsed.ChapterStart, 0))\r
396                     chapterlbl = "Auto";\r
397                 else\r
398                 {\r
399                     string chapters = parsed.ChapterStart.ToString();\r
400                     if (parsed.ChapterFinish != 0)\r
401                         chapters = chapters + " - " + parsed.ChapterFinish;\r
402                     chapterlbl = chapters;\r
403                 }\r
404 \r
405                 // Get audio information\r
406                 string audio = string.Empty;\r
407                 foreach (AudioTrack track in parsed.AudioInformation)\r
408                 {\r
409                     if (audio != string.Empty) \r
410                         audio += ", " + track.Encoder;\r
411                     else\r
412                         audio = track.Encoder;\r
413                 }\r
414 \r
415                 // found query is a global varible        \r
416                 lbl_encodeStatus.Text = "Encoding ...";\r
417                 lbl_source.Text = queue.QueueManager.LastProcessedJob.Source + "(Title: " + title + " Chapters: " + chapterlbl + ")";\r
418                 lbl_dest.Text = queue.QueueManager.LastProcessedJob.Destination;\r
419                 lbl_encodeOptions.Text = "Video: " + parsed.VideoEncoder + " Audio: " + audio + Environment.NewLine +\r
420                                     "x264 Options: " + parsed.H264Query;\r
421                }\r
422             catch (Exception)\r
423             {\r
424                 // Do Nothing\r
425             }\r
426         }\r
427 \r
428         /* Right Click Menu */\r
429 \r
430         /// <summary>\r
431         /// Handle the Move Up Menu Item\r
432         /// </summary>\r
433         /// <param name="sender">\r
434         /// The sender.\r
435         /// </param>\r
436         /// <param name="e">\r
437         /// The e.\r
438         /// </param>\r
439         private void MnuUpClick(object sender, EventArgs e)\r
440         {\r
441             MoveUp();\r
442         }\r
443 \r
444         /// <summary>\r
445         /// Handle the Move down Menu Item\r
446         /// </summary>\r
447         /// <param name="sender">\r
448         /// The sender.\r
449         /// </param>\r
450         /// <param name="e">\r
451         /// The e.\r
452         /// </param>\r
453         private void MnuDownClick(object sender, EventArgs e)\r
454         {\r
455             MoveDown();\r
456         }\r
457 \r
458         /// <summary>\r
459         /// Edit a job\r
460         /// </summary>\r
461         /// <param name="sender">\r
462         /// The sender.\r
463         /// </param>\r
464         /// <param name="e">\r
465         /// The e.\r
466         /// </param>\r
467         private void MnuEditClick(object sender, EventArgs e)\r
468         {\r
469             if (list_queue.SelectedIndices != null && list_queue.SelectedIndices.Count != 0)\r
470             {\r
471                 lock (queue)\r
472                 {\r
473                     lock (list_queue)\r
474                     {\r
475                         QueueTask index = list_queue.SelectedItems[0].Tag as QueueTask;\r
476                         mainWindow.RecievingJob(index);\r
477                         queue.QueueManager.Remove(index);\r
478                         RedrawQueue();\r
479                     }\r
480                 }\r
481             }\r
482         }\r
483 \r
484         /// <summary>\r
485         /// Handle the delete Menu Item\r
486         /// </summary>\r
487         /// <param name="sender">\r
488         /// The sender.\r
489         /// </param>\r
490         /// <param name="e">\r
491         /// The e.\r
492         /// </param>\r
493         private void MnuDeleteClick(object sender, EventArgs e)\r
494         {\r
495             DeleteSelectedItems();\r
496         }\r
497 \r
498         /* Keyboard Shortcuts */\r
499 \r
500         /// <summary>\r
501         /// Handle the delete keyboard press\r
502         /// </summary>\r
503         /// <param name="sender">\r
504         /// The sender.\r
505         /// </param>\r
506         /// <param name="e">\r
507         /// The e.\r
508         /// </param>\r
509         private void ListQueueDeleteKey(object sender, KeyEventArgs e)\r
510         {\r
511             if (e.KeyCode == Keys.Delete && e.Modifiers == Keys.None)\r
512                 DeleteSelectedItems();\r
513         }\r
514 \r
515         /* Queue Management */\r
516 \r
517         /// <summary>\r
518         /// Move items up in the queue\r
519         /// </summary>\r
520         private void MoveUp()\r
521         {\r
522             // If there are selected items and the first item is not selected\r
523             if (list_queue.SelectedIndices.Count > 0 && !list_queue.SelectedIndices.Contains(0))\r
524             {\r
525                 // Copy the selected indices to preserve them during the movement\r
526                 List<int> selectedIndices = new List<int>(list_queue.SelectedIndices.Count);\r
527                 foreach (int selectedIndex in list_queue.SelectedIndices)\r
528                     selectedIndices.Add(selectedIndex);\r
529 \r
530                 // Move up each selected item\r
531                 foreach (int selectedIndex in selectedIndices)\r
532                     queue.QueueManager.MoveUp(selectedIndex);\r
533 \r
534                 // Keep the selected item(s) selected, now moved up one index\r
535                 foreach (int selectedIndex in selectedIndices)\r
536                     if (selectedIndex - 1 > -1) // Defensive programming: ensure index is good\r
537                         list_queue.Items[selectedIndex - 1].Selected = true;\r
538             }\r
539 \r
540             list_queue.Select(); // Activate the control to show the selected items\r
541         }\r
542 \r
543         /// <summary>\r
544         /// Move items down in the queue\r
545         /// </summary>\r
546         private void MoveDown()\r
547         {\r
548             // If there are selected items and the last item is not selected\r
549             if (list_queue.SelectedIndices.Count > 0 &&\r
550                 !list_queue.SelectedIndices.Contains(list_queue.Items[list_queue.Items.Count - 1].Index))\r
551             {\r
552                 // Copy the selected indices to preserve them during the movement\r
553                 List<int> selectedIndices = new List<int>(list_queue.SelectedIndices.Count);\r
554                 foreach (int selectedIndex in list_queue.SelectedIndices)\r
555                     selectedIndices.Add(selectedIndex);\r
556 \r
557                 // Reverse the indices to move the items down from last to first (preserves indices)\r
558                 selectedIndices.Reverse();\r
559 \r
560                 // Move down each selected item\r
561                 foreach (int selectedIndex in selectedIndices)\r
562                     queue.QueueManager.MoveDown(selectedIndex);\r
563 \r
564                 // Keep the selected item(s) selected, now moved down one index\r
565                 foreach (int selectedIndex in selectedIndices)\r
566                     if (selectedIndex + 1 < list_queue.Items.Count) // Defensive programming: ensure index is good\r
567                         list_queue.Items[selectedIndex + 1].Selected = true;\r
568             }\r
569 \r
570             list_queue.Select(); // Activate the control to show the selected items\r
571         }\r
572 \r
573         /// <summary>\r
574         /// Delete the currently selected items on the queue\r
575         /// </summary>\r
576         private void DeleteSelectedItems()\r
577         {\r
578             // If there are selected items\r
579             if (list_queue.SelectedIndices.Count > 0)\r
580             {\r
581                 // Remove each selected item\r
582                 foreach (ListViewItem selectedIndex in this.list_queue.SelectedItems)\r
583                     queue.QueueManager.Remove((QueueTask)selectedIndex.Tag);\r
584 \r
585                 // Select the first item after deletion.\r
586                 if (list_queue.Items.Count > 0)\r
587                     list_queue.Items[0].Selected = true;\r
588             }\r
589 \r
590             list_queue.Select(); // Activate the control to show the selected items\r
591         }\r
592 \r
593         /* Queue Import / Export features */\r
594 \r
595         /// <summary>\r
596         /// Create a batch script\r
597         /// </summary>\r
598         /// <param name="sender">\r
599         /// The sender.\r
600         /// </param>\r
601         /// <param name="e">\r
602         /// The e.\r
603         /// </param>\r
604         private void MnuBatchClick(object sender, EventArgs e)\r
605         {\r
606             SaveFile.FileName = string.Empty;\r
607             SaveFile.Filter = "Batch|.bat";\r
608             SaveFile.ShowDialog();\r
609             if (SaveFile.FileName != String.Empty)\r
610                 queue.QueueManager.WriteBatchScriptToFile(SaveFile.FileName);\r
611         }\r
612 \r
613         /// <summary>\r
614         /// Export Queue\r
615         /// </summary>\r
616         /// <param name="sender">\r
617         /// The sender.\r
618         /// </param>\r
619         /// <param name="e">\r
620         /// The e.\r
621         /// </param>\r
622         private void MnuExportClick(object sender, EventArgs e)\r
623         {\r
624             SaveFile.FileName = string.Empty;\r
625             SaveFile.Filter = "HandBrake Queue|*.queue";\r
626             SaveFile.ShowDialog();\r
627             if (SaveFile.FileName != String.Empty)\r
628                 queue.QueueManager.BackupQueue(SaveFile.FileName);\r
629         }\r
630 \r
631         /// <summary>\r
632         /// Import Queue\r
633         /// </summary>\r
634         /// <param name="sender">\r
635         /// The sender.\r
636         /// </param>\r
637         /// <param name="e">\r
638         /// The e.\r
639         /// </param>\r
640         private void MnuImportClick(object sender, EventArgs e)\r
641         {\r
642             OpenFile.FileName = string.Empty;\r
643             OpenFile.ShowDialog();\r
644             if (OpenFile.FileName != String.Empty)\r
645                 queue.QueueManager.RestoreQueue(OpenFile.FileName);\r
646         }\r
647 \r
648         /// <summary>\r
649         /// Readd current job to queue\r
650         /// </summary>\r
651         /// <param name="sender">\r
652         /// The sender.\r
653         /// </param>\r
654         /// <param name="e">\r
655         /// The e.\r
656         /// </param>\r
657         private void MnuReaddClick(object sender, EventArgs e)\r
658         {\r
659             if (queue.QueueManager.LastProcessedJob != null && !queue.QueueManager.LastProcessedJob.IsEmpty)\r
660             {\r
661                 queue.QueueManager.Add(queue.QueueManager.LastProcessedJob);\r
662             }\r
663         }\r
664 \r
665         /* Overrides */\r
666 \r
667         /// <summary>\r
668         /// Hide's the window when the user tries to "x" out of the window instead of closing it.\r
669         /// </summary>\r
670         /// <param name="e">\r
671         /// The e.\r
672         /// </param>\r
673         protected override void OnClosing(CancelEventArgs e)\r
674         {\r
675             e.Cancel = true;\r
676             this.Hide();\r
677             base.OnClosing(e);\r
678         }\r
679 \r
680         /// <summary>\r
681         /// Change the OnComplete option setting.\r
682         /// </summary>\r
683         /// <param name="sender">\r
684         /// The sender.\r
685         /// </param>\r
686         /// <param name="e">\r
687         /// The EventArgs.\r
688         /// </param>\r
689         private void CompleteOptionChanged(object sender, EventArgs e)\r
690         {\r
691             Properties.Settings.Default.CompletionOption = drp_completeOption.Text;\r
692             HandBrake.ApplicationServices.Init.CompletionOption = drp_completeOption.Text;\r
693             Properties.Settings.Default.Save();\r
694         }\r
695     }\r
696 }