OSDN Git Service

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