1 /*****************************************************************************
2 * DebugMessageVisualizer.m: Mac OS X interface crash reporter
3 *****************************************************************************
4 * Copyright (C) 2004-2013 VLC authors and VideoLAN
7 * Authors: Felix Paul Kühne <fkuehne at videolan dot org>
8 * Pierre d'Herbemont <pdherbemont # videolan org>
9 * Derk-Jan Hartman <hartman at videolan.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 #import "DebugMessageVisualizer.h"
28 #import <vlc_common.h>
30 static void MsgCallback(void *data, int type, const vlc_log_t *item, const char *format, va_list ap);
32 /*****************************************************************************
33 * MsgCallback: Callback triggered by the core once a new debug message is
34 * ready to be displayed. We store everything in a NSArray in our Cocoa part
36 *****************************************************************************/
38 @interface VLCDebugMessageVisualizer () <NSWindowDelegate>
40 NSMutableArray * _msg_arr;
43 - (void)processReceivedlibvlcMessage:(const vlc_log_t *) item ofType: (int)i_type withStr: (char *)str;
47 static void MsgCallback(void *data, int type, const vlc_log_t *item, const char *format, va_list ap)
49 int canc = vlc_savecancel();
52 if (vasprintf(&str, format, ap) == -1) {
53 vlc_restorecancel(canc);
57 NSAutoreleasePool *_pool = [[NSAutoreleasePool alloc] init];
58 [[VLCDebugMessageVisualizer sharedInstance] processReceivedlibvlcMessage: item ofType: type withStr: str];
61 vlc_restorecancel(canc);
65 @implementation VLCDebugMessageVisualizer
67 static VLCDebugMessageVisualizer *_sharedMainInstance = nil;
69 + (VLCDebugMessageVisualizer *)sharedInstance
71 return _sharedMainInstance ? _sharedMainInstance : [[self alloc] init];
76 if (_sharedMainInstance)
79 _sharedMainInstance = [super init];
80 _msg_lock = [[NSLock alloc] init];
81 _msg_arr = [[NSMutableArray arrayWithCapacity:600] retain];
82 BOOL loaded = [NSBundle loadNibNamed:@"DebugMessageVisualizer" owner:self];
85 return _sharedMainInstance;
90 [_msgs_panel setExcludedFromWindowsMenu: YES];
91 [_msgs_panel setDelegate: self];
92 [_msgs_panel setTitle: _NS("Messages")];
93 [_msgs_save_btn setTitle: _NS("Save this Log...")];
94 [_msgs_refresh_btn setImage: [NSImage imageNamed: NSImageNameRefreshTemplate]];
99 [_msg_arr removeAllObjects];
108 #pragma mark - UI interaction
112 /* subscribe to LibVLCCore's messages */
113 vlc_LogSet(VLCIntf->p_libvlc, MsgCallback, NULL);
116 [_msgs_panel makeKeyAndOrderFront:nil];
119 - (IBAction)updateMessagesPanel:(id)sender
121 [self windowDidBecomeKey:nil];
124 - (void)windowDidBecomeKey:(NSNotification *)notification
126 [_msgs_table reloadData];
127 [_msgs_table scrollRowToVisible: [_msg_arr count] - 1];
130 - (void)windowWillClose:(NSNotification *)notification
132 /* unsubscribe from LibVLCCore's messages */
133 vlc_LogSet( VLCIntf->p_libvlc, NULL, NULL );
136 - (IBAction)saveDebugLog:(id)sender
138 NSSavePanel * saveFolderPanel = [[NSSavePanel alloc] init];
140 [saveFolderPanel setCanSelectHiddenExtension: NO];
141 [saveFolderPanel setCanCreateDirectories: YES];
142 [saveFolderPanel setAllowedFileTypes: [NSArray arrayWithObject:@"rtf"]];
143 [saveFolderPanel setNameFieldStringValue:[NSString stringWithFormat: _NS("VLC Debug Log (%s).rtf"), VERSION_MESSAGE]];
144 [saveFolderPanel beginSheetModalForWindow: _msgs_panel completionHandler:^(NSInteger returnCode) {
145 if (returnCode == NSOKButton) {
146 NSUInteger count = [_msg_arr count];
147 NSMutableAttributedString * string = [[NSMutableAttributedString alloc] init];
148 for (NSUInteger i = 0; i < count; i++)
149 [string appendAttributedString: [_msg_arr objectAtIndex:i]];
151 NSData *data = [string RTFFromRange:NSMakeRange(0, [string length])
152 documentAttributes:[NSDictionary dictionaryWithObject: NSRTFTextDocumentType forKey: NSDocumentTypeDocumentAttribute]];
154 if ([data writeToFile: [[saveFolderPanel URL] path] atomically: YES] == NO)
155 msg_Warn(VLCIntf, "Error while saving the debug log");
160 [saveFolderPanel release];
163 #pragma mark - data handling
165 - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
167 if (aTableView == _msgs_table)
168 return [_msg_arr count];
172 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
174 NSMutableAttributedString *result = NULL;
177 if (rowIndex < [_msg_arr count])
178 result = [_msg_arr objectAtIndex:rowIndex];
187 - (void)processReceivedlibvlcMessage:(const vlc_log_t *) item ofType: (int)i_type withStr: (char *)str
190 NSColor *_white = [NSColor whiteColor];
191 NSColor *_red = [NSColor redColor];
192 NSColor *_yellow = [NSColor yellowColor];
193 NSColor *_gray = [NSColor grayColor];
194 NSString * firstString, * secondString;
196 NSColor * pp_color[4] = { _white, _red, _yellow, _gray };
197 static const char * ppsz_type[4] = { ": ", " error: ", " warning: ", " debug: " };
200 NSMutableAttributedString *_msg_color;
204 if ([_msg_arr count] > 10000) {
205 [_msg_arr removeObjectAtIndex: 0];
206 [_msg_arr removeObjectAtIndex: 1];
208 if (!item->psz_module)
213 firstString = [NSString stringWithFormat:@"%s%s", item->psz_module, ppsz_type[i_type]];
214 secondString = [NSString stringWithFormat:@"%@%s\n", firstString, str];
216 _attr = [NSDictionary dictionaryWithObject: pp_color[i_type] forKey: NSForegroundColorAttributeName];
217 _msg_color = [[NSMutableAttributedString alloc] initWithString: secondString attributes: _attr];
218 _attr = [NSDictionary dictionaryWithObject: pp_color[3] forKey: NSForegroundColorAttributeName];
219 [_msg_color setAttributes: _attr range: NSMakeRange(0, [firstString length])];
220 [_msg_arr addObject: [_msg_color autorelease]];