1 /*****************************************************************************
2 * interaction.h: Mac OS X interaction dialogs
3 *****************************************************************************
4 * Copyright (C) 2005-2007 the VideoLAN team
7 * Authors: Derk-Jan Hartman <hartman at videolan dot org>
8 * Felix Kühne <fkuehne at videolan dot org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
26 #import "interaction.h"
29 /* for the icons in our custom error panel */
30 #import <ApplicationServices/ApplicationServices.h>
32 /*****************************************************************************
33 * VLCInteractionList implementation
34 *****************************************************************************/
35 @implementation VLCInteractionList
40 o_interaction_list = [[NSMutableArray alloc] initWithCapacity:1];
41 [[NSNotificationCenter defaultCenter] addObserver:self
42 selector:@selector(newInteractionEvent:)
43 name: @"VLCNewInteractionEventNotification"
46 o_error_panel = [[VLCErrorInteractionPanel alloc] init];
51 -(void)newInteractionEvent: (NSNotification *)o_notification
53 VLCInteraction *o_interaction;
54 NSValue *o_value = [[o_notification userInfo] objectForKey:@"VLCDialogPointer"];
55 interaction_dialog_t *p_dialog = [o_value pointerValue];
57 switch( p_dialog->i_action )
60 [self addInteraction: p_dialog];
63 o_interaction = (VLCInteraction *)p_dialog->p_private;
64 [o_interaction updateDialog];
67 o_interaction = (VLCInteraction *)p_dialog->p_private;
68 [o_interaction hideDialog];
70 case INTERACT_DESTROY:
71 o_interaction = (VLCInteraction *)p_dialog->p_private;
72 [o_interaction destroyDialog];
73 [self removeInteraction:o_interaction];
74 p_dialog->i_status = DESTROYED_DIALOG;
79 -(void)addInteraction: (interaction_dialog_t *)p_dialog
81 VLCInteraction *o_interaction = [[VLCInteraction alloc] initDialog: p_dialog];
83 p_dialog->p_private = (void *)o_interaction;
84 [o_interaction_list addObject:[o_interaction autorelease]];
85 [o_interaction runDialog];
88 -(void)removeInteraction: (VLCInteraction *)o_interaction
90 [o_interaction_list removeObject:o_interaction];
100 [[NSNotificationCenter defaultCenter] removeObserver:self];
101 [o_interaction_list removeAllObjects];
102 [o_interaction_list release];
107 /*****************************************************************************
108 * VLCInteraction implementation
109 *****************************************************************************/
110 @implementation VLCInteraction
112 -(id)initDialog: (interaction_dialog_t *)_p_dialog
116 p_dialog = _p_dialog;
124 msg_Err( p_intf, "no available interaction framework" );
126 if( !nib_interact_loaded )
128 nib_interact_loaded = [NSBundle loadNibNamed:@"Interaction" owner:self];
129 [o_prog_cancel_btn setTitle: _NS("Cancel")];
130 [o_prog_bar setUsesThreadedAnimation: YES];
131 [o_auth_login_txt setStringValue: _NS("Login:")];
132 [o_auth_pw_txt setStringValue: _NS("Password:")];
133 [o_auth_cancel_btn setTitle: _NS("Cancel")];
134 [o_auth_ok_btn setTitle: _NS("OK")];
135 [o_input_ok_btn setTitle: _NS("OK")];
136 [o_input_cancel_btn setTitle: _NS("Cancel")];
137 o_mainIntfPgbar = [[VLCMain sharedInstance] getMainIntfPgbar];
140 NSString *o_title = [NSString stringWithUTF8String:p_dialog->psz_title ? p_dialog->psz_title : _("Error")];
141 NSString *o_description = [NSString stringWithUTF8String:p_dialog->psz_description ? p_dialog->psz_description : ""];
142 NSString *o_defaultButton = p_dialog->psz_default_button ? [NSString stringWithUTF8String:p_dialog->psz_default_button] : nil;
143 NSString *o_alternateButton = p_dialog->psz_alternate_button ? [NSString stringWithUTF8String:p_dialog->psz_alternate_button] : nil;
144 NSString *o_otherButton = p_dialog->psz_other_button ? [NSString stringWithUTF8String:p_dialog->psz_other_button] : nil;
146 vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
149 NSEnumerator * o_enum = [[NSApp orderedWindows] objectEnumerator];
151 while( ( o_window = [o_enum nextObject] ) )
153 if( [[o_window className] isEqualToString: @"VLCVoutWindow"] )
155 vlc_object_release( (vlc_object_t *)p_vout );
159 vlc_object_release( (vlc_object_t *)p_vout );
163 o_window = [NSApp mainWindow];
167 msg_Dbg( p_intf, "Title: %s", [o_title UTF8String] );
168 msg_Dbg( p_intf, "Description: %s", [o_description UTF8String] );
169 msg_Dbg( p_intf, "Delivered flag: %i", p_dialog->i_flags );
172 if( p_dialog->i_flags & DIALOG_BLOCKING_ERROR )
174 msg_Dbg( p_intf, "error panel requested" );
175 NSBeginInformationalAlertSheet( o_title, _NS("OK"), nil, nil,
176 o_window, self, @selector(sheetDidEnd: returnCode: contextInfo:),
177 NULL, nil, o_description );
179 else if( p_dialog->i_flags & DIALOG_NONBLOCKING_ERROR )
181 msg_Dbg( p_intf, "addition to non-blocking error panel received" );
182 [[[[VLCMain sharedInstance] getInteractionList] getErrorPanel]
183 addError: o_title withMsg: o_description];
185 else if( p_dialog->i_flags & DIALOG_WARNING )
187 msg_Dbg( p_intf, "addition to non-blocking warning panel received" );
188 [[[[VLCMain sharedInstance] getInteractionList] getErrorPanel]
189 addWarning: o_title withMsg: o_description];
191 else if( p_dialog->i_flags & DIALOG_YES_NO_CANCEL )
193 msg_Dbg( p_intf, "yes-no-cancel-dialog requested" );
194 NSBeginInformationalAlertSheet( o_title, o_defaultButton,
195 o_alternateButton, o_otherButton, o_window, self,
196 @selector(sheetDidEnd: returnCode: contextInfo:), NULL, nil,
199 else if( p_dialog->i_flags & DIALOG_LOGIN_PW_OK_CANCEL )
201 msg_Dbg( p_intf, "dialog for login and pw requested" );
202 [o_auth_title setStringValue: o_title];
203 [o_auth_description setStringValue: o_description];
204 [o_auth_login_fld setStringValue: @""];
205 [o_auth_pw_fld setStringValue: @""];
206 [NSApp beginSheet: o_auth_win modalForWindow: o_window
207 modalDelegate: self didEndSelector: nil contextInfo: nil];
208 [o_auth_win makeKeyWindow];
210 else if( p_dialog->i_flags & DIALOG_USER_PROGRESS )
212 msg_Dbg( p_intf, "user progress dialog requested" );
213 [o_prog_title setStringValue: o_title];
214 [o_prog_description setStringValue: o_description];
215 [o_prog_bar setDoubleValue: (double)p_dialog->val.f_float];
216 if( p_dialog->i_timeToGo < 1 )
217 [o_prog_timeToGo setStringValue: @""];
219 [o_prog_timeToGo setStringValue: [NSString stringWithFormat:
220 _NS("Remaining time: %i seconds"), p_dialog->i_timeToGo]];
221 [NSApp beginSheet: o_prog_win modalForWindow: o_window
222 modalDelegate: self didEndSelector: nil contextInfo: nil];
223 [o_prog_win makeKeyWindow];
225 else if( p_dialog->i_flags & DIALOG_PSZ_INPUT_OK_CANCEL )
227 msg_Dbg( p_intf, "text input from user requested" );
228 [o_input_title setStringValue: o_title];
229 [o_input_description setStringValue: o_description];
230 [o_input_fld setStringValue: @""];
231 [NSApp beginSheet: o_input_win modalForWindow: o_window
232 modalDelegate: self didEndSelector: nil contextInfo: nil];
233 [o_input_win makeKeyWindow];
235 else if( p_dialog->i_flags & DIALOG_INTF_PROGRESS )
237 msg_Dbg( p_intf, "progress-bar in main intf requested" );
238 [[VLCMain sharedInstance] setScrollField: o_description stopAfter: -1];
239 [o_mainIntfPgbar setDoubleValue: (double)p_dialog->val.f_float];
240 [o_mainIntfPgbar setHidden: NO];
241 [[[VLCMain sharedInstance] getControllerWindow] makeKeyWindow];
242 [o_mainIntfPgbar setIndeterminate: NO];
245 msg_Err( p_intf, "requested dialog type unknown (%i)", p_dialog->i_flags );
248 - (void)sheetDidEnd:(NSWindow *)o_sheet returnCode:(int)i_return
249 contextInfo:(void *)o_context
251 vlc_object_lock( p_dialog->p_interaction );
252 if( i_return == NSAlertDefaultReturn )
254 p_dialog->i_return = DIALOG_OK_YES;
256 else if( i_return == NSAlertAlternateReturn )
258 p_dialog->i_return = DIALOG_NO;
260 else if( i_return == NSAlertOtherReturn )
262 p_dialog->i_return = DIALOG_CANCELLED;
264 p_dialog->i_status = ANSWERED_DIALOG;
265 vlc_object_unlock( p_dialog->p_interaction );
270 if( p_dialog->i_flags & DIALOG_USER_PROGRESS )
272 [o_prog_description setStringValue:
273 [NSString stringWithUTF8String: p_dialog->psz_description]];
274 [o_prog_bar setDoubleValue: (double)p_dialog->val.f_float];
276 if( [o_prog_bar doubleValue] == 100.0 )
278 /* we are done, let's hide */
282 if( p_dialog->i_timeToGo < 1 )
283 [o_prog_timeToGo setStringValue: @""];
285 [o_prog_timeToGo setStringValue: [NSString stringWithFormat:
286 _NS("Remaining time: %i seconds"), p_dialog->i_timeToGo]];
290 if( p_dialog->i_flags & DIALOG_INTF_PROGRESS )
292 [[VLCMain sharedInstance] setScrollField:
293 [NSString stringWithUTF8String: p_dialog->psz_description]
295 [o_mainIntfPgbar setDoubleValue: (double)p_dialog->val.f_float];
297 if( [o_mainIntfPgbar doubleValue] == 100.0 )
299 /* we are done, let's hide */
308 msg_Dbg( p_intf, "hide event %p", self );
309 if( p_dialog->i_flags & DIALOG_USER_PROGRESS )
311 if([o_prog_win isVisible])
313 [NSApp endSheet: o_prog_win];
317 if( p_dialog->i_flags & DIALOG_LOGIN_PW_OK_CANCEL )
319 if([o_auth_win isVisible])
321 [NSApp endSheet: o_auth_win];
325 if( p_dialog->i_flags & DIALOG_PSZ_INPUT_OK_CANCEL )
327 if([o_input_win isVisible])
329 [NSApp endSheet: o_input_win];
333 if( p_dialog->i_flags & DIALOG_INTF_PROGRESS )
335 [o_mainIntfPgbar setIndeterminate: YES];
336 [o_mainIntfPgbar setHidden: YES];
337 [[VLCMain sharedInstance] resetScrollField];
343 msg_Dbg( p_intf, "destroy event" );
344 if( o_mainIntfPgbar )
345 [o_mainIntfPgbar release];
348 - (IBAction)cancelAndClose:(id)sender
350 /* tell the core that the dialog was cancelled in a yes/no-style dialogue */
351 vlc_object_lock( p_dialog->p_interaction );
352 p_dialog->i_return = DIALOG_CANCELLED;
353 p_dialog->i_status = ANSWERED_DIALOG;
354 vlc_object_unlock( p_dialog->p_interaction );
355 msg_Dbg( p_intf, "dialog cancelled" );
358 - (IBAction)cancelDialog:(id)sender
360 /* tell core that the user wishes to cancel the dialogue
361 * Use this function if cancelling is optionally like in the progress-dialogue */
362 vlc_object_lock( p_dialog->p_interaction );
363 p_dialog->b_cancelled = true;
364 vlc_object_unlock( p_dialog->p_interaction );
365 msg_Dbg( p_intf, "cancelling dialog, will close it later on" );
368 - (IBAction)okayAndClose:(id)sender
370 msg_Dbg( p_intf, "running okayAndClose" );
371 vlc_object_lock( p_dialog->p_interaction );
372 if( p_dialog->i_flags == DIALOG_LOGIN_PW_OK_CANCEL )
374 p_dialog->psz_returned[0] = strdup( [[o_auth_login_fld stringValue] UTF8String] );
375 p_dialog->psz_returned[1] = strdup( [[o_auth_pw_fld stringValue] UTF8String] );
377 else if( p_dialog->i_flags == DIALOG_PSZ_INPUT_OK_CANCEL )
378 p_dialog->psz_returned[0] = strdup( [[o_input_fld stringValue] UTF8String] );
379 p_dialog->i_return = DIALOG_OK_YES;
380 p_dialog->i_status = ANSWERED_DIALOG;
381 vlc_object_unlock( p_dialog->p_interaction );
382 msg_Dbg( p_intf, "dialog acknowledged" );
387 /*****************************************************************************
388 * VLCErrorInteractionPanel implementation
389 *****************************************************************************/
390 @implementation VLCErrorInteractionPanel
396 nib_interact_errpanel_loaded = [NSBundle loadNibNamed:@"InteractionErrorPanel" owner:self];
399 [o_window setTitle: _NS("Errors and Warnings")];
400 [o_cleanup_button setTitle: _NS("Clean up")];
401 [o_messages_btn setTitle: _NS("Show Details")];
403 /* init data sources */
404 o_errors = [[NSMutableArray alloc] init];
405 o_icons = [[NSMutableArray alloc] init];
419 [o_window makeKeyAndOrderFront: self];
422 -(void)addError: (NSString *)o_error withMsg:(NSString *)o_msg
424 /* format our string as desired */
425 NSMutableAttributedString * ourError;
426 ourError = [[NSMutableAttributedString alloc] initWithString:
427 [NSString stringWithFormat:@"%@\n%@", o_error, o_msg]
429 [NSDictionary dictionaryWithObject: [NSFont systemFontOfSize:11] forKey: NSFontAttributeName]];
431 addAttribute: NSFontAttributeName
432 value: [NSFont boldSystemFontOfSize:11]
433 range: NSMakeRange( 0, [o_error length])];
434 [o_errors addObject: ourError];
437 [o_icons addObject: [NSImage imageWithErrorIcon]];
439 [o_error_table reloadData];
442 -(void)addWarning: (NSString *)o_warning withMsg:(NSString *)o_msg
444 /* format our string as desired */
445 NSMutableAttributedString * ourWarning;
446 ourWarning = [[NSMutableAttributedString alloc] initWithString:
447 [NSString stringWithFormat:@"%@\n%@", o_warning, o_msg]
449 [NSDictionary dictionaryWithObject: [NSFont systemFontOfSize:11] forKey: NSFontAttributeName]];
451 addAttribute: NSFontAttributeName
452 value: [NSFont boldSystemFontOfSize:11]
453 range: NSMakeRange( 0, [o_warning length])];
454 [o_errors addObject: ourWarning];
455 [ourWarning release];
457 [o_icons addObject: [NSImage imageWithWarningIcon]];
459 [o_error_table reloadData];
462 -(IBAction)cleanupTable:(id)sender
464 [o_errors removeAllObjects];
465 [o_icons removeAllObjects];
466 [o_error_table reloadData];
469 -(IBAction)showMessages:(id)sender
471 [[VLCMain sharedInstance] showMessagesPanel: sender];
474 /*----------------------------------------------------------------------------
475 * data source methods
476 *---------------------------------------------------------------------------*/
477 - (int)numberOfRowsInTableView:(NSTableView *)theDataTable
479 return [o_errors count];
482 - (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn:
483 (NSTableColumn *)theTableColumn row: (int)row
485 if( [[theTableColumn identifier] isEqualToString: @"error_msg"] )
486 return [o_errors objectAtIndex: row];
488 if( [[theTableColumn identifier] isEqualToString: @"icon"] )
489 return [o_icons objectAtIndex: row];
491 return @"unknown identifier";