/***************************************************************************** * VLCiOSLegacyDialogProvider.m: an implementation of the libvlc dialog API * Included for compatiblity with iOS 7 ***************************************************************************** * Copyright (C) 2009, 2014-2015 VLC authors and VideoLAN * Copyright (C) 2016 VideoLabs SAS * $Id$ * * Authors: Felix Paul Kühne * Pierre d'Herbemont * * 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. *****************************************************************************/ #import "VLCLibrary.h" #import "VLCiOSLegacyDialogProvider.h" @interface VLCiOSLegacyDialogProvider () { VLCLibrary *_libraryInstance; } - (instancetype)initWithLibrary:(VLCLibrary *)library; - (void)displayError:(NSArray * _Nonnull)dialogData; - (void)displayLoginDialog:(NSArray * _Nonnull)dialogData; - (void)displayQuestion:(NSArray * _Nonnull)dialogData; - (void)displayProgressDialog:(NSArray * _Nonnull)dialogData; - (void)updateDisplayedProgressDialog:(NSArray * _Nonnull)dialogData; @end @interface VLCBlockingAlertView : UIAlertView @property (copy, nonatomic) void (^completion)(BOOL, NSInteger); - (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles; @end static void displayErrorCallback(void *p_data, const char *psz_title, const char *psz_text) { @autoreleasepool { VLCiOSLegacyDialogProvider *dialogProvider = (__bridge VLCiOSLegacyDialogProvider *)p_data; [dialogProvider performSelectorOnMainThread:@selector(displayError:) withObject:@[toNSStr(psz_title), toNSStr(psz_text)] waitUntilDone:NO]; } } static void displayLoginCallback(void *p_data, libvlc_dialog_id *p_id, const char *psz_title, const char *psz_text, const char *psz_default_username, bool b_ask_store) { @autoreleasepool { VLCiOSLegacyDialogProvider *dialogProvider = (__bridge VLCiOSLegacyDialogProvider *)p_data; [dialogProvider performSelectorOnMainThread:@selector(displayLoginDialog:) withObject:@[[NSValue valueWithPointer:p_id], toNSStr(psz_title), toNSStr(psz_text), toNSStr(psz_default_username), @(b_ask_store)] waitUntilDone:NO]; } } static void displayQuestionCallback(void *p_data, libvlc_dialog_id *p_id, const char *psz_title, const char *psz_text, libvlc_dialog_question_type i_type, const char *psz_cancel, const char *psz_action1, const char *psz_action2) { @autoreleasepool { VLCiOSLegacyDialogProvider *dialogProvider = (__bridge VLCiOSLegacyDialogProvider *)p_data; [dialogProvider performSelectorOnMainThread:@selector(displayQuestion:) withObject:@[[NSValue valueWithPointer:p_id], toNSStr(psz_title), toNSStr(psz_text), @(i_type), toNSStr(psz_cancel), toNSStr(psz_action1), toNSStr(psz_action2)] waitUntilDone:NO]; } } static void displayProgressCallback(void *p_data, libvlc_dialog_id *p_id, const char *psz_title, const char *psz_text, bool b_indeterminate, float f_position, const char *psz_cancel) { @autoreleasepool { VLCiOSLegacyDialogProvider *dialogProvider = (__bridge VLCiOSLegacyDialogProvider *)p_data; [dialogProvider performSelectorOnMainThread:@selector(displayProgressDialog:) withObject:@[[NSValue valueWithPointer:p_id], toNSStr(psz_title), toNSStr(psz_text), @(b_indeterminate), @(f_position), toNSStr(psz_cancel)] waitUntilDone:NO]; } } static void cancelCallback(void *p_data, libvlc_dialog_id *p_id) { @autoreleasepool { // FIXME: the saddest NO-OP VKLog(@"%s: %i", __PRETTY_FUNCTION__, (int)p_id); } } static void updateProgressCallback(void *p_data, libvlc_dialog_id *p_id, float f_position, const char *psz_text) { @autoreleasepool { VLCiOSLegacyDialogProvider *dialogProvider = (__bridge VLCiOSLegacyDialogProvider *)p_data; [dialogProvider performSelectorOnMainThread:@selector(updateDisplayedProgressDialog:) withObject:@[[NSValue valueWithPointer:p_id], @(f_position), toNSStr(psz_text)] waitUntilDone:NO]; } } @implementation VLCiOSLegacyDialogProvider - (void)dealloc { libvlc_dialog_set_callbacks(_libraryInstance.instance, NULL, NULL); } - (instancetype)initWithLibrary:(VLCLibrary *)library { self = [super init]; if (self != nil) { if (library == nil) { library = [VLCLibrary sharedLibrary]; } _libraryInstance = library; /* callback setup */ const libvlc_dialog_cbs cbs = { displayErrorCallback, displayLoginCallback, displayQuestionCallback, displayProgressCallback, cancelCallback, updateProgressCallback }; libvlc_dialog_set_callbacks(_libraryInstance.instance, &cbs, (__bridge void *)self); } return self; } - (void)displayError:(NSArray * _Nonnull)dialogData { VLCBlockingAlertView *alert = [[VLCBlockingAlertView alloc] initWithTitle:dialogData[0] message:dialogData[1] delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil]; alert.completion = nil; [alert show]; } - (void)displayLoginDialog:(NSArray * _Nonnull)dialogData { VLCBlockingAlertView *alert = [[VLCBlockingAlertView alloc] initWithTitle:dialogData[1] message:dialogData[2] delegate:nil cancelButtonTitle:NSLocalizedString(@"Cancel", nil) otherButtonTitles:NSLocalizedString(@"Login", nil), [dialogData[4] boolValue] ? NSLocalizedString(@"Store", nil) : nil, nil]; alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput; __weak typeof(alert) weakAlert = alert; alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) { if (!cancelled) { NSString *username = [weakAlert textFieldAtIndex:0].text; NSString *password = [weakAlert textFieldAtIndex:1].text; libvlc_dialog_post_login([dialogData[0] pointerValue], username ? [username UTF8String] : "", password ? [password UTF8String] : "", buttonIndex != alert.firstOtherButtonIndex); } else { libvlc_dialog_dismiss([dialogData[0] pointerValue]); } }; alert.delegate = alert; [alert show]; } - (void)displayQuestion:(NSArray * _Nonnull)dialogData { VLCBlockingAlertView * alert = [[VLCBlockingAlertView alloc] initWithTitle:dialogData[1] message:dialogData[2] delegate:nil cancelButtonTitle:dialogData[4] otherButtonTitles:dialogData[5], dialogData[6], nil]; alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) { if (cancelled) libvlc_dialog_post_action([dialogData[0] pointerValue], 3); else libvlc_dialog_post_action([dialogData[0] pointerValue], (int)buttonIndex); }; alert.delegate = alert; [alert show]; } - (void)displayProgressDialog:(NSArray * _Nonnull)dialogData { VKLog(@"%s: %@", __PRETTY_FUNCTION__, dialogData); } - (void)updateDisplayedProgressDialog:(NSArray * _Nonnull)dialogData { VKLog(@"%s: %@", __PRETTY_FUNCTION__, dialogData); } @end @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; } } @end