OSDN Git Service

BuildSystem: fixed configure --debug + Xcode
[handbrake-jp/handbrake-jp-git.git] / macosx / HBOutputPanelController.m
1 /**
2  * @file
3  * @date 18.5.2007
4  *
5  * Implementation of class HBOutputPanelController.
6  */
7
8 #import "HBOutputPanelController.h"
9 #import "HBOutputRedirect.h"
10
11 /// Maximum amount of characters that can be shown in the view.
12 // Original value used by cleaner
13 //#define TextStorageUpperSizeLimit 20000
14 // lets use this higher value for now for better gui debugging
15 #define TextStorageUpperSizeLimit 40000
16
17 /// When old output is removed, this is the amount of characters that will be
18 /// left in outputTextStorage.
19 // Original value used by cleaner
20 //#define TextStorageLowerSizeLimit 15000
21 // lets use this higher value for now for better gui debugging
22 #define TextStorageLowerSizeLimit 35000
23
24 @implementation HBOutputPanelController
25
26 /**
27  * Initializes the object, creates outputTextStorage and starts redirection of stderr.
28  */
29 - (id)init
30 {
31     if( (self = [super initWithWindowNibName:@"OutputPanel"]) )
32     {
33         /* NSWindowController likes to lazily load its window nib. Since this
34          * controller tries to touch the outlets before accessing the window, we
35          * need to force it to load immadiately by invoking its accessor.
36          *
37          * If/when we switch to using bindings, this can probably go away.
38          */
39         [self window];
40
41         /* We initialize the outputTextStorage object for the activity window */
42         outputTextStorage = [[NSTextStorage alloc] init];
43
44         /* We declare the default NSFileManager into fileManager */
45         NSFileManager * fileManager = [NSFileManager defaultManager];
46         /* Establish the log file location to write to */
47         /* We are initially using a .txt file as opposed to a .log file since it will open by
48          * default with the users text editor instead of the .log default Console.app, should
49          * create less confusion for less experienced users when we ask them to paste the log for support
50          */
51         outputLogFile = @"~/Library/Application Support/HandBrake/HandBrake-activitylog.txt";
52         outputLogFile = [[outputLogFile stringByExpandingTildeInPath]retain];
53
54         /* We check for an existing output log file here */
55         if( [fileManager fileExistsAtPath:outputLogFile] == 0 )
56         {
57             /* if not, then we create a new blank one */
58             [fileManager createFileAtPath:outputLogFile contents:nil attributes:nil];
59         }
60         /* We overwrite the existing output log with the date for starters the output log to start fresh with the new session */
61         /* Use the current date and time for the new output log header */
62         NSString *startOutputLogString = [NSString stringWithFormat: @"HandBrake Activity Log for Session (Cleared): %@\n\n", [[NSDate  date] descriptionWithCalendarFormat:nil timeZone:nil locale:nil]];
63         [startOutputLogString writeToFile:outputLogFile atomically:YES encoding:NSUTF8StringEncoding error:NULL];
64
65         [[HBOutputRedirect stderrRedirect] addListener:self];
66         [[HBOutputRedirect stdoutRedirect] addListener:self];
67
68         [self setWindowFrameAutosaveName:@"OutputPanelFrame"];
69         [[textView layoutManager] replaceTextStorage:outputTextStorage];
70         [[textView enclosingScrollView] setLineScroll:10];
71         [[textView enclosingScrollView] setPageScroll:20];
72         
73         encodeLogOn = NO;
74     }
75     return self;
76 }
77
78 /**
79  * Stops redirection of stderr and releases resources.
80  */
81 - (void)dealloc
82 {
83     [[HBOutputRedirect stderrRedirect] removeListener:self];
84     [[HBOutputRedirect stdoutRedirect] removeListener:self];
85     [outputTextStorage release];
86     [super dealloc];
87 }
88
89 /**
90  * Loads output panel from OutputPanel.nib and shows it.
91  */
92 - (IBAction)showOutputPanel:(id)sender
93 {
94     if ([[self window] isVisible])
95     {
96         [[self window] close];
97     }
98     else
99     {
100     [textView scrollRangeToVisible:NSMakeRange([outputTextStorage length], 0)];
101     [self showWindow:sender];
102
103     [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"OutputPanelIsOpen"];
104     }
105 }
106
107 - (void) startEncodeLog:(NSString *) logPath
108 {
109     encodeLogOn = YES;
110     NSString *outputFileForEncode = logPath ;
111     /* Since the destination path matches the extension of the output file, replace the
112      * output movie extension and replace it with ".txt"
113      */
114     NSFileManager * fileManager = [NSFileManager defaultManager];
115     /* Establish the log file location to write to */
116     /* We are initially using a .txt file as opposed to a .log file since it will open by
117      * default with the users text editor instead of the .log default Console.app, should
118      * create less confusion for less experienced users when we ask them to paste the log for support
119      */
120     /* We need to get the current time in YY-MM-DD HH-MM-SS format to put at the beginning of the name of the log file */
121     time_t _now = time( NULL );
122     struct tm * now  = localtime( &_now );
123     NSString *dateForLogTitle = [NSString stringWithFormat:@"%02d-%02d-%02d %02d-%02d-%02d",now->tm_year + 1900, now->tm_mon + 1, now->tm_mday,now->tm_hour, now->tm_min, now->tm_sec]; 
124     
125     /* Assemble the new log file name as YY-MM-DD HH-MM-SS mymoviename.txt */
126     NSString *outputDateFileName = [NSString stringWithFormat:@"%@ %@.txt",dateForLogTitle,[[outputFileForEncode lastPathComponent] stringByDeletingPathExtension]];
127     if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EncodeLogLocation"]) // if we are putting it in the same directory with the movie
128     {
129         
130         outputLogFileForEncode = [[NSString stringWithFormat:@"%@/%@",[outputFileForEncode stringByDeletingLastPathComponent],outputDateFileName] retain];
131     }
132     else // if we are putting it in the default ~/Libraries/Application Support/HandBrake/EncodeLogs logs directory
133     {
134         NSString *libraryDir = [NSSearchPathForDirectoriesInDomains( NSLibraryDirectory,
135                                                                     NSUserDomainMask,
136                                                                     YES ) objectAtIndex:0];
137         NSString *encodeLogDirectory = [[[libraryDir stringByAppendingPathComponent:@"Application Support"] stringByAppendingPathComponent:@"HandBrake"] stringByAppendingPathComponent:@"EncodeLogs"];
138         if( ![[NSFileManager defaultManager] fileExistsAtPath:encodeLogDirectory] )
139         {
140             [[NSFileManager defaultManager] createDirectoryAtPath:encodeLogDirectory
141                                                        attributes:nil];
142         }
143         outputLogFileForEncode = [[NSString stringWithFormat:@"%@/%@",encodeLogDirectory,outputDateFileName] retain];   
144     }
145     [fileManager createFileAtPath:outputLogFileForEncode contents:nil attributes:nil];
146     
147     /* Similar to the regular activity log, we print a header containing the date and time of the encode as well as what directory it was encoded to */
148     NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)\n\n", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
149     NSString *startOutputLogString = [NSString stringWithFormat: @"HandBrake Activity Log for %@: %@\n%@",outputFileForEncode, [[NSDate  date] descriptionWithCalendarFormat:nil timeZone:nil locale:nil],versionStringFull];
150     [startOutputLogString writeToFile:outputLogFileForEncode atomically:YES encoding:NSUTF8StringEncoding error:NULL];
151
152
153 }
154
155 - (void) endEncodeLog
156 {
157     encodeLogOn = NO;
158 }
159
160 /**
161  * Displays text received from HBOutputRedirect in the text view.
162  */
163 - (void)stderrRedirect:(NSString *)text
164 {
165         
166     NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text];
167         /* Actually write the libhb output to the text view (outputTextStorage) */
168     [outputTextStorage appendAttributedString:attributedString];
169     [attributedString release];
170     
171         /* remove text from outputTextStorage as defined by TextStorageUpperSizeLimit and TextStorageLowerSizeLimit */
172     if ([outputTextStorage length] > TextStorageUpperSizeLimit)
173                 [outputTextStorage deleteCharactersInRange:NSMakeRange(0, [outputTextStorage length] - TextStorageLowerSizeLimit)];
174     
175     [textView scrollRangeToVisible:NSMakeRange([outputTextStorage length], 0)];
176     
177     /* We use a c function to write to the log file without reading it into memory 
178         * as it should be faster and easier on memory than using cocoa's writeToFile
179         * thanks ritsuka !!*/
180     FILE *f = fopen([outputLogFile UTF8String], "a");
181     fprintf(f, "%s", [text UTF8String]);
182     fclose(f);
183     
184     if (encodeLogOn == YES && outputLogFileForEncode != nil)
185     {
186     FILE *e = fopen([outputLogFileForEncode UTF8String], "a");
187     fprintf(e, "%s", [text UTF8String]);
188     fclose(e);
189     }
190     /* Below uses Objective-C to write to the file, though it is slow and uses
191         * more memory than the c function above. For now, leaving this in here
192         * just in case and commented out.
193     */
194     /* Put the new incoming string from libhb into an nsstring for appending to our log file */
195     //NSString *newOutputString = [[NSString alloc] initWithString:text];
196     /*get the current log file and put it into an NSString */
197     /* HACK ALERT: must be a way to do it without reading the whole log into memory 
198         Performance note: could batch write to the log, but want to get each line as it comes out of
199         libhb in case of a crash or freeze so we see exactly what the last thing was before crash*/
200     //NSString *currentOutputLogString = [[NSString alloc]initWithContentsOfFile:outputLogFile encoding:NSUTF8StringEncoding error:NULL];
201     
202     /* Append the new libhb output string to the existing log file string */
203     //currentOutputLogString = [currentOutputLogString stringByAppendingString:newOutputString];
204     /* Save the new modified log file string back to disk */
205     //[currentOutputLogString writeToFile:outputLogFile atomically:YES encoding:NSUTF8StringEncoding error:NULL];
206     /* Release the new libhb output string */
207     //[newOutputString release];
208 }
209 - (void)stdoutRedirect:(NSString *)text { [self stderrRedirect:text]; }
210
211 /**
212  * Clears the output window.
213  */
214 - (IBAction)clearOutput:(id)sender
215 {
216         [outputTextStorage deleteCharactersInRange:NSMakeRange(0, [outputTextStorage length])];
217     /* We want to rewrite the app version info to the top of the activity window so it is always present */
218     NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGetInfoString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
219     time_t _now = time( NULL );
220     struct tm * now  = localtime( &_now );
221     fprintf(stderr, "[%02d:%02d:%02d] macgui: %s\n", now->tm_hour, now->tm_min, now->tm_sec, [versionStringFull UTF8String]);
222     
223 }
224
225 /**
226  * Copies all text in the output window to pasteboard.
227  */
228 - (IBAction)copyAllOutputToPasteboard:(id)sender
229 {
230         NSPasteboard *pboard = [NSPasteboard generalPasteboard];
231         [pboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
232         [pboard setString:[outputTextStorage string] forType:NSStringPboardType];
233     
234 }
235
236 /**
237  * Opens the activity log txt file in users default editor.
238  */
239 - (IBAction)openActivityLogFile:(id)sender
240 {
241     /* Opens the activity window log file in the users default text editor */
242     NSAppleScript *myScript = [[NSAppleScript alloc] initWithSource: [NSString stringWithFormat: @"%@%@%@", @"tell application \"Finder\" to open (POSIX file \"", outputLogFile, @"\")"]];
243     [myScript executeAndReturnError: nil];
244     [myScript release];
245 }
246
247 /**
248  * Opens the activity log txt file in users default editor.
249  */
250 - (IBAction)openEncodeLogDirectory:(id)sender
251 {
252     /* Opens the activity window log file in the users default text editor */
253     NSString *libraryDir = [NSSearchPathForDirectoriesInDomains( NSLibraryDirectory,
254                                                                 NSUserDomainMask,
255                                                                 YES ) objectAtIndex:0];
256     NSString *encodeLogDirectory = [[[libraryDir stringByAppendingPathComponent:@"Application Support"] stringByAppendingPathComponent:@"HandBrake"] stringByAppendingPathComponent:@"EncodeLogs"];
257     if( ![[NSFileManager defaultManager] fileExistsAtPath:encodeLogDirectory] )
258     {
259         [[NSFileManager defaultManager] createDirectoryAtPath:encodeLogDirectory
260                                                    attributes:nil];
261     }
262     
263     NSAppleScript *myScript = [[NSAppleScript alloc] initWithSource: [NSString stringWithFormat: @"%@%@%@", @"tell application \"Finder\" to open (POSIX file \"", encodeLogDirectory, @"\")"]];
264     [myScript executeAndReturnError: nil];
265     [myScript release];
266 }
267
268 - (IBAction)clearActivityLogFile:(id)sender
269 {
270     /* We overwrite the existing output log with the new date and time header */
271         /* Use the current date and time for the new output log header */
272         NSString *startOutputLogString = [NSString stringWithFormat: @"HandBrake Activity Log for Session Starting: %@\n\n", [[NSDate  date] descriptionWithCalendarFormat:nil timeZone:nil locale:nil]];
273         [startOutputLogString writeToFile:outputLogFile atomically:NO encoding:NSUTF8StringEncoding error:NULL];
274         
275         /* We want to rewrite the app version info to the top of the activity window so it is always present */
276         NSString *versionStringFull = [[NSString stringWithFormat: @"macgui: Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGetInfoString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
277         [versionStringFull writeToFile:outputLogFile atomically:NO encoding:NSUTF8StringEncoding error:NULL];
278         
279 }
280
281 - (void)windowWillClose:(NSNotification *)aNotification
282 {
283     [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"OutputPanelIsOpen"];
284 }
285
286
287 @end