]> git.sesse.net Git - vlc/blob - modules/gui/macosx_dialog_provider/dialogProvider.m
osx dialog provider: make sure we can actually quit VLC
[vlc] / modules / gui / macosx_dialog_provider / dialogProvider.m
1 /*****************************************************************************
2  * dialogProvider.m: Minimal Dialog Provider for Mac OS X
3  *****************************************************************************
4  * Copyright (C) 2009-2010 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Felix Paul Kühne <fkuehne at videolan dot org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #import <stdlib.h>                                      /* malloc(), free() */
28 #import <string.h>
29
30 #ifdef HAVE_CONFIG_H
31 # import "config.h"
32 #endif
33
34 #import <vlc_common.h>
35 #import <vlc_plugin.h>
36 #import <vlc_dialog.h>
37 #import <vlc_interface.h>
38
39 #import <Cocoa/Cocoa.h>
40 #import "VLCLoginPanel.h"
41 #import "VLCProgressPanel.h"
42
43 /*****************************************************************************
44  * Prototypes
45  *****************************************************************************/
46 static int  OpenIntf(vlc_object_t *);
47 static void CloseIntf(vlc_object_t *);
48 static void Run(intf_thread_t * );
49
50 static int DisplayError(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
51 static int DisplayCritical(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
52 static int DisplayQuestion(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
53 static int DisplayLogin(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
54 static int DisplayProgressPanelAction(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
55
56 static void updateProgressPanel (void *, const char *, float);
57 static bool checkProgressPanel (void *);
58 static void destroyProgressPanel (void *);
59
60 struct intf_sys_t
61 {
62     VLCProgressPanel *currentProgressBarPanel;
63
64     vlc_mutex_t lock;
65     vlc_cond_t wait;
66 };
67
68 /*****************************************************************************
69  * Module descriptor
70  *****************************************************************************/
71
72 vlc_module_begin()
73 /* Minimal interface. see intf.m */
74 set_shortname("Mac OS X Dialogs")
75 add_shortcut("macosx_dialog_provider")
76 add_shortcut("miosx")
77 set_description("Minimal Mac OS X Dialog Provider")
78 set_capability("interface", 50)
79 set_callbacks(OpenIntf, CloseIntf)
80 set_category(CAT_INTERFACE)
81 set_subcategory(SUBCAT_INTERFACE_MAIN)
82 vlc_module_end()
83
84 /*****************************************************************************
85  * OpenIntf: initialize interface
86  *****************************************************************************/
87 int OpenIntf(vlc_object_t *p_this)
88 {
89     intf_thread_t *p_intf = (intf_thread_t*) p_this;
90
91     p_intf->p_sys = malloc(sizeof(intf_sys_t));
92     if(!p_intf->p_sys)
93         return VLC_ENOMEM;
94
95     memset(p_intf->p_sys,0,sizeof(*p_intf->p_sys));
96
97     p_intf->b_should_run_on_first_thread = true;
98     p_intf->pf_run = Run;
99
100     msg_Dbg(p_intf,"Opening Mac OS X dialog provider");
101     return VLC_SUCCESS;
102 }
103
104 /*****************************************************************************
105  * Run: waiting for the death
106  *****************************************************************************/
107 static void Run( intf_thread_t *p_intf )
108 {
109     /* subscribe to various interactive dialogues */
110     var_Create(p_intf,"dialog-error",VLC_VAR_ADDRESS);
111     var_AddCallback(p_intf,"dialog-error",DisplayError,p_intf);
112     var_Create(p_intf,"dialog-critical",VLC_VAR_ADDRESS);
113     var_AddCallback(p_intf,"dialog-critical",DisplayCritical,p_intf);
114     var_Create(p_intf,"dialog-login",VLC_VAR_ADDRESS);
115     var_AddCallback(p_intf,"dialog-login",DisplayLogin,p_intf);
116     var_Create(p_intf,"dialog-question",VLC_VAR_ADDRESS);
117     var_AddCallback(p_intf,"dialog-question",DisplayQuestion,p_intf);
118     var_Create(p_intf,"dialog-progress-bar",VLC_VAR_ADDRESS);
119     var_AddCallback(p_intf,"dialog-progress-bar",DisplayProgressPanelAction,p_intf);
120     dialog_Register(p_intf);
121
122     msg_Dbg(p_intf,"Mac OS X dialog provider initialised");
123
124     /* idle */
125     while(vlc_object_alive(p_intf))
126         msleep(INTF_IDLE_SLEEP);
127     
128     /* unsubscribe from the interactive dialogues */
129     dialog_Unregister(p_intf);
130     var_DelCallback(p_intf,"dialog-error",DisplayError,p_intf);
131     var_DelCallback(p_intf,"dialog-critical",DisplayCritical,p_intf);
132     var_DelCallback(p_intf,"dialog-login",DisplayLogin,p_intf);
133     var_DelCallback(p_intf,"dialog-question",DisplayQuestion,p_intf);
134     var_DelCallback(p_intf,"dialog-progress-bar",DisplayProgressPanelAction,p_intf);
135 }
136 /*****************************************************************************
137  * CloseIntf: destroy interface
138  *****************************************************************************/
139 void CloseIntf(vlc_object_t *p_this)
140 {
141     intf_thread_t *p_intf = (intf_thread_t*) p_this;
142
143     msg_Dbg(p_intf,"Mac OS X dialog provider closed");
144     free(p_intf->p_sys);
145 }
146
147
148 /*****************************************************************************
149  * Callbacks triggered by the "dialog-*" variables
150  *****************************************************************************/
151 static int DisplayError(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
152 {
153     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
154     dialog_fatal_t *p_dialog = (dialog_fatal_t *)value.p_address;
155     NSRunInformationalAlertPanel([NSString stringWithUTF8String:p_dialog->title],
156                             [NSString stringWithUTF8String:p_dialog->message],
157                             @"OK", nil, nil);
158     [o_pool release];
159     return VLC_SUCCESS;
160 }
161
162 static int DisplayCritical(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
163 {
164     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
165     dialog_fatal_t *p_dialog = (dialog_fatal_t *)value.p_address;
166     NSRunCriticalAlertPanel([NSString stringWithUTF8String:p_dialog->title],
167                             [NSString stringWithUTF8String:p_dialog->message],
168                             @"OK", nil, nil);
169     [o_pool release];
170     return VLC_SUCCESS;
171 }
172
173 static int DisplayQuestion(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
174 {
175     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
176     dialog_question_t *p_dialog = (dialog_question_t *)value.p_address;
177     NSAlert *o_alert;
178     NSString *o_yes, *o_no, *o_cancel;
179     NSInteger i_returnValue = 0;
180
181     if (p_dialog->yes != NULL)
182         o_yes = [NSString stringWithUTF8String:p_dialog->yes];
183     if (p_dialog->no != NULL)
184         o_no = [NSString stringWithUTF8String:p_dialog->no];
185     if (p_dialog->cancel != NULL)
186         o_cancel = [NSString stringWithUTF8String:p_dialog->cancel];
187
188     o_alert = [NSAlert alertWithMessageText:[NSString stringWithUTF8String:p_dialog->title]
189                               defaultButton:o_yes
190                             alternateButton:o_no 
191                                 otherButton:o_cancel
192                   informativeTextWithFormat:[NSString stringWithUTF8String:p_dialog->message]];
193     [o_alert setAlertStyle:NSInformationalAlertStyle];
194     i_returnValue = [o_alert runModal];
195
196     if (i_returnValue == NSAlertDefaultReturn)
197         p_dialog->answer = 1;
198     if (i_returnValue == NSAlertAlternateReturn)
199         p_dialog->answer = 2;
200     if (i_returnValue == NSAlertOtherReturn)
201         p_dialog->answer = 3;
202     [o_pool release];
203     return VLC_SUCCESS;
204 }
205
206 static int DisplayLogin(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
207 {
208     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
209     dialog_login_t *p_dialog = (dialog_login_t *)value.p_address;
210     NSInteger i_returnValue = 0;
211     VLCLoginPanel *thePanel = [[VLCLoginPanel alloc] init];
212     [thePanel createContentView];
213     [thePanel setDialogTitle:[NSString stringWithUTF8String:p_dialog->title]];
214     [thePanel setDialogMessage:[NSString stringWithUTF8String:p_dialog->message]];
215     [thePanel center];
216     i_returnValue = [NSApp runModalForWindow:thePanel];
217     [thePanel close];
218     if (i_returnValue) {
219         *p_dialog->username = strdup( [[thePanel userName] UTF8String] );
220         *p_dialog->password = strdup( [[thePanel password] UTF8String] );
221     } else
222         *p_dialog->username = *p_dialog->password = NULL;
223     [o_pool release];
224     return VLC_SUCCESS;
225 }
226
227 static int DisplayProgressPanelAction(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
228 {
229     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
230     dialog_progress_bar_t * p_dialog = (dialog_progress_bar_t *)value.p_address;
231     intf_thread_t *p_intf = (intf_thread_t*) p_this;
232     intf_sys_t *p_sys = p_intf->p_sys;
233
234     if(p_sys->currentProgressBarPanel)
235         [p_sys->currentProgressBarPanel release];
236
237     p_sys->currentProgressBarPanel = [[VLCProgressPanel alloc] init];
238     [p_sys->currentProgressBarPanel createContentView];
239     if (p_dialog->title)
240         [p_sys->currentProgressBarPanel setDialogTitle:[NSString stringWithUTF8String:p_dialog->title]];
241     if (p_dialog->message)
242         [p_sys->currentProgressBarPanel setDialogMessage:[NSString stringWithUTF8String:p_dialog->message]];
243     if (p_dialog->cancel)
244         [p_sys->currentProgressBarPanel setCancelButtonLabel:[NSString stringWithUTF8String:p_dialog->cancel]];
245     [p_sys->currentProgressBarPanel center];
246     [p_sys->currentProgressBarPanel makeKeyAndOrderFront:nil];
247
248     p_dialog->pf_update = updateProgressPanel;
249     p_dialog->pf_check = checkProgressPanel;
250     p_dialog->pf_destroy = destroyProgressPanel;
251     p_dialog->p_sys = p_intf->p_sys;
252
253     [o_pool release];
254     return VLC_SUCCESS;
255 }
256
257 void updateProgressPanel (void *priv, const char *text, float value)
258 {
259     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
260     intf_sys_t *p_sys = (intf_sys_t *)priv;
261
262     if (text)
263         [p_sys->currentProgressBarPanel setDialogMessage:[NSString stringWithUTF8String:text]];
264     else
265         [p_sys->currentProgressBarPanel setDialogMessage:@""];
266     [p_sys->currentProgressBarPanel setProgressAsDouble:(double)(value * 1000.)];
267
268     [o_pool release];
269 }
270
271 void destroyProgressPanel (void *priv)
272 {
273     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
274     intf_sys_t *p_sys = (intf_sys_t *)priv;
275
276     [p_sys->currentProgressBarPanel close];
277     [p_sys->currentProgressBarPanel release];
278
279     [o_pool release];
280 }
281
282 bool checkProgressPanel (void *priv)
283 {
284     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
285     intf_sys_t *p_sys = (intf_sys_t *)priv;
286     BOOL b_returned;
287
288     b_returned = [p_sys->currentProgressBarPanel isCancelled];
289
290     [o_pool release];
291     return b_returned;
292 }
293