D3D11: include assert.h for vlc_assert_unreachable()
[vlc.git] / modules / gui / macosx / DebugMessageVisualizer.m
blob1242620c9fa54b2de81142de0dc6a9ae337ca278
1 /*****************************************************************************
2  * DebugMessageVisualizer.m: Mac OS X interface crash reporter
3  *****************************************************************************
4  * Copyright (C) 2004-2013 VLC authors and VideoLAN
5  * $Id$
6  *
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>
10  *
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.
15  *
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.
20  *
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"
27 #import "intf.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
35  * of this file.
36  *****************************************************************************/
38 @interface VLCDebugMessageVisualizer () <NSWindowDelegate>
40     NSMutableArray * _msg_arr;
41     NSLock * _msg_lock;
43 - (void)processReceivedlibvlcMessage:(const vlc_log_t *) item ofType: (int)i_type withStr: (char *)str;
45 @end
47 static void MsgCallback(void *data, int type, const vlc_log_t *item, const char *format, va_list ap)
49     @autoreleasepool {
51         VLCDebugMessageVisualizer *visualizer = (__bridge VLCDebugMessageVisualizer*)data;
53         int canc = vlc_savecancel();
54         char *str;
56         if (vasprintf(&str, format, ap) == -1) {
57             vlc_restorecancel(canc);
58             return;
59         }
61         [visualizer processReceivedlibvlcMessage: item ofType: type withStr: str];
63         vlc_restorecancel(canc);
64         free(str);
65     }
68 @implementation VLCDebugMessageVisualizer
70 - (id)init
72     self = [super initWithWindowNibName:@"DebugMessageVisualizer"];
73     if (self) {
74         _msg_lock = [[NSLock alloc] init];
75         _msg_arr = [NSMutableArray arrayWithCapacity:600];
76     }
77     return self;
80 - (void)dealloc
82     vlc_LogSet( VLCIntf->p_libvlc, NULL, NULL );
85 - (void)windowDidLoad
87     [self.window setExcludedFromWindowsMenu: YES];
88     [self.window setDelegate: self];
89     [self.window setTitle: _NS("Messages")];
90     [_msgs_save_btn setTitle: _NS("Save this Log...")];
91     [_msgs_refresh_btn setImage: [NSImage imageNamed: NSImageNameRefreshTemplate]];
94 #pragma mark - UI interaction
96 - (void)showWindow:(id)sender
98     /* subscribe to LibVLCCore's messages */
99     vlc_LogSet(VLCIntf->p_libvlc, MsgCallback, (__bridge void*)self);
101     [super showWindow:sender];
104 - (IBAction)updateMessagesPanel:(id)sender
106     [self windowDidBecomeKey:nil];
109 - (void)windowDidBecomeKey:(NSNotification *)notification
111     [_msgs_table reloadData];
112     [_msgs_table scrollRowToVisible: [_msg_arr count] - 1];
115 - (void)windowWillClose:(NSNotification *)notification
117     /* unsubscribe from LibVLCCore's messages */
118     vlc_LogSet( VLCIntf->p_libvlc, NULL, NULL );
121 - (IBAction)saveDebugLog:(id)sender
123     NSSavePanel * saveFolderPanel = [[NSSavePanel alloc] init];
125     [saveFolderPanel setCanSelectHiddenExtension: NO];
126     [saveFolderPanel setCanCreateDirectories: YES];
127     [saveFolderPanel setAllowedFileTypes: [NSArray arrayWithObject:@"rtf"]];
128     [saveFolderPanel setNameFieldStringValue:[NSString stringWithFormat: _NS("VLC Debug Log (%s).rtf"), VERSION_MESSAGE]];
129     [saveFolderPanel beginSheetModalForWindow: self.window completionHandler:^(NSInteger returnCode) {
130         if (returnCode == NSOKButton) {
131             NSUInteger count = [_msg_arr count];
132             NSMutableAttributedString * string = [[NSMutableAttributedString alloc] init];
133             for (NSUInteger i = 0; i < count; i++)
134                 [string appendAttributedString: [_msg_arr objectAtIndex:i]];
136             NSData *data = [string RTFFromRange:NSMakeRange(0, [string length])
137                              documentAttributes:[NSDictionary dictionaryWithObject: NSRTFTextDocumentType forKey: NSDocumentTypeDocumentAttribute]];
139             if ([data writeToFile: [[saveFolderPanel URL] path] atomically: YES] == NO)
140                 msg_Warn(VLCIntf, "Error while saving the debug log");
141         }
142     }];
145 #pragma mark - data handling
147 - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
149     if (aTableView == _msgs_table)
150         return [_msg_arr count];
151     return 0;
154 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
156     NSMutableAttributedString *result = NULL;
158     [_msg_lock lock];
159     if (rowIndex < [_msg_arr count])
160         result = [_msg_arr objectAtIndex:rowIndex];
161     [_msg_lock unlock];
163     if (result != NULL)
164         return result;
165     else
166         return @"";
169 - (void)processReceivedlibvlcMessage:(const vlc_log_t *) item ofType: (int)i_type withStr: (char *)str
171     if (_msg_arr) {
172         NSColor *_white = [NSColor whiteColor];
173         NSColor *_red = [NSColor redColor];
174         NSColor *_yellow = [NSColor yellowColor];
175         NSColor *_gray = [NSColor grayColor];
176         NSString * firstString, * secondString;
178         NSColor * pp_color[4] = { _white, _red, _yellow, _gray };
179         static const char * ppsz_type[4] = { ": ", " error: ", " warning: ", " debug: " };
181         NSDictionary *_attr;
182         NSMutableAttributedString *_msg_color;
184         [_msg_lock lock];
186         if ([_msg_arr count] > 10000) {
187             [_msg_arr removeObjectAtIndex: 0];
188             [_msg_arr removeObjectAtIndex: 1];
189         }
190         if (!item->psz_module)
191             return;
192         if (!str)
193             return;
195         firstString = [NSString stringWithFormat:@"%s%s", item->psz_module, ppsz_type[i_type]];
196         secondString = [NSString stringWithFormat:@"%@%s\n", firstString, str];
198         _attr = [NSDictionary dictionaryWithObject: pp_color[i_type]  forKey: NSForegroundColorAttributeName];
199         _msg_color = [[NSMutableAttributedString alloc] initWithString: secondString attributes: _attr];
200         _attr = [NSDictionary dictionaryWithObject: pp_color[3] forKey: NSForegroundColorAttributeName];
201         [_msg_color setAttributes: _attr range: NSMakeRange(0, [firstString length])];
202         [_msg_arr addObject:_msg_color];
204         [_msg_lock unlock];
205     }
208 @end