OSDN Git Service

merge 0.9.4 to jp
[handbrake-jp/handbrake-jp.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: NSLocalizedStringFromTable(@"HandBrake Activity Log for Session (Cleared): %@\n\n", @"OutputPanel", @""), [[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",[[outputFileForEncode lastPathComponent] stringByDeletingPathExtension],dateForLogTitle];
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                                             withIntermediateDirectories:NO
142                                             attributes:nil
143                                             error:nil];
144         }
145         outputLogFileForEncode = [[NSString stringWithFormat:@"%@/%@",encodeLogDirectory,outputDateFileName] retain];   
146     }
147     [fileManager createFileAtPath:outputLogFileForEncode contents:nil attributes:nil];
148     
149     /* 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 */
150     /*
151     NSString *versionStringFull = [[NSString stringWithFormat: NSLocalizedStringFromTable(@"Handbrake Version: %@", @"OutputPanel", @""), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGetInfoString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)\n\n", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
152     NSString *startOutputLogString = [NSString stringWithFormat: NSLocalizedStringFromTable(@"HandBrake Activity Log for %@: %@\n%@", @"OutputPanel", @""),outputFileForEncode, [[NSDate  date] descriptionWithCalendarFormat:nil timeZone:nil locale:nil],versionStringFull];
153     */
154     NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)\n\n", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
155     NSString *startOutputLogString = [NSString stringWithFormat: @"HandBrake Activity Log for %@: %@\n%@",outputFileForEncode, [[NSDate  date] descriptionWithCalendarFormat:nil timeZone:nil locale:nil],versionStringFull];
156     [startOutputLogString writeToFile:outputLogFileForEncode atomically:YES encoding:NSUTF8StringEncoding error:NULL];
157
158
159 }
160
161 - (void) endEncodeLog
162 {
163     encodeLogOn = NO;
164 }
165
166 /**
167  * Displays text received from HBOutputRedirect in the text view.
168  */
169 - (void)stderrRedirect:(NSString *)text
170 {
171         
172     NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text];
173         /* Actually write the libhb output to the text view (outputTextStorage) */
174     [outputTextStorage appendAttributedString:attributedString];
175     [attributedString release];
176     
177         /* remove text from outputTextStorage as defined by TextStorageUpperSizeLimit and TextStorageLowerSizeLimit */
178     if ([outputTextStorage length] > TextStorageUpperSizeLimit)
179                 [outputTextStorage deleteCharactersInRange:NSMakeRange(0, [outputTextStorage length] - TextStorageLowerSizeLimit)];
180     
181     [textView scrollRangeToVisible:NSMakeRange([outputTextStorage length], 0)];
182     
183     /* We use a c function to write to the log file without reading it into memory 
184         * as it should be faster and easier on memory than using cocoa's writeToFile
185         * thanks ritsuka !!*/
186     FILE *f = fopen([outputLogFile UTF8String], "a");
187     fprintf(f, "%s", [text UTF8String]);
188     fclose(f);
189     
190     if (encodeLogOn == YES && outputLogFileForEncode != nil)
191     {
192     FILE *e = fopen([outputLogFileForEncode UTF8String], "a");
193     fprintf(e, "%s", [text UTF8String]);
194     fclose(e);
195     }
196     /* Below uses Objective-C to write to the file, though it is slow and uses
197         * more memory than the c function above. For now, leaving this in here
198         * just in case and commented out.
199     */
200     /* Put the new incoming string from libhb into an nsstring for appending to our log file */
201     //NSString *newOutputString = [[NSString alloc] initWithString:text];
202     /*get the current log file and put it into an NSString */
203     /* HACK ALERT: must be a way to do it without reading the whole log into memory 
204         Performance note: could batch write to the log, but want to get each line as it comes out of
205         libhb in case of a crash or freeze so we see exactly what the last thing was before crash*/
206     //NSString *currentOutputLogString = [[NSString alloc]initWithContentsOfFile:outputLogFile encoding:NSUTF8StringEncoding error:NULL];
207     
208     /* Append the new libhb output string to the existing log file string */
209     //currentOutputLogString = [currentOutputLogString stringByAppendingString:newOutputString];
210     /* Save the new modified log file string back to disk */
211     //[currentOutputLogString writeToFile:outputLogFile atomically:YES encoding:NSUTF8StringEncoding error:NULL];
212     /* Release the new libhb output string */
213     //[newOutputString release];
214 }
215 - (void)stdoutRedirect:(NSString *)text { [self stderrRedirect:text]; }
216
217 /**
218  * Clears the output window.
219  */
220 - (IBAction)clearOutput:(id)sender
221 {
222         [outputTextStorage deleteCharactersInRange:NSMakeRange(0, [outputTextStorage length])];
223     /* We want to rewrite the app version info to the top of the activity window so it is always present */
224         /*
225     NSString *versionStringFull = [[NSString stringWithFormat: NSLocalizedStringFromTable(@"Handbrake Version: %@", @"OutputPanel", @""), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGetInfoString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
226         */
227     NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)\n\n", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
228     time_t _now = time( NULL );
229     struct tm * now  = localtime( &_now );
230     fprintf(stderr, "[%02d:%02d:%02d] macgui: %s\n", now->tm_hour, now->tm_min, now->tm_sec, [versionStringFull UTF8String]);
231
232 }
233
234 /**
235  * Copies all text in the output window to pasteboard.
236  */
237 - (IBAction)copyAllOutputToPasteboard:(id)sender
238 {
239         NSPasteboard *pboard = [NSPasteboard generalPasteboard];
240         [pboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
241         [pboard setString:[outputTextStorage string] forType:NSStringPboardType];
242     
243 }
244
245 /**
246  * Opens the activity log txt file in users default editor.
247  */
248 - (IBAction)openActivityLogFile:(id)sender
249 {
250     /* Opens the activity window log file in the users default text editor */
251     NSAppleScript *myScript = [[NSAppleScript alloc] initWithSource: [NSString stringWithFormat: @"%@%@%@", NSLocalizedStringFromTable(@"tell application \"Finder\" to open (POSIX file \"", @"OutputPanel", @""), outputLogFile, @"\")"]];
252     [myScript executeAndReturnError: nil];
253     [myScript release];
254 }
255
256 /**
257  * Opens the activity log txt file in users default editor.
258  */
259 - (IBAction)openEncodeLogDirectory:(id)sender
260 {
261     /* Opens the activity window log file in the users default text editor */
262     NSString *libraryDir = [NSSearchPathForDirectoriesInDomains( NSLibraryDirectory,
263                                                                 NSUserDomainMask,
264                                                                 YES ) objectAtIndex:0];
265     NSString *encodeLogDirectory = [[[libraryDir stringByAppendingPathComponent:@"Application Support"] stringByAppendingPathComponent:@"HandBrake"] stringByAppendingPathComponent:@"EncodeLogs"];
266     if( ![[NSFileManager defaultManager] fileExistsAtPath:encodeLogDirectory] )
267     {
268         [[NSFileManager defaultManager] createDirectoryAtPath:encodeLogDirectory
269                                             withIntermediateDirectories:NO
270                                             attributes:nil
271                                             error:nil];
272     }
273     
274     NSAppleScript *myScript = [[NSAppleScript alloc] initWithSource: [NSString stringWithFormat: @"%@%@%@", NSLocalizedStringFromTable(@"tell application \"Finder\" to open (POSIX file \"", @"OutputPanel", @""), encodeLogDirectory, @"\")"]];
275     [myScript executeAndReturnError: nil];
276     [myScript release];
277 }
278
279 - (IBAction)clearActivityLogFile:(id)sender
280 {
281     /* We overwrite the existing output log with the new date and time header */
282         /* Use the current date and time for the new output log header */
283         NSString *startOutputLogString = [NSString stringWithFormat: NSLocalizedStringFromTable(@"HandBrake Activity Log for Session Starting: %@\n\n", @"OutputPanel", @""), [[NSDate  date] descriptionWithCalendarFormat:nil timeZone:nil locale:nil]];
284         [startOutputLogString writeToFile:outputLogFile atomically:NO encoding:NSUTF8StringEncoding error:NULL];
285         
286         /* We want to rewrite the app version info to the top of the activity window so it is always present */
287         /*
288         NSString *versionStringFull = [[NSString stringWithFormat: NSLocalizedStringFromTable(@"macgui: Handbrake Version: %@", @"OutputPanel", @""), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGetInfoString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
289         */
290         NSString *versionStringFull = [[NSString stringWithFormat: @"macgui: Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)\n\n", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
291         [versionStringFull writeToFile:outputLogFile atomically:NO encoding:NSUTF8StringEncoding error:NULL];
292         
293 }
294
295 - (void)windowWillClose:(NSNotification *)aNotification
296 {
297     [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"OutputPanelIsOpen"];
298 }
299
300
301 @end