]> git.sesse.net Git - vlc/blob - modules/gui/macosx/DebugMessageVisualizer.m
macosx: do not allow playlist item deletion for sd modules
[vlc] / modules / gui / macosx / DebugMessageVisualizer.m
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  *****************************************************************************/
25
26 #import "DebugMessageVisualizer.h"
27 #import "intf.h"
28 #import <vlc_common.h>
29
30 static void MsgCallback(void *data, int type, const vlc_log_t *item, const char *format, va_list ap);
31
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  *****************************************************************************/
37
38 @interface VLCDebugMessageVisualizer () <NSWindowDelegate>
39 {
40     NSMutableArray * _msg_arr;
41     NSLock * _msg_lock;
42 }
43 - (void)processReceivedlibvlcMessage:(const vlc_log_t *) item ofType: (int)i_type withStr: (char *)str;
44
45 @end
46
47 static void MsgCallback(void *data, int type, const vlc_log_t *item, const char *format, va_list ap)
48 {
49     int canc = vlc_savecancel();
50     char *str;
51
52     if (vasprintf(&str, format, ap) == -1) {
53         vlc_restorecancel(canc);
54         return;
55     }
56
57     NSAutoreleasePool *_pool = [[NSAutoreleasePool alloc] init];
58     [[VLCDebugMessageVisualizer sharedInstance] processReceivedlibvlcMessage: item ofType: type withStr: str];
59     [_pool release];
60
61     vlc_restorecancel(canc);
62     free(str);
63 }
64
65 @implementation VLCDebugMessageVisualizer
66
67 static VLCDebugMessageVisualizer *_sharedMainInstance = nil;
68
69 + (VLCDebugMessageVisualizer *)sharedInstance
70 {
71     return _sharedMainInstance ? _sharedMainInstance : [[self alloc] init];
72 }
73
74 - (id)init
75 {
76     if (_sharedMainInstance)
77         [self dealloc];
78     else {
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];
83     }
84
85     return _sharedMainInstance;
86 }
87
88 - (void)awakeFromNib
89 {
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]];
95 }
96
97 - (void)dealloc
98 {
99     [_msg_arr removeAllObjects];
100     [_msg_arr release];
101     _msg_arr = NULL;
102
103     [_msg_lock release];
104
105     [super dealloc];
106 }
107
108 #pragma mark - UI interaction
109
110 - (void)showPanel
111 {
112     /* subscribe to LibVLCCore's messages */
113     vlc_LogSet(VLCIntf->p_libvlc, MsgCallback, NULL);
114
115     /* show panel */
116     [_msgs_panel makeKeyAndOrderFront:nil];
117 }
118
119 - (IBAction)updateMessagesPanel:(id)sender
120 {
121     [self windowDidBecomeKey:nil];
122 }
123
124 - (void)windowDidBecomeKey:(NSNotification *)notification
125 {
126     [_msgs_table reloadData];
127     [_msgs_table scrollRowToVisible: [_msg_arr count] - 1];
128 }
129
130 - (void)windowWillClose:(NSNotification *)notification
131 {
132     /* unsubscribe from LibVLCCore's messages */
133     vlc_LogSet( VLCIntf->p_libvlc, NULL, NULL );
134 }
135
136 - (IBAction)saveDebugLog:(id)sender
137 {
138     NSSavePanel * saveFolderPanel = [[NSSavePanel alloc] init];
139
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]];
150
151             NSData *data = [string RTFFromRange:NSMakeRange(0, [string length])
152                              documentAttributes:[NSDictionary dictionaryWithObject: NSRTFTextDocumentType forKey: NSDocumentTypeDocumentAttribute]];
153
154             if ([data writeToFile: [[saveFolderPanel URL] path] atomically: YES] == NO)
155                 msg_Warn(VLCIntf, "Error while saving the debug log");
156
157             [string release];
158         }
159     }];
160     [saveFolderPanel release];
161 }
162
163 #pragma mark - data handling
164
165 - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
166 {
167     if (aTableView == _msgs_table)
168         return [_msg_arr count];
169     return 0;
170 }
171
172 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
173 {
174     NSMutableAttributedString *result = NULL;
175
176     [_msg_lock lock];
177     if (rowIndex < [_msg_arr count])
178         result = [_msg_arr objectAtIndex:rowIndex];
179     [_msg_lock unlock];
180
181     if (result != NULL)
182         return result;
183     else
184         return @"";
185 }
186
187 - (void)processReceivedlibvlcMessage:(const vlc_log_t *) item ofType: (int)i_type withStr: (char *)str
188 {
189     if (_msg_arr) {
190         NSColor *_white = [NSColor whiteColor];
191         NSColor *_red = [NSColor redColor];
192         NSColor *_yellow = [NSColor yellowColor];
193         NSColor *_gray = [NSColor grayColor];
194         NSString * firstString, * secondString;
195
196         NSColor * pp_color[4] = { _white, _red, _yellow, _gray };
197         static const char * ppsz_type[4] = { ": ", " error: ", " warning: ", " debug: " };
198
199         NSDictionary *_attr;
200         NSMutableAttributedString *_msg_color;
201
202         [_msg_lock lock];
203
204         if ([_msg_arr count] > 10000) {
205             [_msg_arr removeObjectAtIndex: 0];
206             [_msg_arr removeObjectAtIndex: 1];
207         }
208         if (!item->psz_module)
209             return;
210         if (!str)
211             return;
212
213         firstString = [NSString stringWithFormat:@"%s%s", item->psz_module, ppsz_type[i_type]];
214         secondString = [NSString stringWithFormat:@"%@%s\n", firstString, str];
215
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]];
221
222         [_msg_lock unlock];
223     }
224 }
225
226 @end