OSDN Git Service

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