[vlc-commits] macosx: refactor input manager remnants

Felix Paul Kühne git at videolan.org
Thu Apr 11 19:26:45 CEST 2019


vlc | branch: master | Felix Paul Kühne <felix at feepk.net> | Thu Apr 11 19:22:36 2019 +0200| [7ab1d4b0cfd89d052217c852581afa01822b837f] | committer: Felix Paul Kühne

macosx: refactor input manager remnants

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7ab1d4b0cfd89d052217c852581afa01822b837f
---

 .../package/macosx/VLC.xcodeproj/project.pbxproj   |  12 +-
 modules/gui/macosx/Makefile.am                     |   4 +-
 .../gui/macosx/coreinteraction/VLCClickerManager.m |   4 +-
 .../gui/macosx/coreinteraction/VLCInputManager.m   | 407 ---------------------
 modules/gui/macosx/main/VLCMain.h                  |   2 -
 modules/gui/macosx/main/VLCMain.m                  |  16 +-
 .../VLCPlaybackContinuityController.h}             |  25 +-
 .../playlist/VLCPlaybackContinuityController.m     | 244 ++++++++++++
 .../windows/extensions/VLCExtensionsManager.m      |   1 +
 po/POTFILES.in                                     |   4 +-
 10 files changed, 266 insertions(+), 453 deletions(-)

diff --git a/extras/package/macosx/VLC.xcodeproj/project.pbxproj b/extras/package/macosx/VLC.xcodeproj/project.pbxproj
index 623d90e72d..3912b982e0 100644
--- a/extras/package/macosx/VLC.xcodeproj/project.pbxproj
+++ b/extras/package/macosx/VLC.xcodeproj/project.pbxproj
@@ -26,7 +26,7 @@
 		1C3113AD1E508C6900D4DD76 /* VLCExtensionsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CCED71314C0D4A90057F8D1 /* VLCExtensionsManager.m */; };
 		1C3113AF1E508C6900D4DD76 /* VLCFSPanelController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BCB590A1DA247CD009BCA66 /* VLCFSPanelController.m */; };
 		1C3113B11E508C6900D4DD76 /* VLCFSPanelDraggableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CAEBC001E1EC0A400A99E49 /* VLCFSPanelDraggableView.m */; };
-		1C3113B41E508C6900D4DD76 /* VLCInputManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF812EE1B555A340052293C /* VLCInputManager.m */; };
+		1C3113B41E508C6900D4DD76 /* VLCPlaybackContinuityController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF812EE1B555A340052293C /* VLCPlaybackContinuityController.m */; };
 		1C3113B61E508C6900D4DD76 /* VLCMain+OldPrefs.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D871D381B5E6844000B56C0 /* VLCMain+OldPrefs.m */; };
 		1C3113B81E508C6900D4DD76 /* VLCMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 8ED6C27D03E2EB1C0059A3A7 /* VLCMain.m */; };
 		1C3113BA1E508C6900D4DD76 /* VLCApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D5678EC1D5BA1DC002698F3 /* VLCApplication.m */; };
@@ -533,8 +533,8 @@
 		7DE9C7DC220728420089108F /* VLCPlayerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCPlayerController.m; sourceTree = "<group>"; };
 		7DF0435E1972E26A0022B534 /* VLCAddonListItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCAddonListItem.h; sourceTree = "<group>"; };
 		7DF0435F1972E26A0022B534 /* VLCAddonListItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCAddonListItem.m; sourceTree = "<group>"; };
-		7DF812ED1B555A340052293C /* VLCInputManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCInputManager.h; sourceTree = "<group>"; };
-		7DF812EE1B555A340052293C /* VLCInputManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCInputManager.m; sourceTree = "<group>"; };
+		7DF812ED1B555A340052293C /* VLCPlaybackContinuityController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCPlaybackContinuityController.h; sourceTree = "<group>"; };
+		7DF812EE1B555A340052293C /* VLCPlaybackContinuityController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCPlaybackContinuityController.m; sourceTree = "<group>"; };
 		7DF812EF1B555C8E0052293C /* VLCKeyboardBacklightControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCKeyboardBacklightControl.h; sourceTree = "<group>"; };
 		7DF812F01B555C8E0052293C /* VLCKeyboardBacklightControl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCKeyboardBacklightControl.m; sourceTree = "<group>"; };
 		8E49720006417F6800370C9F /* VLCInformationWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCInformationWindowController.h; sourceTree = "<group>"; };
@@ -854,8 +854,6 @@
 				7D66D4352200BC340040D04A /* VLCClickerManager.m */,
 				CC448A6013B68A0B009F72E0 /* VLCCoreInteraction.h */,
 				CC448A6113B68A0B009F72E0 /* VLCCoreInteraction.m */,
-				7DF812ED1B555A340052293C /* VLCInputManager.h */,
-				7DF812EE1B555A340052293C /* VLCInputManager.m */,
 				7D66D4372200C5B80040D04A /* VLCVideoFilterHelper.h */,
 				7D66D4382200C5B80040D04A /* VLCVideoFilterHelper.m */,
 			);
@@ -965,6 +963,8 @@
 		1C1ED5142205A96600811EC0 /* playlist */ = {
 			isa = PBXGroup;
 			children = (
+				7DF812ED1B555A340052293C /* VLCPlaybackContinuityController.h */,
+				7DF812EE1B555A340052293C /* VLCPlaybackContinuityController.m */,
 				7DE9C7DB220728420089108F /* VLCPlayerController.h */,
 				7DE9C7DC220728420089108F /* VLCPlayerController.m */,
 				7D445D7F2202524000263D34 /* VLCPlaylistController.h */,
@@ -1643,7 +1643,7 @@
 				1C3113AF1E508C6900D4DD76 /* VLCFSPanelController.m in Sources */,
 				7D66D4362200BC340040D04A /* VLCClickerManager.m in Sources */,
 				1C3113B11E508C6900D4DD76 /* VLCFSPanelDraggableView.m in Sources */,
-				1C3113B41E508C6900D4DD76 /* VLCInputManager.m in Sources */,
+				1C3113B41E508C6900D4DD76 /* VLCPlaybackContinuityController.m in Sources */,
 				1C3113B61E508C6900D4DD76 /* VLCMain+OldPrefs.m in Sources */,
 				1C3113B81E508C6900D4DD76 /* VLCMain.m in Sources */,
 				1CAC3EE820CD1B3B00613DB2 /* VLCVideoOutputProvider.m in Sources */,
diff --git a/modules/gui/macosx/Makefile.am b/modules/gui/macosx/Makefile.am
index b250880b5a..4aa0319f57 100644
--- a/modules/gui/macosx/Makefile.am
+++ b/modules/gui/macosx/Makefile.am
@@ -30,8 +30,6 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/coreinteraction/VLCClickerManager.m \
 	gui/macosx/coreinteraction/VLCCoreInteraction.h \
 	gui/macosx/coreinteraction/VLCCoreInteraction.m \
-	gui/macosx/coreinteraction/VLCInputManager.h \
-	gui/macosx/coreinteraction/VLCInputManager.m \
 	gui/macosx/coreinteraction/VLCVideoFilterHelper.h \
 	gui/macosx/coreinteraction/VLCVideoFilterHelper.m \
 	gui/macosx/extensions/NSScreen+VLCAdditions.h \
@@ -118,6 +116,8 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/panels/dialogs/VLCResumeDialogController.m \
 	gui/macosx/panels/dialogs/VLCTextfieldPanelController.h \
 	gui/macosx/panels/dialogs/VLCTextfieldPanelController.m \
+	gui/macosx/playlist/VLCPlaybackContinuityController.h \
+	gui/macosx/playlist/VLCPlaybackContinuityController.m \
 	gui/macosx/playlist/VLCPlayerController.h \
 	gui/macosx/playlist/VLCPlayerController.m \
 	gui/macosx/playlist/VLCPlaylistController.h \
diff --git a/modules/gui/macosx/coreinteraction/VLCClickerManager.m b/modules/gui/macosx/coreinteraction/VLCClickerManager.m
index dade9fa98b..44611bab84 100644
--- a/modules/gui/macosx/coreinteraction/VLCClickerManager.m
+++ b/modules/gui/macosx/coreinteraction/VLCClickerManager.m
@@ -25,7 +25,6 @@
 #include <vlc_common.h>
 #include <vlc_actions.h>
 
-#import "coreinteraction/VLCInputManager.h"
 #import "coreinteraction/VLCCoreInteraction.h"
 #import "extensions/NSSound+VLCAdditions.h"
 #import "imported/SPMediaKeyTap/SPMediaKeyTap.h"
@@ -111,8 +110,7 @@
         _mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self];
 
     VLCMain *main = [VLCMain sharedInstance];
-    if (b_mediaKeySupport && ([[[main playlistController] playlistModel] numberOfPlaylistItems] > 0 ||
-                              [[main inputManager] hasInput])) {
+    if (b_mediaKeySupport && ([[[main playlistController] playlistModel] numberOfPlaylistItems] > 0)) {
         if (!b_mediaKeyTrapEnabled) {
             msg_Dbg(p_intf, "Enabling media key support");
             if ([_mediaKeyController startWatchingMediaKeys]) {
diff --git a/modules/gui/macosx/coreinteraction/VLCInputManager.m b/modules/gui/macosx/coreinteraction/VLCInputManager.m
deleted file mode 100644
index 8882560448..0000000000
--- a/modules/gui/macosx/coreinteraction/VLCInputManager.m
+++ /dev/null
@@ -1,407 +0,0 @@
-/*****************************************************************************
- * VLCInputManager.m: MacOS X interface module
- *****************************************************************************
- * Copyright (C) 2015-2018 VLC authors and VideoLAN
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 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 General Public License for more details.
- *
- * You should have received a copy of the GNU 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 "VLCInputManager.h"
-
-#include <vlc_url.h>
-#import <vlc_playlist_legacy.h>
-
-#import "coreinteraction/VLCCoreInteraction.h"
-#import "main/CompatibilityFixes.h"
-#import "main/VLCMain.h"
-#import "menus/VLCMainMenu.h"
-#import "panels/VLCTrackSynchronizationWindowController.h"
-#import "panels/dialogs/VLCResumeDialogController.h"
-#import "windows/extensions/VLCExtensionsManager.h"
-#import "windows/mainwindow/VLCMainWindow.h"
-#import "windows/video/VLCVoutView.h"
-
- at interface VLCInputManager()
-- (void)updateMainMenu;
-- (void)updateMainWindow;
- at end
-
-#pragma mark Callbacks
-
-static int InputThreadChanged(vlc_object_t *p_this, const char *psz_var,
-                              vlc_value_t oldval, vlc_value_t new_val, void *param)
-{
-    @autoreleasepool {
-        VLCInputManager *inputManager = (__bridge VLCInputManager *)param;
-        [inputManager performSelectorOnMainThread:@selector(inputThreadChanged) withObject:nil waitUntilDone:NO];
-    }
-
-    return VLC_SUCCESS;
-}
-
-static NSDate *lastPositionUpdate = nil;
-
-static int InputEvent(vlc_object_t *p_this, const char *psz_var,
-                      vlc_value_t oldval, vlc_value_t new_val, void *param)
-{
-    @autoreleasepool {
-        VLCInputManager *inputManager = (__bridge VLCInputManager *)param;
-
-        switch (new_val.i_int) {
-            case INPUT_EVENT_STATE:
-                [inputManager performSelectorOnMainThread:@selector(playbackStatusUpdated) withObject: nil waitUntilDone:NO];
-                break;
-            case INPUT_EVENT_RATE:
-                break;
-            case INPUT_EVENT_POSITION:
-                break;
-            case INPUT_EVENT_TITLE:
-            case INPUT_EVENT_CHAPTER:
-                [inputManager performSelectorOnMainThread:@selector(updateMainMenu) withObject: nil waitUntilDone:NO];
-                break;
-            case INPUT_EVENT_CACHE:
-                [inputManager performSelectorOnMainThread:@selector(updateMainWindow) withObject:nil waitUntilDone:NO];
-                break;
-            case INPUT_EVENT_STATISTICS:
-                break;
-            case INPUT_EVENT_ES:
-                break;
-            case INPUT_EVENT_VOUT:
-                break;
-            case INPUT_EVENT_ITEM_META:
-            case INPUT_EVENT_ITEM_INFO:
-                [inputManager performSelectorOnMainThread:@selector(updateMainMenu) withObject: nil waitUntilDone:NO];
-                [inputManager performSelectorOnMainThread:@selector(updateName) withObject: nil waitUntilDone:NO];
-                break;
-            case INPUT_EVENT_BOOKMARK:
-                break;
-            case INPUT_EVENT_RECORD:
-                break;
-            case INPUT_EVENT_PROGRAM:
-                [inputManager performSelectorOnMainThread:@selector(updateMainMenu) withObject: nil waitUntilDone:NO];
-                break;
-            case INPUT_EVENT_ITEM_EPG:
-                break;
-            case INPUT_EVENT_SIGNAL:
-                break;
-
-            case INPUT_EVENT_DEAD:
-                [inputManager performSelectorOnMainThread:@selector(updateName) withObject: nil waitUntilDone:NO];
-                break;
-
-            default:
-                break;
-        }
-
-        return VLC_SUCCESS;
-    }
-}
-
-#pragma mark -
-#pragma mark InputManager implementation
-
- at interface VLCInputManager()
-{
-    __weak VLCMain *o_main;
-
-    input_thread_t *p_current_input;
-    dispatch_queue_t informInputChangedQueue;
-}
- at end
-
- at implementation VLCInputManager
-
-+ (void)initialize
-{
-    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-    NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
-                                 [NSArray array], @"recentlyPlayedMediaList",
-                                 [NSDictionary dictionary], @"recentlyPlayedMedia", nil];
-
-    [defaults registerDefaults:appDefaults];
-}
-
-- (id)initWithMain:(VLCMain *)o_mainObj
-{
-    self = [super init];
-    if(self) {
-        msg_Dbg(getIntf(), "Initializing input manager");
-
-        o_main = o_mainObj;
-        var_AddCallback(pl_Get(getIntf()), "input-current", InputThreadChanged, (__bridge void *)self);
-
-        informInputChangedQueue = dispatch_queue_create("org.videolan.vlc.inputChangedQueue", DISPATCH_QUEUE_SERIAL);
-    }
-    return self;
-}
-
-/*
- * TODO: Investigate if this can be moved to dealloc again. Current problems:
- * - dealloc might be never called of this object, as strong references could be in the
- *   (already stopped) main loop, preventing the refcount to go 0.
- * - Calling var_DelCallback waits for all callbacks to finish. Thus, while dealloc is already
- *   called, callback might grab a reference to this object again, which could cause trouble.
- */
-- (void)deinit
-{
-    msg_Dbg(getIntf(), "Deinitializing input manager");
-
-    if (p_current_input) {
-        /* continue playback where you left off */
-        [self storePlaybackPositionForItem:p_current_input];
-
-        var_DelCallback(p_current_input, "intf-event", InputEvent, (__bridge void *)self);
-        input_Release(p_current_input);
-        p_current_input = NULL;
-    }
-
-    var_DelCallback(pl_Get(getIntf()), "input-current", InputThreadChanged, (__bridge void *)self);
-
-#if !OS_OBJECT_USE_OBJC
-    dispatch_release(informInputChangedQueue);
-#endif
-}
-
-- (void)inputThreadChanged
-{
-    if (p_current_input) {
-        var_DelCallback(p_current_input, "intf-event", InputEvent, (__bridge void *)self);
-        input_Release(p_current_input);
-        p_current_input = NULL;
-
-        [[o_main mainMenu] setRateControlsEnabled: NO];
-
-        [[NSNotificationCenter defaultCenter] postNotificationName:VLCInputChangedNotification
-                                                            object:nil];
-    }
-
-    // Cancel pending resume dialogs
-    [[[VLCMain sharedInstance] resumeDialog] cancel];
-
-    input_thread_t *p_input_changed = NULL;
-
-    // object is hold here and released then it is dead
-    p_current_input = playlist_CurrentInput(pl_Get(getIntf()));
-    if (p_current_input) {
-        var_AddCallback(p_current_input, "intf-event", InputEvent, (__bridge void *)self);
-        [self playbackStatusUpdated];
-        [[o_main mainMenu] setRateControlsEnabled: YES];
-
-        if ([o_main activeVideoPlayback] && [[[o_main mainWindow] videoView] isHidden]) {
-            [[o_main mainWindow] changePlaylistState: psPlaylistItemChangedEvent];
-        }
-
-        p_input_changed = input_Hold(p_current_input);
-
-//        [[o_main playlist] currentlyPlayingItemChanged];
-
-        [self continuePlaybackWhereYouLeftOff:p_current_input];
-
-        [[NSNotificationCenter defaultCenter] postNotificationName:VLCInputChangedNotification
-                                                            object:nil];
-    }
-
-    [self updateMainWindow];
-    [self updateMainMenu];
-
-    /*
-     * Due to constraints within NSAttributedString's main loop runtime handling
-     * and other issues, we need to inform the extension manager on a separate thread.
-     * The serial queue ensures that changed inputs are propagated in the same order as they arrive.
-     */
-    dispatch_async(informInputChangedQueue, ^{
-        [[self->o_main extensionsManager] inputChanged:p_input_changed];
-        if (p_input_changed)
-            input_Release(p_input_changed);
-    });
-}
-
-- (void)playbackStatusUpdated
-{
-    // On shutdown, input might not be dead yet. Cleanup actions like itunes playback
-    // and playback positon are done in different code paths (dealloc and appWillTerminate:).
-    if ([[VLCMain sharedInstance] isTerminating]) {
-        return;
-    }
-
-    int64_t state = -1;
-    if (p_current_input) {
-        state = var_GetInteger(p_current_input, "state");
-    }
-
-    if (state != PLAYING_S) {
-        if (state == END_S || state == -1) {
-            /* continue playback where you left off */
-            if (p_current_input)
-                [self storePlaybackPositionForItem:p_current_input];
-        }
-    }
-
-    [self updateMainWindow];
-}
-
-- (void)updateMainWindow
-{
-    [[o_main mainWindow] updateWindow];
-}
-
-- (void)updateName
-{
-    [[o_main mainWindow] updateName];
-}
-
-- (void)updateMainMenu
-{
-}
-
-- (BOOL)hasInput
-{
-    return p_current_input != NULL;
-}
-
-#pragma mark -
-#pragma mark Resume logic
-
-
-- (BOOL)isValidResumeItem:(input_item_t *)p_item
-{
-    char *psz_url = input_item_GetURI(p_item);
-    NSString *urlString = toNSStr(psz_url);
-    free(psz_url);
-
-    if ([urlString isEqualToString:@""])
-        return NO;
-
-    NSURL *url = [NSURL URLWithString:urlString];
-
-    if (![url isFileURL])
-        return NO;
-
-    BOOL isDir = false;
-    if (![[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir])
-        return NO;
-
-    if (isDir)
-        return NO;
-
-    return YES;
-}
-
-- (void)continuePlaybackWhereYouLeftOff:(input_thread_t *)p_input_thread
-{
-    NSDictionary *recentlyPlayedFiles = [[NSUserDefaults standardUserDefaults] objectForKey:@"recentlyPlayedMedia"];
-    if (!recentlyPlayedFiles)
-        return;
-
-    input_item_t *p_item = input_GetItem(p_input_thread);
-    if (!p_item)
-        return;
-
-    /* allow the user to over-write the start/stop/run-time */
-    if (var_GetFloat(p_input_thread, "run-time") > 0 ||
-        var_GetFloat(p_input_thread, "start-time") > 0 ||
-        var_GetFloat(p_input_thread, "stop-time") != 0) {
-        return;
-    }
-
-    /* check for file existance before resuming */
-    if (![self isValidResumeItem:p_item])
-        return;
-
-    char *psz_url = vlc_uri_decode(input_item_GetURI(p_item));
-    if (!psz_url)
-        return;
-    NSString *url = toNSStr(psz_url);
-    free(psz_url);
-
-    NSNumber *lastPosition = [recentlyPlayedFiles objectForKey:url];
-    if (!lastPosition || lastPosition.intValue <= 0)
-        return;
-
-    int settingValue = (int)config_GetInt("macosx-continue-playback");
-    if (settingValue == 2) // never resume
-        return;
-
-    CompletionBlock completionBlock = ^(enum ResumeResult result) {
-
-        if (result == RESUME_RESTART)
-            return;
-
-        vlc_tick_t lastPos = vlc_tick_from_sec( lastPosition.intValue );
-        msg_Dbg(getIntf(), "continuing playback at %lld", lastPos);
-        var_SetInteger(p_input_thread, "time", lastPos);
-    };
-
-    if (settingValue == 1) { // always
-        completionBlock(RESUME_NOW);
-        return;
-    }
-
-    [[[VLCMain sharedInstance] resumeDialog] showWindowWithItem:p_item
-                                               withLastPosition:lastPosition.intValue
-                                                completionBlock:completionBlock];
-
-}
-
-- (void)storePlaybackPositionForItem:(input_thread_t *)p_input_thread
-{
-    if (!var_InheritBool(getIntf(), "macosx-recentitems"))
-        return;
-
-    input_item_t *p_item = input_GetItem(p_input_thread);
-    if (!p_item)
-        return;
-
-    if (![self isValidResumeItem:p_item])
-        return;
-
-    char *psz_url = vlc_uri_decode(input_item_GetURI(p_item));
-    if (!psz_url)
-        return;
-    NSString *url = toNSStr(psz_url);
-    free(psz_url);
-
-    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-    NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] initWithDictionary:[defaults objectForKey:@"recentlyPlayedMedia"]];
-
-    float relativePos = var_GetFloat(p_input_thread, "position");
-    long long pos = SEC_FROM_VLC_TICK(var_GetInteger(p_input_thread, "time"));
-    long long dur = SEC_FROM_VLC_TICK(input_item_GetDuration(p_item));
-
-    NSMutableArray *mediaList = [[defaults objectForKey:@"recentlyPlayedMediaList"] mutableCopy];
-
-    if (relativePos > .05 && relativePos < .95 && dur > 180) {
-        msg_Dbg(getIntf(), "Store current playback position of %f", relativePos);
-        [mutDict setObject:[NSNumber numberWithInteger:pos] forKey:url];
-
-        [mediaList removeObject:url];
-        [mediaList addObject:url];
-        NSUInteger mediaListCount = mediaList.count;
-        if (mediaListCount > 30) {
-            for (NSUInteger x = 0; x < mediaListCount - 30; x++) {
-                [mutDict removeObjectForKey:[mediaList firstObject]];
-                [mediaList removeObjectAtIndex:0];
-            }
-        }
-    } else {
-        [mutDict removeObjectForKey:url];
-        [mediaList removeObject:url];
-    }
-    [defaults setObject:mutDict forKey:@"recentlyPlayedMedia"];
-    [defaults setObject:mediaList forKey:@"recentlyPlayedMediaList"];
-    [defaults synchronize];
-}
-
- at end
diff --git a/modules/gui/macosx/main/VLCMain.h b/modules/gui/macosx/main/VLCMain.h
index 861eaf5fd9..5a7ad20e55 100644
--- a/modules/gui/macosx/main/VLCMain.h
+++ b/modules/gui/macosx/main/VLCMain.h
@@ -60,7 +60,6 @@ static NSString * VLCAppleRemoteSettingChangedNotification = @"VLCAppleRemoteSet
 @class AppleRemote;
 @class VLCInformationWindowController;
 @class VLCMainMenu;
- at class VLCInputManager;
 @class VLCResumeDialogController;
 @class VLCSimplePrefsController;
 @class VLCPrefs;
@@ -96,7 +95,6 @@ static NSString * VLCAppleRemoteSettingChangedNotification = @"VLCAppleRemoteSet
 - (VLCPrefs *)preferences;
 - (VLCCoreDialogProvider *)coreDialogProvider;
 - (VLCResumeDialogController *)resumeDialog;
-- (VLCInputManager *)inputManager;
 - (VLCExtensionsManager *)extensionsManager;
 - (VLCStatusBarIcon *)statusBarIcon;
 
diff --git a/modules/gui/macosx/main/VLCMain.m b/modules/gui/macosx/main/VLCMain.m
index f4d07db9c9..a1aafe0bbc 100644
--- a/modules/gui/macosx/main/VLCMain.m
+++ b/modules/gui/macosx/main/VLCMain.m
@@ -43,7 +43,6 @@
 #include <vlc_variables.h>
 
 #import "coreinteraction/VLCCoreInteraction.h"
-#import "coreinteraction/VLCInputManager.h"
 
 #import "library/VLCLibraryWindow.h"
 
@@ -64,6 +63,7 @@
 #import "playlist/VLCPlaylistController.h"
 #import "playlist/VLCPlayerController.h"
 #import "playlist/VLCPlaylistModel.h"
+#import "playlist/VLCPlaybackContinuityController.h"
 
 #import "preferences/prefs.h"
 #import "preferences/VLCSimplePrefsController.h"
@@ -178,7 +178,7 @@ static int ShowController(vlc_object_t *p_this, const char *psz_variable,
     VLCCoreDialogProvider *_coredialogs;
     VLCBookmarksWindowController *_bookmarks;
     VLCResumeDialogController *_resume_dialog;
-    VLCInputManager *_input_manager;
+    VLCPlaybackContinuityController *_continuityController;
     VLCLogWindowController *_messagePanelController;
     VLCStatusBarIcon *_statusBarIcon;
     VLCTrackSynchronizationWindowController *_trackSyncPanel;
@@ -228,7 +228,7 @@ static VLCMain *sharedInstance = nil;
         [VLCApplication sharedApplication].delegate = self;
 
         _playlistController = [[VLCPlaylistController alloc] initWithPlaylist:vlc_intf_GetMainPlaylist(p_intf)];
-        _input_manager = [[VLCInputManager alloc] initWithMain:self];
+        _continuityController = [[VLCPlaybackContinuityController alloc] init];
 
         // first initalize extensions dialog provider, then core dialog
         // provider which will register both at the core
@@ -331,7 +331,7 @@ static VLCMain *sharedInstance = nil;
         return;
     b_intf_terminating = true;
 
-    [_input_manager deinit];
+    _continuityController = nil;
 
     if (notification == nil)
         [[NSNotificationCenter defaultCenter] postNotificationName: NSApplicationWillTerminateNotification object: nil];
@@ -443,9 +443,6 @@ static VLCMain *sharedInstance = nil;
     if ([self mainWindow]) {
         [[self mainWindow] setVideoplayEnabled];
     }
-
-    // update sleep blockers
-    [_input_manager playbackStatusUpdated];
 }
 
 #pragma mark -
@@ -471,11 +468,6 @@ static VLCMain *sharedInstance = nil;
     return _libraryWindowController;
 }
 
-- (VLCInputManager *)inputManager
-{
-    return _input_manager;
-}
-
 - (VLCExtensionsManager *)extensionsManager
 {
     return _extensionsManager;
diff --git a/modules/gui/macosx/coreinteraction/VLCInputManager.h b/modules/gui/macosx/playlist/VLCPlaybackContinuityController.h
similarity index 74%
rename from modules/gui/macosx/coreinteraction/VLCInputManager.h
rename to modules/gui/macosx/playlist/VLCPlaybackContinuityController.h
index 47bb1ddaa2..325aa9698d 100644
--- a/modules/gui/macosx/coreinteraction/VLCInputManager.h
+++ b/modules/gui/macosx/playlist/VLCPlaybackContinuityController.h
@@ -1,7 +1,10 @@
 /*****************************************************************************
- * VLCInputManager.h: MacOS X interface module
+ * VLCPlaybackContinuityController.h: MacOS X interface module
  *****************************************************************************
- * Copyright (C) 2015 VLC authors and VideoLAN
+ * Copyright (C) 2015-2019 VLC authors and VideoLAN
+ *
+ * Authors: Felix Paul Kühne <fkuehne # videolan.org>
+ *          David Fuhrmann <dfuhrmann # videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,22 +23,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include <vlc_common.h>
-#import <vlc_interface.h>
-
-
-
- at class VLCMain;
-
- at interface VLCInputManager : NSObject
-
-- (id)initWithMain:(VLCMain *)o_mainObj;
-- (void)deinit;
-
-- (void)inputThreadChanged;
-
-- (void)playbackStatusUpdated;
-
-- (BOOL)hasInput;
+ at interface VLCPlaybackContinuityController : NSObject
 
 @end
diff --git a/modules/gui/macosx/playlist/VLCPlaybackContinuityController.m b/modules/gui/macosx/playlist/VLCPlaybackContinuityController.m
new file mode 100644
index 0000000000..d4d319732c
--- /dev/null
+++ b/modules/gui/macosx/playlist/VLCPlaybackContinuityController.m
@@ -0,0 +1,244 @@
+/*****************************************************************************
+ * VLCPlaybackContinuityController.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2015-2019 VLC authors and VideoLAN
+ *
+ * Authors: Felix Paul Kühne <fkuehne # videolan.org>
+ *          David Fuhrmann <dfuhrmann # videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 "VLCPlaybackContinuityController.h"
+
+#import "main/VLCMain.h"
+#import "panels/dialogs/VLCResumeDialogController.h"
+#import "playlist/VLCPlaylistController.h"
+#import "playlist/VLCPlayerController.h"
+
+#import <vlc_url.h>
+
+ at interface VLCPlaybackContinuityController()
+{
+    __weak VLCMain *_mainInstance;
+    input_item_t *p_current_input;
+}
+ at end
+
+ at implementation VLCPlaybackContinuityController
+
++ (void)initialize
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
+                                 [NSArray array], @"recentlyPlayedMediaList",
+                                 [NSDictionary dictionary], @"recentlyPlayedMedia", nil];
+
+    [defaults registerDefaults:appDefaults];
+}
+
+- (id)init
+{
+    self = [super init];
+    if (self) {
+        _mainInstance = [VLCMain sharedInstance];
+        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+        [notificationCenter addObserver:self
+                               selector:@selector(inputItemChanged:)
+                                   name:VLCPlaylistCurrentItemChanged
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(playbackStatusUpdated:)
+                                   name:VLCPlayerStateChanged
+                                 object:nil];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    msg_Dbg(getIntf(), "Deinitializing input manager");
+
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+    if (p_current_input) {
+        /* continue playback where you left off */
+        [self storePlaybackPositionForItem:p_current_input player:_mainInstance.playlistController.playerController];
+    }
+}
+
+- (void)inputItemChanged:(NSNotification *)aNotification
+{
+    // Cancel pending resume dialogs
+    [[_mainInstance resumeDialog] cancel];
+
+    // object is hold here and released then it is dead
+    p_current_input = [[_mainInstance playlistController] currentlyPlayingInputItem];
+    if (p_current_input) {
+        VLCPlaylistController *playlistController = aNotification.object;
+        [self continuePlaybackWhereYouLeftOff:p_current_input player:playlistController.playerController];
+    }
+}
+
+- (void)playbackStatusUpdated:(NSNotification *)aNotification
+{
+    // On shutdown, input might not be dead yet. Cleanup actions like itunes playback
+    // and playback positon are done in different code paths (dealloc and appWillTerminate:).
+    if ([_mainInstance isTerminating]) {
+        return;
+    }
+
+    VLCPlayerController *playerController = aNotification.object;
+    enum vlc_player_state playerState = [playerController playerState];
+
+    if (playerState == VLC_PLAYER_STATE_STOPPED || playerState == VLC_PLAYER_STATE_STOPPING) {
+        /* continue playback where you left off */
+        if (p_current_input)
+            [self storePlaybackPositionForItem:p_current_input player:playerController];
+    }
+}
+
+- (BOOL)isValidResumeItem:(input_item_t *)p_item
+{
+    char *psz_url = input_item_GetURI(p_item);
+    NSString *urlString = toNSStr(psz_url);
+    free(psz_url);
+
+    if ([urlString isEqualToString:@""])
+        return NO;
+
+    NSURL *url = [NSURL URLWithString:urlString];
+
+    if (![url isFileURL])
+        return NO;
+
+    BOOL isDir = false;
+    if (![[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir])
+        return NO;
+
+    if (isDir)
+        return NO;
+
+    return YES;
+}
+
+- (void)continuePlaybackWhereYouLeftOff:(input_item_t *)p_input_item player:(VLCPlayerController *)playerController
+{
+    NSDictionary *recentlyPlayedFiles = [[NSUserDefaults standardUserDefaults] objectForKey:@"recentlyPlayedMedia"];
+    if (!recentlyPlayedFiles)
+        return;
+
+    if (!p_input_item)
+        return;
+
+    /* allow the user to over-write the start/stop/run-time */
+    // FIXME: reimplement using new playlist
+#if 0
+    if (var_GetFloat(p_input_thread, "run-time") > 0 ||
+        var_GetFloat(p_input_thread, "start-time") > 0 ||
+        var_GetFloat(p_input_thread, "stop-time") != 0) {
+        return;
+    }
+#endif
+
+    /* check for file existance before resuming */
+    if (![self isValidResumeItem:p_input_item])
+        return;
+
+    char *psz_url = vlc_uri_decode(input_item_GetURI(p_input_item));
+    if (!psz_url)
+        return;
+    NSString *url = toNSStr(psz_url);
+    free(psz_url);
+
+    NSNumber *lastPosition = [recentlyPlayedFiles objectForKey:url];
+    if (!lastPosition || lastPosition.intValue <= 0)
+        return;
+
+    int settingValue = (int)config_GetInt("macosx-continue-playback");
+    if (settingValue == 2) // never resume
+        return;
+
+    CompletionBlock completionBlock = ^(enum ResumeResult result) {
+
+        if (result == RESUME_RESTART)
+            return;
+
+        vlc_tick_t lastPos = vlc_tick_from_sec( lastPosition.intValue );
+        msg_Dbg(getIntf(), "continuing playback at %lld", lastPos);
+
+        [playerController setTimePrecise: lastPos];
+    };
+
+    if (settingValue == 1) { // always
+        completionBlock(RESUME_NOW);
+        return;
+    }
+
+    [[_mainInstance resumeDialog] showWindowWithItem:p_input_item
+                                    withLastPosition:lastPosition.intValue
+                                     completionBlock:completionBlock];
+
+}
+
+- (void)storePlaybackPositionForItem:(input_item_t *)p_input_item player:(VLCPlayerController *)playerController
+{
+    if (!var_InheritBool(getIntf(), "macosx-recentitems"))
+        return;
+
+    if (!p_input_item)
+        return;
+
+    if (![self isValidResumeItem:p_input_item])
+        return;
+
+    char *psz_url = vlc_uri_decode(input_item_GetURI(p_input_item));
+    if (!psz_url)
+        return;
+    NSString *url = toNSStr(psz_url);
+    free(psz_url);
+
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] initWithDictionary:[defaults objectForKey:@"recentlyPlayedMedia"]];
+
+    float relativePos = playerController.position;
+    long long pos = SEC_FROM_VLC_TICK(playerController.time);
+    long long dur = SEC_FROM_VLC_TICK(input_item_GetDuration(p_input_item));
+
+    NSMutableArray *mediaList = [[defaults objectForKey:@"recentlyPlayedMediaList"] mutableCopy];
+
+    if (relativePos > .05 && relativePos < .95 && dur > 180) {
+        msg_Dbg(getIntf(), "Store current playback position of %f", relativePos);
+        [mutDict setObject:[NSNumber numberWithInteger:pos] forKey:url];
+
+        [mediaList removeObject:url];
+        [mediaList addObject:url];
+        NSUInteger mediaListCount = mediaList.count;
+        if (mediaListCount > 30) {
+            for (NSUInteger x = 0; x < mediaListCount - 30; x++) {
+                [mutDict removeObjectForKey:[mediaList firstObject]];
+                [mediaList removeObjectAtIndex:0];
+            }
+        }
+    } else {
+        [mutDict removeObjectForKey:url];
+        [mediaList removeObject:url];
+    }
+    [defaults setObject:mutDict forKey:@"recentlyPlayedMedia"];
+    [defaults setObject:mediaList forKey:@"recentlyPlayedMediaList"];
+    [defaults synchronize];
+}
+
+ at end
diff --git a/modules/gui/macosx/windows/extensions/VLCExtensionsManager.m b/modules/gui/macosx/windows/extensions/VLCExtensionsManager.m
index 5751c7261d..d65cc44db8 100644
--- a/modules/gui/macosx/windows/extensions/VLCExtensionsManager.m
+++ b/modules/gui/macosx/windows/extensions/VLCExtensionsManager.m
@@ -239,6 +239,7 @@
 
 - (void)inputChanged:(input_thread_t *)p_input
 {
+    // FIXME: this is never called!
     //This is unlikely, but can happen if no extension modules can be loaded.
     if (p_extensions_manager == NULL)
         return;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 33249fe09e..46482564a1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -452,8 +452,6 @@ modules/gui/macosx/coreinteraction/VLCClickerManager.h
 modules/gui/macosx/coreinteraction/VLCClickerManager.m
 modules/gui/macosx/coreinteraction/VLCCoreInteraction.h
 modules/gui/macosx/coreinteraction/VLCCoreInteraction.m
-modules/gui/macosx/coreinteraction/VLCInputManager.h
-modules/gui/macosx/coreinteraction/VLCInputManager.m
 modules/gui/macosx/coreinteraction/VLCVideoFilterHelper.h
 modules/gui/macosx/coreinteraction/VLCVideoFilterHelper.m
 modules/gui/macosx/extensions/NSScreen+VLCAdditions.h
@@ -519,6 +517,8 @@ modules/gui/macosx/panels/dialogs/VLCResumeDialogController.h
 modules/gui/macosx/panels/dialogs/VLCResumeDialogController.m
 modules/gui/macosx/panels/dialogs/VLCTextfieldPanelController.h
 modules/gui/macosx/panels/dialogs/VLCTextfieldPanelController.m
+modules/gui/macosx/playlist/VLCPlaybackContinuityController.h
+modules/gui/macosx/playlist/VLCPlaybackContinuityController.m
 modules/gui/macosx/playlist/VLCPlaylistController.h
 modules/gui/macosx/playlist/VLCPlaylistController.m
 modules/gui/macosx/playlist/VLCPlaylistDataSource.h



More information about the vlc-commits mailing list