OSDN Git Service

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