OSDN Git Service

CLI: update the built in presets
[handbrake-jp/handbrake-jp-git.git] / win / C# / HandBrake.ApplicationServices / Services / Scan.cs
1 /*  Scan.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.ApplicationServices.Services\r
7 {\r
8     using System;\r
9     using System.Diagnostics;\r
10     using System.IO;\r
11     using System.Text;\r
12     using System.Threading;\r
13     using System.Windows.Forms;\r
14 \r
15     using HandBrake.Framework.Services;\r
16     using HandBrake.Framework.Services.Interfaces;\r
17     using HandBrake.ApplicationServices.Functions;\r
18     using HandBrake.ApplicationServices.Parsing;\r
19     using HandBrake.ApplicationServices.Services.Interfaces;\r
20 \r
21     /// <summary>\r
22     /// Scan a Source\r
23     /// </summary>\r
24     public class ScanService : IScan\r
25     {\r
26         /* Private Variables */\r
27 \r
28         /// <summary>\r
29         /// The Error Service\r
30         /// </summary>\r
31         private readonly IErrorService errorService;\r
32 \r
33         /// <summary>\r
34         /// A Lock object\r
35         /// </summary>\r
36         private static readonly object locker = new object();\r
37 \r
38         /// <summary>\r
39         /// The CLI data parser\r
40         /// </summary>\r
41         private Parser readData;\r
42 \r
43         /// <summary>\r
44         /// The Log Buffer\r
45         /// </summary>\r
46         private StringBuilder logBuffer;\r
47 \r
48         /// <summary>\r
49         /// The line number thats been read to in the log file\r
50         /// </summary>\r
51         private int logFilePosition;\r
52 \r
53         /// <summary>\r
54         /// The Process belonging to the CLI\r
55         /// </summary>\r
56         private Process hbProc;\r
57 \r
58         /// <summary>\r
59         /// Initializes a new instance of the <see cref="ScanService"/> class.\r
60         /// </summary>\r
61         public ScanService()\r
62         {\r
63             this.errorService = new ErrorService();\r
64         }\r
65 \r
66         /* Event Handlers */\r
67 \r
68         /// <summary>\r
69         /// Scan has Started\r
70         /// </summary>\r
71         public event EventHandler ScanStared;\r
72 \r
73         /// <summary>\r
74         /// Scan has completed\r
75         /// </summary>\r
76         public event EventHandler ScanCompleted;\r
77 \r
78         /// <summary>\r
79         /// Scan process has changed to a new title\r
80         /// </summary>\r
81         public event EventHandler ScanStatusChanged;\r
82 \r
83         /* Properties */\r
84 \r
85         /// <summary>\r
86         /// Gets a value indicating whether IsScanning.\r
87         /// </summary>\r
88         public bool IsScanning { get; private set; }\r
89 \r
90         /// <summary>\r
91         /// Gets the Scan Status.\r
92         /// </summary>\r
93         public string ScanStatus { get; private set; }\r
94 \r
95         /// <summary>\r
96         /// Gets the Souce Data.\r
97         /// </summary>\r
98         public DVD SouceData { get; private set; }\r
99 \r
100         /// <summary>\r
101         /// Gets ActivityLog.\r
102         /// </summary>\r
103         public string ActivityLog\r
104         {\r
105             get\r
106             {\r
107                 if (IsScanning)\r
108                     return readData.Buffer.ToString();\r
109 \r
110                 if (logBuffer == null)\r
111                 {\r
112                     ResetLogReader(false);\r
113                     ReadLastScanFile();  \r
114                 }\r
115 \r
116                 return logBuffer != null ? logBuffer.ToString() : string.Empty;\r
117             }\r
118         }\r
119 \r
120         /* Public Methods */\r
121 \r
122         /// <summary>\r
123         /// Scan a Source Path.\r
124         /// Title 0: scan all\r
125         /// </summary>\r
126         /// <param name="sourcePath">Path to the file to scan</param>\r
127         /// <param name="title">int title number. 0 for scan all</param>\r
128         public void Scan(string sourcePath, int title)\r
129         {\r
130             Thread t = new Thread(unused => this.ScanSource(sourcePath, title));\r
131             t.Start();\r
132         }\r
133 \r
134         /// <summary>\r
135         /// Kill the scan\r
136         /// </summary>\r
137         public void Stop()\r
138         {\r
139             try\r
140             {\r
141                 this.readData.OnScanProgress -= this.OnScanProgress;\r
142 \r
143                 if (hbProc != null && !hbProc.HasExited)\r
144                     hbProc.Kill();\r
145             }\r
146             catch (Exception ex)\r
147             {\r
148                 errorService.ShowError("Unable to kill HandBrakeCLI.exe \n" +\r
149                 "You may need to manually kill HandBrakeCLI.exe using the Windows Task Manager if it does not close automatically" + \r
150                 " within the next few minutes. ", ex.ToString());\r
151             }\r
152         }\r
153 \r
154         /* Private Methods */\r
155 \r
156         /// <summary>\r
157         /// Start a scan for a given source path and title\r
158         /// </summary>\r
159         /// <param name="sourcePath">Path to the source file</param>\r
160         /// <param name="title">the title number to look at</param>\r
161         private void ScanSource(object sourcePath, int title)\r
162         {\r
163             try\r
164             {\r
165                 IsScanning = true;\r
166                 if (this.ScanStared != null)\r
167                     this.ScanStared(this, new EventArgs());\r
168 \r
169                 ResetLogReader(true);\r
170 \r
171                 string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");\r
172                 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +\r
173                                 "\\HandBrake\\logs";\r
174                 string dvdInfoPath = Path.Combine(logDir, string.Format("last_scan_log{0}.txt", Init.InstanceId == 0 ? string.Empty : Init.InstanceId.ToString()));\r
175 \r
176                 // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file)\r
177                 if (File.Exists(dvdInfoPath))\r
178                     File.Delete(dvdInfoPath);\r
179 \r
180                 string extraArguments = string.Empty;\r
181                 if (Init.DisableDvdNav)\r
182                     extraArguments = " --no-dvdnav";\r
183 \r
184                 if (title > 0)\r
185                     extraArguments += " --scan ";\r
186 \r
187                 this.hbProc = new Process\r
188                                   {\r
189                                       StartInfo =\r
190                                           {\r
191                                               FileName = handbrakeCLIPath,\r
192                                               Arguments =\r
193                                                   String.Format(@" -i ""{0}"" -t{1} {2} -v ", sourcePath, title,\r
194                                                                 extraArguments),\r
195                                               RedirectStandardOutput = true,\r
196                                               RedirectStandardError = true,\r
197                                               UseShellExecute = false,\r
198                                               CreateNoWindow = true\r
199                                           }\r
200                                   };\r
201 \r
202                 // Start the Scan\r
203                 this.hbProc.Start();\r
204 \r
205                 this.readData = new Parser(this.hbProc.StandardError.BaseStream);\r
206                 this.readData.OnScanProgress += this.OnScanProgress;\r
207                 this.SouceData = DVD.Parse(this.readData);\r
208 \r
209                 // Write the Buffer out to file.\r
210                 using (StreamWriter scanLog = new StreamWriter(dvdInfoPath))\r
211                 {\r
212                     // Only write the log file to disk if it's less than 100MB.\r
213                     if (this.readData.Buffer.Length < 100000000)\r
214                     {\r
215                         scanLog.WriteLine(Logging.CreateCliLogHeader(null));\r
216                         scanLog.Write(this.readData.Buffer);\r
217                         logBuffer.AppendLine(this.readData.Buffer.ToString());\r
218                     }\r
219                     else\r
220                     {\r
221                         throw new Exception(\r
222                             "The Log file has not been written to disk as it has grown above the 100MB limit. This indicates there was a problem during the scan process.");\r
223                     }\r
224                 }\r
225 \r
226                 IsScanning = false;\r
227 \r
228                 if (this.ScanCompleted != null)\r
229                     this.ScanCompleted(this, new EventArgs()); \r
230             }\r
231             catch (Exception exc)\r
232             {\r
233                 this.Stop();\r
234 \r
235                 errorService.ShowError("An error has occured during the scan process.", exc.ToString());\r
236 \r
237                 if (this.ScanCompleted != null)\r
238                     this.ScanCompleted(this, new EventArgs());   \r
239             }\r
240         }\r
241 \r
242         /// <summary>\r
243         /// Read the log file\r
244         /// </summary>\r
245         private void ReadLastScanFile()\r
246         {\r
247             lock (locker)\r
248             {\r
249                 // last_encode_log.txt is the primary log file. Since .NET can't read this file whilst the CLI is outputing to it (Not even in read only mode),\r
250                 // we'll need to make a copy of it.\r
251                 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +\r
252                                 "\\HandBrake\\logs";\r
253                 string logFile = Path.Combine(logDir, string.Format("last_scan_log{0}.txt", Init.InstanceId == 0 ? string.Empty : Init.InstanceId.ToString()));\r
254                 string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", Init.InstanceId == 0 ? string.Empty : Init.InstanceId.ToString()));\r
255 \r
256                 try\r
257                 {\r
258                     // Make sure the application readable log file does not already exist. FileCopy fill fail if it does.\r
259                     if (File.Exists(logFile2))\r
260                         File.Delete(logFile2);\r
261 \r
262                     // Copy the log file.\r
263                     if (File.Exists(logFile))\r
264                         File.Copy(logFile, logFile2, true);\r
265                     else\r
266                     {\r
267                         ResetLogReader(true);\r
268                         return;\r
269                     }\r
270 \r
271                     // Start the Reader\r
272                     // Only use text which continues on from the last read line\r
273                     StreamReader sr = new StreamReader(logFile2);\r
274                     string line;\r
275                     int i = 1;\r
276                     while ((line = sr.ReadLine()) != null)\r
277                     {\r
278                         if (i > logFilePosition)\r
279                         {\r
280                             logBuffer.AppendLine(line);\r
281                             logFilePosition++;\r
282                         }\r
283                         i++;\r
284                     }\r
285                     sr.Close();\r
286                     sr.Dispose();\r
287                 }\r
288                 catch (Exception exc)\r
289                 {\r
290                     Console.WriteLine(exc.ToString());\r
291                     ResetLogReader(true);\r
292                 }\r
293             }\r
294         }\r
295 \r
296         /// <summary>\r
297         /// Reset the Log Reader\r
298         /// </summary>\r
299         /// <param name="addHeader">\r
300         /// The add Header.\r
301         /// </param>\r
302         private void ResetLogReader(bool addHeader)\r
303         {\r
304             logFilePosition = 0;\r
305             logBuffer = new StringBuilder();\r
306             if (addHeader)\r
307                 logBuffer.AppendLine(Logging.CreateCliLogHeader(null));\r
308         }\r
309 \r
310         /// <summary>\r
311         /// Fire an event when the scan process progresses\r
312         /// </summary>\r
313         /// <param name="sender">the sender</param>\r
314         /// <param name="currentTitle">the current title being scanned</param>\r
315         /// <param name="titleCount">the total number of titles</param>\r
316         private void OnScanProgress(object sender, int currentTitle, int titleCount)\r
317         {\r
318             this.ScanStatus = string.Format("Processing Title: {0} of {1}", currentTitle, titleCount);\r
319             if (this.ScanStatusChanged != null)\r
320                 this.ScanStatusChanged(this, new EventArgs());\r
321         }\r
322     }\r
323 }