OSDN Git Service

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