[vlc-devel] [PATCH] Add basic iOS Dialog provider
Felix Paul Kühne
fkuehne at videolan.org
Wed Mar 5 17:19:13 CET 2014
---
configure.ac | 14 +
modules/gui/Modules.am | 5 +-
modules/gui/ios_dialog_provider/Modules.am | 5 +
modules/gui/ios_dialog_provider/dialogProvider.m | 332 +++++++++++++++++++++++
4 files changed, 355 insertions(+), 1 deletion(-)
create mode 100644 modules/gui/ios_dialog_provider/Modules.am
create mode 100644 modules/gui/ios_dialog_provider/dialogProvider.m
diff --git a/configure.ac b/configure.ac
index a9ab432..5c92027 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3819,6 +3819,19 @@ fi
AM_CONDITIONAL(ENABLE_MACOSX_DIALOG_PROVIDER, [test "$enable_macosx_dialog_provider" != "no"])
dnl
+dnl iOS dialog provider
+dnl
+AC_ARG_ENABLE(ios-dialog-provider,
+ [ --enable-ios-dialog-provider iOS dialog module (default disabled)])
+if test "x${enable_ios_dialog_provider}" != "xno" &&
+ (test "${SYS}" = "darwin" || test "${enable_ios_dialog_provider}" = "yes")
+then
+ VLC_ADD_LIBS([ios_dialog_provider],[-Wl,-framework,UIKit])
+ VLC_ADD_PLUGIN([ios_dialog_provider])
+fi
+AM_CONDITIONAL(ENABLE_IOS_DIALOG_PROVIDER, [test "$enable_ios_dialog_provider" != "no"])
+
+dnl
dnl ncurses module
dnl
AC_ARG_ENABLE(ncurses,
@@ -4159,6 +4172,7 @@ AC_CONFIG_FILES([
modules/control/Makefile
modules/demux/Makefile
modules/gui/Makefile
+ modules/gui/ios_dialog_provider/Makefile
modules/gui/macosx/Makefile
modules/gui/minimal_macosx/Makefile
modules/gui/macosx_dialog_provider/Makefile
diff --git a/modules/gui/Modules.am b/modules/gui/Modules.am
index dcb1ba4..3b022ab 100644
--- a/modules/gui/Modules.am
+++ b/modules/gui/Modules.am
@@ -1,4 +1,4 @@
-DIST_SUBDIRS = macosx minimal_macosx qt4 skins2 macosx_dialog_provider
+DIST_SUBDIRS = macosx minimal_macosx qt4 skins2 macosx_dialog_provider ios_dialog_provider
SUBDIRS =
if ENABLE_MACOSX_UI
@@ -7,6 +7,9 @@ endif
if ENABLE_MACOSX_DIALOG_PROVIDER
SUBDIRS += macosx_dialog_provider
endif
+if ENABLE_IOS_DIALOG_PROVIDER
+SUBDIRS += ios_dialog_provider
+endif
if ENABLE_MINIMAL_MACOSX
SUBDIRS += minimal_macosx
endif
diff --git a/modules/gui/ios_dialog_provider/Modules.am b/modules/gui/ios_dialog_provider/Modules.am
new file mode 100644
index 0000000..1a528d9
--- /dev/null
+++ b/modules/gui/ios_dialog_provider/Modules.am
@@ -0,0 +1,5 @@
+AM_LIBTOOLFLAGS=--tag=CC
+
+SOURCES_ios_dialog_provider = \
+ dialogProvider.m \
+ $(NULL)
diff --git a/modules/gui/ios_dialog_provider/dialogProvider.m b/modules/gui/ios_dialog_provider/dialogProvider.m
new file mode 100644
index 0000000..111b9fb
--- /dev/null
+++ b/modules/gui/ios_dialog_provider/dialogProvider.m
@@ -0,0 +1,332 @@
+/*****************************************************************************
+ * dialogProvider.m: iOS Dialog Provider
+ *****************************************************************************
+ * Copyright (C) 2009, 2014 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Felix Paul Kühne <fkuehne # videolan org>
+ * Pierre d'Herbemont <pdherbemont # videolan org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#import <stdlib.h> /* malloc(), free() */
+#import <string.h>
+
+#ifdef HAVE_CONFIG_H
+# import "config.h"
+#endif
+
+#import <vlc_common.h>
+#import <vlc_plugin.h>
+#import <vlc_dialog.h>
+#import <vlc_modules.h>
+#import <vlc_interface.h>
+
+#import <UIKit/UIKit.h>
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+ at interface VLCDialogDisplayer : NSObject
+{
+}
+
++ (NSDictionary *)dictionaryForDialog:(const char *)title :(const char *)message :(const char *)yes :(const char *)no :(const char *)cancel;
+
+- (void)displayError:(NSDictionary *)dialog;
+- (void)displayCritical:(NSDictionary *)dialog;
+- (NSNumber *)displayQuestion:(NSDictionary *)dialog;
+- (NSDictionary *)displayLogin:(NSDictionary *)dialog;
+
+ at end
+
+ at interface VLCBlockingAlertView : UIAlertView <UIAlertViewDelegate>
+
+ at property (copy, nonatomic) void (^completion)(BOOL, NSInteger);
+
+- (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles;
+
+ at end
+
+static int OpenIntf(vlc_object_t *);
+static void CloseIntf(vlc_object_t *);
+static void Run(intf_thread_t * );
+
+static int DisplayError(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
+static int DisplayCritical(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
+static int DisplayQuestion(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
+static int DisplayLogin(vlc_object_t *,const char *,vlc_value_t,vlc_value_t,void * );
+
+static inline NSDictionary *DictFromDialogFatal(dialog_fatal_t *dialog) {
+ return [VLCDialogDisplayer dictionaryForDialog:dialog->title :dialog->message :NULL :NULL :NULL];
+}
+static inline NSDictionary *DictFromDialogLogin(dialog_login_t *dialog) {
+ return [VLCDialogDisplayer dictionaryForDialog:dialog->title :dialog->message :NULL :NULL :NULL];
+}
+static inline NSDictionary *DictFromDialogQuestion(dialog_question_t *dialog) {
+ return [VLCDialogDisplayer dictionaryForDialog:dialog->title :dialog->message :dialog->yes :dialog->no :dialog->cancel];
+}
+
+struct intf_sys_t
+{
+ VLCDialogDisplayer *displayer;
+};
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+vlc_module_begin()
+ /* Minimal interface. see intf.m */
+ set_shortname("iOS Dialogs")
+ add_shortcut("ios_dialog_provider", "miosx")
+ set_description("iOS Dialog Provider")
+ set_capability("interface", 0)
+
+ set_callbacks(OpenIntf, CloseIntf)
+ set_category(CAT_INTERFACE)
+ set_subcategory(SUBCAT_INTERFACE_MAIN)
+vlc_module_end()
+
+/*****************************************************************************
+ * OpenIntf: initialize interface
+ *****************************************************************************/
+int OpenIntf(vlc_object_t *p_this)
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+
+ p_intf->p_sys = malloc(sizeof(intf_sys_t));
+ if(!p_intf->p_sys)
+ return VLC_ENOMEM;
+
+ memset(p_intf->p_sys,0,sizeof(*p_intf->p_sys));
+
+ p_intf->p_sys->displayer = [[VLCDialogDisplayer alloc] init];
+
+ var_Create(p_intf,"dialog-error",VLC_VAR_ADDRESS);
+ var_AddCallback(p_intf,"dialog-error",DisplayError,p_intf);
+ var_Create(p_intf,"dialog-critical",VLC_VAR_ADDRESS);
+ var_AddCallback(p_intf,"dialog-critical",DisplayCritical,p_intf);
+ var_Create(p_intf,"dialog-login",VLC_VAR_ADDRESS);
+ var_AddCallback(p_intf,"dialog-login",DisplayLogin,p_intf);
+ var_Create(p_intf,"dialog-question",VLC_VAR_ADDRESS);
+ var_AddCallback(p_intf,"dialog-question",DisplayQuestion,p_intf);
+ dialog_Register(p_intf);
+
+ msg_Dbg(p_intf,"iOS dialog provider initialised");
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * CloseIntf: destroy interface
+ *****************************************************************************/
+void CloseIntf(vlc_object_t *p_this)
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+
+ /* unsubscribe from the interactive dialogues */
+ dialog_Unregister(p_intf);
+
+ var_DelCallback(p_intf,"dialog-error",DisplayError,p_intf);
+ var_DelCallback(p_intf,"dialog-critical",DisplayCritical,p_intf);
+ var_DelCallback(p_intf,"dialog-login",DisplayLogin,p_intf);
+ var_DelCallback(p_intf,"dialog-question",DisplayQuestion,p_intf);
+
+ [p_intf->p_sys->displayer release];
+
+ msg_Dbg(p_intf,"iOS dialog provider closed");
+ free(p_intf->p_sys);
+}
+
+
+/*****************************************************************************
+ * Callbacks triggered by the "dialog-*" variables
+ *****************************************************************************/
+static int DisplayError(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ dialog_fatal_t *dialog = value.p_address;
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+ intf_sys_t *sys = p_intf->p_sys;
+ [sys->displayer performSelectorOnMainThread:@selector(displayError:) withObject:DictFromDialogFatal(dialog) waitUntilDone:NO];
+ [pool release];
+ return VLC_SUCCESS;
+}
+
+static int DisplayCritical(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ dialog_fatal_t *dialog = value.p_address;
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+ intf_sys_t *sys = p_intf->p_sys;
+ [sys->displayer performSelectorOnMainThread:@selector(displayCritical:) withObject:DictFromDialogFatal(dialog) waitUntilDone:NO];
+ [pool release];
+ return VLC_SUCCESS;
+}
+
+static int DisplayQuestion(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ dialog_question_t *dialog = value.p_address;
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+ intf_sys_t *sys = p_intf->p_sys;
+ dialog->answer = [[sys->displayer displayQuestion:DictFromDialogQuestion(dialog)] intValue];
+ [pool release];
+ return VLC_SUCCESS;
+}
+
+static int DisplayLogin(vlc_object_t *p_this, const char *type, vlc_value_t previous, vlc_value_t value, void *data)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ dialog_login_t *dialog = value.p_address;
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+ intf_sys_t *sys = p_intf->p_sys;
+ NSDictionary *dict = [sys->displayer displayLogin:DictFromDialogLogin(dialog)];
+ if (dict) {
+ *dialog->username = strdup([[dict objectForKey:@"username"] UTF8String]);
+ *dialog->password = strdup([[dict objectForKey:@"password"] UTF8String]);
+ }
+ [pool release];
+ return VLC_SUCCESS;
+}
+
+ at implementation VLCDialogDisplayer
+
++ (NSDictionary *)dictionaryForDialog:(const char *)title :(const char *)message :(const char *)yes :(const char *)no :(const char *)cancel
+{
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
+ if (title)
+ [dict setObject:@(title) forKey:@"title"];
+ if (message)
+ [dict setObject:@(message) forKey:@"message"];
+ if (yes)
+ [dict setObject:@(yes) forKey:@"yes"];
+ if (no)
+ [dict setObject:@(no) forKey:@"no"];
+ if (cancel)
+ [dict setObject:@(cancel) forKey:@"cancel"];
+
+ return dict;
+}
+#define VLCAssertIsMainThread() assert([NSThread isMainThread])
+
+- (void)displayError:(NSDictionary *)dialog
+{
+ VLCAssertIsMainThread();
+
+ VLCBlockingAlertView *alert = [[VLCBlockingAlertView alloc] initWithTitle:[dialog objectForKey:@"title"] message:[dialog objectForKey:@"message"] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
+ alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) {
+ [alert release];
+ };
+ [alert show];
+}
+
+- (void)displayCritical:(NSDictionary *)dialog
+{
+ VLCAssertIsMainThread();
+
+ VLCBlockingAlertView *alert = [[VLCBlockingAlertView alloc] initWithTitle:[dialog objectForKey:@"title"] message:[dialog objectForKey:@"message"] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
+ alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) {
+ [alert release];
+ };
+ [alert show];
+}
+
+- (NSNumber *)displayQuestion:(NSDictionary *)dialog
+{
+ __block int ret = 0;
+ __block VLCBlockingAlertView *alert;
+
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ alert = [[VLCBlockingAlertView alloc] initWithTitle:[dialog objectForKey:@"title"] message:[dialog objectForKey:@"message"] delegate:nil cancelButtonTitle:[dialog objectForKey:@"cancel"] otherButtonTitles:[dialog objectForKey:@"yes"], [dialog objectForKey:@"no"], nil];
+ alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) {
+ if (cancelled)
+ ret = 3;
+ else
+ ret = buttonIndex;
+
+ dispatch_semaphore_signal(sema);
+ };
+ alert.delegate = alert;
+ [alert show];
+ });
+
+ dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+ [alert release];
+
+ return @(ret);
+}
+
+- (NSDictionary *)displayLogin:(NSDictionary *)dialog
+{
+ __block NSDictionary *dict;
+ __block VLCBlockingAlertView *alert;
+
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ alert = [[VLCBlockingAlertView alloc] initWithTitle:[dialog objectForKey:@"title"] message:[dialog objectForKey:@"message"] delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"Login", nil];
+ alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
+ alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) {
+ NSString *user = [alert textFieldAtIndex:0].text;
+ NSString *pass = [alert textFieldAtIndex:1].text;
+ dict = [[NSDictionary dictionaryWithObjectsAndKeys:
+ user, @"username",
+ pass, @"password",
+ nil] retain];
+
+ dispatch_semaphore_signal(sema);
+ };
+ alert.delegate = alert;
+ [alert show];
+ });
+
+ dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+
+ [alert release];
+ return dict;
+}
+
+ at end
+
+ at implementation VLCBlockingAlertView
+
+- (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles
+{
+ self = [self initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil];
+
+ if (self) {
+ for (NSString *buttonTitle in otherButtonTitles)
+ [self addButtonWithTitle:buttonTitle];
+ }
+ return self;
+}
+
+- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
+{
+ if (self.completion) {
+ self.completion(buttonIndex == self.cancelButtonIndex, buttonIndex);
+ self.completion = nil;
+ }
+}
+
+ at end
--
1.8.3.4 (Apple Git-47)
More information about the vlc-devel
mailing list