summaryrefslogtreecommitdiffstats
path: root/macosx/HBOutputPanelController.m
blob: d91379a2ff16b9779c8f579ebc6e8b2cf9a8e781 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/**
 * @file
 * @date 18.5.2007
 *
 * Implementation of class HBOutputPanelController.
 */

#import "HBOutputPanelController.h"
#import "HBOutputRedirect.h"

/// Maximum amount of characters that can be shown in the view.
// Original value used by cleaner
//#define TextStorageUpperSizeLimit 20000
// lets use this higher value for now for better gui debugging
#define TextStorageUpperSizeLimit 40000

/// When old output is removed, this is the amount of characters that will be
/// left in outputTextStorage.
// Original value used by cleaner
//#define TextStorageLowerSizeLimit 15000
// lets use this higher value for now for better gui debugging
#define TextStorageLowerSizeLimit 35000

@implementation HBOutputPanelController

/**
 * Initializes the object, creates outputTextStorage and starts redirection of stderr.
 */
- (id)init
{
	if (self = [super init])
	{
		/* We initialize the outputTextStorage object for the activity window */
        outputTextStorage = [[NSTextStorage alloc] init];
        
        /* We declare the default NSFileManager into fileManager */
        NSFileManager * fileManager = [NSFileManager defaultManager];
        /* Establish the log file location to write to */
        /* We are initially using a .txt file as opposed to a .log file since it will open by
            * default with the users text editor instead of the .log default Console.app, should
        * create less confusion for less experienced users when we ask them to paste the log for support
            */
        outputLogFile = @"~/Library/Application Support/HandBrake/HandBrake-activitylog.txt";
        outputLogFile = [[outputLogFile stringByExpandingTildeInPath]retain];
        
        /* We check for an existing output log file here */
        if ([fileManager fileExistsAtPath:outputLogFile] == 0) 
        {
            /* if not, then we create a new blank one */
            [fileManager createFileAtPath:outputLogFile contents:nil attributes:nil];
        }
        /* We overwrite the existing output log with the date for starters the output log to start fresh with the new session */
        /* Use the current date and time for the new output log header */
        NSString *startOutputLogString = [NSString stringWithFormat: @"HandBrake Activity Log for Session (Cleared): %@\n\n", [[NSDate  date] descriptionWithCalendarFormat:nil timeZone:nil locale:nil]];
        
        [startOutputLogString writeToFile:outputLogFile atomically:YES encoding:NSUTF8StringEncoding error:NULL];
        
		[[HBOutputRedirect stderrRedirect] addListener:self];
		[[HBOutputRedirect stdoutRedirect] addListener:self];
        
        
	}
	return self;
}

/**
 * Stops redirection of stderr and releases resources.
 */
- (void)dealloc
{
	[[HBOutputRedirect stderrRedirect] removeListener:self];
	[[HBOutputRedirect stdoutRedirect] removeListener:self];	
	[outputTextStorage release];
	[outputPanel release];
	[super dealloc];
}

/**
 * Loads output panel from OutputPanel.nib and shows it.
 */
- (IBAction)showOutputPanel:(id)sender
{
	if (!outputPanel)
	{
		BOOL loadSucceeded = [NSBundle loadNibNamed:@"OutputPanel" owner:self] && outputPanel;
		NSAssert(loadSucceeded, @"Could not open nib file");
		
		[outputPanel setFrameAutosaveName:@"OutputPanelFrame"];
		[[textView layoutManager] replaceTextStorage:outputTextStorage];
		[[textView enclosingScrollView] setLineScroll:10];
		[[textView enclosingScrollView] setPageScroll:20];
	}
		
    [textView scrollRangeToVisible:NSMakeRange([outputTextStorage length], 0)];
	[outputPanel orderFront:nil];

    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"OutputPanelIsOpen"];
}

/**
 * Displays text received from HBOutputRedirect in the text view.
 */
- (void)stderrRedirect:(NSString *)text
{
	
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text];
	/* Actually write the libhb output to the text view (outputTextStorage) */
    [outputTextStorage appendAttributedString:attributedString];
    [attributedString release];
    
	/* remove text from outputTextStorage as defined by TextStorageUpperSizeLimit and TextStorageLowerSizeLimit */
    if ([outputTextStorage length] > TextStorageUpperSizeLimit)
		[outputTextStorage deleteCharactersInRange:NSMakeRange(0, [outputTextStorage length] - TextStorageLowerSizeLimit)];
    
    [textView scrollRangeToVisible:NSMakeRange([outputTextStorage length], 0)];
    
    /* We use a c function to write to the log file without reading it into memory 
        * as it should be faster and easier on memory than using cocoa's writeToFile
        * thanks ritsuka !!*/
    FILE *f = fopen([outputLogFile UTF8String], "a");
    fprintf(f, "%s", [text UTF8String]);
    fclose(f);
    
    
    /* Below uses Objective-C to write to the file, though it is slow and uses
        * more memory than the c function above. For now, leaving this in here
        * just in case and commented out.
    */
    /* Put the new incoming string from libhb into an nsstring for appending to our log file */
    //NSString *newOutputString = [[NSString alloc] initWithString:text];
    /*get the current log file and put it into an NSString */
    /* HACK ALERT: must be a way to do it without reading the whole log into memory 
        Performance note: could batch write to the log, but want to get each line as it comes out of
        libhb in case of a crash or freeze so we see exactly what the last thing was before crash*/
    //NSString *currentOutputLogString = [[NSString alloc]initWithContentsOfFile:outputLogFile encoding:NSUTF8StringEncoding error:NULL];
    
    /* Append the new libhb output string to the existing log file string */
    //currentOutputLogString = [currentOutputLogString stringByAppendingString:newOutputString];
    /* Save the new modified log file string back to disk */
    //[currentOutputLogString writeToFile:outputLogFile atomically:YES encoding:NSUTF8StringEncoding error:NULL];
    /* Release the new libhb output string */
    //[newOutputString release];
}
- (void)stdoutRedirect:(NSString *)text { [self stderrRedirect:text]; }

/**
 * Clears the output window.
 */
- (IBAction)clearOutput:(id)sender
{
	[outputTextStorage deleteCharactersInRange:NSMakeRange(0, [outputTextStorage length])];
    /* We want to rewrite the app version info to the top of the activity window so it is always present */
    NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGetInfoString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
    time_t _now = time( NULL );
    struct tm * now  = localtime( &_now );
    fprintf(stderr, "[%02d:%02d:%02d] macgui: %s\n", now->tm_hour, now->tm_min, now->tm_sec, [versionStringFull UTF8String]);
    
}

/**
 * Copies all text in the output window to pasteboard.
 */
- (IBAction)copyAllOutputToPasteboard:(id)sender
{
	NSPasteboard *pboard = [NSPasteboard generalPasteboard];
	[pboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
	[pboard setString:[outputTextStorage string] forType:NSStringPboardType];
    
}

/**
 * Opens the activity log txt file in users default editor.
 */
- (IBAction)openActivityLogFile:(id)sender
{
    /* Opens the activity window log file in the users default text editor */
    NSAppleScript *myScript = [[NSAppleScript alloc] initWithSource: [NSString stringWithFormat: @"%@%@%@", @"tell application \"Finder\" to open (POSIX file \"", outputLogFile, @"\")"]];
    [myScript executeAndReturnError: nil];
    [myScript release];
}

- (IBAction)clearActivityLogFile:(id)sender
{
    /* We overwrite the existing output log with the new date and time header */
        /* Use the current date and time for the new output log header */
        NSString *startOutputLogString = [NSString stringWithFormat: @"HandBrake Activity Log for Session Starting: %@\n\n", [[NSDate  date] descriptionWithCalendarFormat:nil timeZone:nil locale:nil]];
        [startOutputLogString writeToFile:outputLogFile atomically:NO encoding:NSUTF8StringEncoding error:NULL];
        
        /* We want to rewrite the app version info to the top of the activity window so it is always present */
        NSString *versionStringFull = [[NSString stringWithFormat: @"macgui: Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGetInfoString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
        [versionStringFull writeToFile:outputLogFile atomically:NO encoding:NSUTF8StringEncoding error:NULL];
        
}

- (void)windowWillClose:(NSNotification *)aNotification
{
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"OutputPanelIsOpen"];
}


@end