From 2dd8d3ec5eca0267d58e3b11a59830c09849045d Mon Sep 17 00:00:00 2001 From: Oleksiy Yakovenko Date: Sun, 19 Nov 2023 12:52:20 +0100 Subject: [PATCH] cocoaui: use scriptableModel to observe selected preset instead of medialib manager KVO --- plugins/cocoaui/MainWindowController.m | 16 +--- .../MediaLibrary/MediaLibraryManager.h | 4 +- .../MediaLibrary/MediaLibraryManager.m | 17 +--- .../MediaLibraryOutlineViewController.m | 27 ++++-- .../ScriptableSelectViewController.h | 2 + .../ScriptableSelectViewController.m | 82 ++++++++++++++++++- plugins/gtkui/medialib/medialibmanager.c | 10 --- plugins/gtkui/medialib/medialibmanager.h | 6 -- plugins/gtkui/medialib/medialibwidget.c | 4 +- .../gtkScriptableSelectViewController.c | 20 +++-- 10 files changed, 124 insertions(+), 64 deletions(-) diff --git a/plugins/cocoaui/MainWindowController.m b/plugins/cocoaui/MainWindowController.m index ff6e9ff4cb..d0f2754ed5 100644 --- a/plugins/cocoaui/MainWindowController.m +++ b/plugins/cocoaui/MainWindowController.m @@ -136,14 +136,7 @@ - (void)windowDidLoad { [_tfQueryContainer addSubview:self.tfQuerySelectViewController.view]; self.tfQuerySelectViewController.errorViewer = ScriptableErrorViewer.sharedInstance; self.tfQuerySelectViewController.dataSource = self.mlQueriesDataSource; - - if (self.mlQueriesDataSource.scriptable != NULL) { - NSString *preset = self.mediaLibraryManager.preset; - scriptableItem_t *currentPreset = scriptableItemSubItemForName(self.mlQueriesDataSource.scriptable, preset.UTF8String); - if (currentPreset != NULL) { - [self.tfQuerySelectViewController selectItem:currentPreset]; - } - } + self.tfQuerySelectViewController.scriptableModel = self.mediaLibraryManager.model; id rootWidget = DesignModeState.sharedInstance.rootWidget; NSView *view = rootWidget.view; @@ -544,8 +537,6 @@ - (void)deletePlaylistDone:(DeletePlaylistConfirmationController *)controller { #pragma mark - ScriptableSelectDelegate - (void)scriptableSelectItemSelected:(scriptableItem_t *)item { - const char *name = scriptableItemPropertyValueForKey(item, "name"); - self.mediaLibraryManager.preset = @(name); } #pragma mark - ScriptableItemDelegate @@ -560,11 +551,6 @@ - (void)scriptableItemDidChange:(scriptableItem_t *)scriptable change:(Scriptabl if (tfQueryRoot != NULL) { scriptableItemSave(tfQueryRoot); } - - // refresh the tree - NSInteger index = self.tfQuerySelectViewController.indexOfSelectedItem; - scriptableItem_t *item = scriptableItemChildAtIndex(tfQueryRoot, (unsigned int)index); - [self scriptableSelectItemSelected:item]; } }); } diff --git a/plugins/cocoaui/MediaLibrary/MediaLibraryManager.h b/plugins/cocoaui/MediaLibrary/MediaLibraryManager.h index bb9cfae94f..2e2e4bfd73 100644 --- a/plugins/cocoaui/MediaLibrary/MediaLibraryManager.h +++ b/plugins/cocoaui/MediaLibrary/MediaLibraryManager.h @@ -8,6 +8,7 @@ #import #include +#include "scriptable/scriptable_model.h" #include "medialib.h" NS_ASSUME_NONNULL_BEGIN @@ -16,8 +17,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,readonly) DB_mediasource_t *medialibPlugin; @property (nonatomic,readonly) ddb_mediasource_source_t *source; - -@property (nullable, nonatomic) NSString *preset; +@property (nonatomic,readonly) scriptableModel_t *model; @end diff --git a/plugins/cocoaui/MediaLibrary/MediaLibraryManager.m b/plugins/cocoaui/MediaLibrary/MediaLibraryManager.m index 05d4e987be..8dff148d03 100644 --- a/plugins/cocoaui/MediaLibrary/MediaLibraryManager.m +++ b/plugins/cocoaui/MediaLibrary/MediaLibraryManager.m @@ -14,6 +14,7 @@ @interface MediaLibraryManager() @property (nonatomic,readwrite) DB_mediasource_t *medialibPlugin; @property (nonatomic,readwrite) ddb_mediasource_source_t *source; +@property (nonatomic,readwrite) scriptableModel_t *model; @end @@ -33,11 +34,14 @@ - (instancetype)init _source = self.medialibPlugin->create_source ("deadbeef"); self.medialibPlugin->refresh(_source); + self.model = scriptableModelInit(scriptableModelAlloc(), deadbeef, "medialib.preset"); + return self; } - (void)dealloc { + scriptableModelFree(_model); if (_source) { _medialibPlugin->free_source(_source); _source = NULL; @@ -45,17 +49,4 @@ - (void)dealloc _medialibPlugin = NULL; } -- (void)setPreset:(NSString *)preset { - [self willChangeValueForKey:@"preset"]; - deadbeef->conf_set_str("medialib.preset", preset.UTF8String); - deadbeef->sendmessage(DB_EV_CONFIGCHANGED, 0, 0, 0); - [self didChangeValueForKey:@"preset"]; -} - -- (NSString *)preset { - char buffer[100]; - deadbeef->conf_get_str("medialib.preset", "", buffer, sizeof(buffer)); - return @(buffer); -} - @end diff --git a/plugins/cocoaui/MediaLibrary/MediaLibraryOutlineViewController.m b/plugins/cocoaui/MediaLibrary/MediaLibraryOutlineViewController.m index 97b9021544..758a42cc82 100644 --- a/plugins/cocoaui/MediaLibrary/MediaLibraryOutlineViewController.m +++ b/plugins/cocoaui/MediaLibrary/MediaLibraryOutlineViewController.m @@ -24,6 +24,7 @@ static void *kPresetCtx = &kPresetCtx; @interface MediaLibraryOutlineViewController() { + int64_t _modelListenerId; } @property (nonatomic) MediaLibraryItem *medialibRootItem; @@ -50,8 +51,6 @@ @interface MediaLibraryOutlineViewController() *albumArtCache; -@property (nonatomic) NSString *currentPreset; - @property (nonatomic) NSImage *folderImage; @end @@ -71,6 +70,16 @@ - (instancetype)init { return [self initWithOutlineView:[NSOutlineView new] searchField:[NSSearchField new]]; } +static void +_model_listener (struct scriptableModel_t *model, void *user_data) { + MediaLibraryOutlineViewController *self = (__bridge MediaLibraryOutlineViewController *)user_data; + [self modelListener]; +} + +- (void)modelListener { + [self initializeTreeView]; +} + - (instancetype)initWithOutlineView:(NSOutlineView *)outlineView searchField:(NSSearchField *)searchField { self = [super init]; if (!self) { @@ -79,9 +88,6 @@ - (instancetype)initWithOutlineView:(NSOutlineView *)outlineView searchField:(NS [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(applicationWillQuit:) name:@"ApplicationWillQuit" object:nil]; - - - self.currentPreset = self.mediaLibraryManager.preset; [self.mediaLibraryManager addObserver:self forKeyPath:@"preset" options:0 context:kPresetCtx]; self.outlineView = outlineView; @@ -103,6 +109,9 @@ - (instancetype)initWithOutlineView:(NSOutlineView *)outlineView searchField:(NS [self initializeTreeView]; + scriptableModel_t *model = self.mediaLibraryManager.model; + _modelListenerId = scriptableModelGetAPI(model)->add_listener (model, _model_listener, (__bridge void *)self); + [self.outlineView expandItem:self.medialibRootItem]; [self updateMedialibStatus]; @@ -125,7 +134,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N dispatch_async(dispatch_get_main_queue(), ^{ // NOTE: don't add a check for whether user changed to another preset. // This would break a refresh if the current preset changes settings. - self.currentPreset = self.mediaLibraryManager.preset; [self filterChanged]; }); } else { @@ -134,6 +142,10 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N } - (void)disconnect { + scriptableModel_t *model = self.mediaLibraryManager.model; + scriptableModelGetAPI(model)->remove_listener(model, _modelListenerId); + _modelListenerId = 0; + if (self.medialibPlugin == NULL) { return; } @@ -170,7 +182,8 @@ - (void)initializeTreeView { scriptableItem_t *tfQueryRoot = self.medialibPlugin->get_queries_scriptable(self.medialibSource); - NSString *presetName = self.mediaLibraryManager.preset; + scriptableModel_t *model = self.mediaLibraryManager.model; + NSString *presetName = @(scriptableModelGetAPI(model)->get_active_name(model)); scriptableItem_t *preset = NULL; if (presetName != nil) { preset = scriptableItemSubItemForName(tfQueryRoot, presetName.UTF8String); diff --git a/plugins/cocoaui/Scriptable/ScriptableSelectViewController.h b/plugins/cocoaui/Scriptable/ScriptableSelectViewController.h index 4bebc06477..1c47aef739 100644 --- a/plugins/cocoaui/Scriptable/ScriptableSelectViewController.h +++ b/plugins/cocoaui/Scriptable/ScriptableSelectViewController.h @@ -8,6 +8,7 @@ #import #include "scriptable/scriptable.h" +#include "scriptable/scriptable_model.h" #import "ScriptableTableDataSource.h" #import "ScriptableProtocols.h" @@ -25,6 +26,7 @@ NS_ASSUME_NONNULL_BEGIN @property (weak) NSObject *scriptableItemDelegate; @property (weak) NSObject *scriptableSelectDelegate; @property (weak) NSObject *errorViewer; +@property scriptableModel_t *scriptableModel; @property (nonatomic,readonly) NSInteger indexOfSelectedItem; diff --git a/plugins/cocoaui/Scriptable/ScriptableSelectViewController.m b/plugins/cocoaui/Scriptable/ScriptableSelectViewController.m index 2f6af0ab25..49bee5527a 100644 --- a/plugins/cocoaui/Scriptable/ScriptableSelectViewController.m +++ b/plugins/cocoaui/Scriptable/ScriptableSelectViewController.m @@ -9,7 +9,11 @@ #import "ScriptableSelectViewController.h" #import "ScriptableNodeEditorWindowController.h" -@interface ScriptableSelectViewController () +@interface ScriptableSelectViewController () { + scriptableModelAPI_t *_modelAPI; + int64_t _modelListenerId; + BOOL _updatingModel; +} @property (weak) IBOutlet NSPopUpButton *nameList; @property (weak) IBOutlet NSButton *browseButton; @@ -19,6 +23,8 @@ @interface ScriptableSelectViewController () @implementation ScriptableSelectViewController +@synthesize scriptableModel = _scriptableModel; + - (void)setDataSource:(ScriptableTableDataSource *)dataSource { _dataSource = dataSource; [self reloadData]; @@ -26,13 +32,14 @@ - (void)setDataSource:(ScriptableTableDataSource *)dataSource { - (IBAction)nameSelectedAction:(NSPopUpButton *)sender { NSUInteger index = sender.indexOfSelectedItem; + [self updateModelFromCurrent]; [self.scriptableSelectDelegate scriptableSelectItemSelected:scriptableItemChildAtIndex(self.dataSource.scriptable, (unsigned int)index)]; } - (void)initNodeEditorWindowController { self.nodeEditorWindowController = [[ScriptableNodeEditorWindowController alloc] initWithWindowNibName:@"ScriptableNodeEditorWindow"]; self.nodeEditorWindowController.dataSource = self.dataSource; - self.nodeEditorWindowController.delegate = self.scriptableItemDelegate; + self.nodeEditorWindowController.delegate = self; self.nodeEditorWindowController.errorViewer = self.errorViewer; } @@ -73,4 +80,75 @@ - (void)selectItem:(scriptableItem_t *)item { } } +- (void)updateCurrentFromModel { + if (_scriptableModel == NULL) { + return; + } + char *preset = _modelAPI->get_active_name (_scriptableModel); + scriptableItem_t *currentPreset = scriptableItemSubItemForName (self.dataSource.scriptable, preset); + if (currentPreset != NULL) { + [self selectItem:currentPreset]; + } + free (preset); +} + +- (void)updateModelFromCurrent { + if (_scriptableModel == NULL) { + return; + } + + NSUInteger index = self.nameList.indexOfSelectedItem; + scriptableItem_t *item = scriptableItemChildAtIndex(self.dataSource.scriptable, (unsigned int)index); + + const char *name = ""; + if (item != NULL) { + name = scriptableItemPropertyValueForKey (item, "name"); + } + _updatingModel = YES; + _modelAPI->set_active_name (_scriptableModel, name); + _updatingModel = NO; +} + +static void +_model_listener (struct scriptableModel_t *model, void *user_data) { + ScriptableSelectViewController *self = (__bridge ScriptableSelectViewController *)user_data; + [self modelListener]; +} + +- (void)modelListener { + if (_updatingModel) { + return; + } + + [self updateCurrentFromModel]; +} + +- (scriptableModel_t *)scriptableModel { + return _scriptableModel; +} + +- (void)setScriptableModel:(scriptableModel_t *)scriptableModel { + if (_scriptableModel != NULL) { + _modelAPI->remove_listener (_scriptableModel, self->_modelListenerId); + _modelListenerId = 0; + _modelAPI = NULL; + } + + _scriptableModel = scriptableModel; + + if (scriptableModel != NULL) { + _modelAPI = scriptableModelGetAPI (scriptableModel); + _modelListenerId = _modelAPI->add_listener (scriptableModel, _model_listener, (__bridge void *)self); + + [self updateCurrentFromModel]; + } +} + +#pragma mark - ScriptableItemDelegate + +- (void)scriptableItemDidChange:(scriptableItem_t *)scriptable change:(ScriptableItemChange)change { + [self updateModelFromCurrent]; + [self.scriptableItemDelegate scriptableItemDidChange:scriptable change:change]; +} + @end diff --git a/plugins/gtkui/medialib/medialibmanager.c b/plugins/gtkui/medialib/medialibmanager.c index 8def6ffe12..c939fd7bad 100644 --- a/plugins/gtkui/medialib/medialibmanager.c +++ b/plugins/gtkui/medialib/medialibmanager.c @@ -53,13 +53,3 @@ scriptableModel_t * gtkui_medialib_get_model (void) { return _model; } - -void -gtkui_medialib_preset_set (const char *preset) { - scriptableModelGetAPI (_model)->set_active_name (_model, preset); -} - -char * -gtkui_medialib_preset_get (void) { - return scriptableModelGetAPI (_model)->get_active_name (_model); -} diff --git a/plugins/gtkui/medialib/medialibmanager.h b/plugins/gtkui/medialib/medialibmanager.h index af558aa7b4..4d5a09f5f6 100644 --- a/plugins/gtkui/medialib/medialibmanager.h +++ b/plugins/gtkui/medialib/medialibmanager.h @@ -18,12 +18,6 @@ gtkui_medialib_get_source (void); void gtkui_medialib_free (void); -void -gtkui_medialib_preset_set (const char *preset); - -char * -gtkui_medialib_preset_get (void); - scriptableModel_t * gtkui_medialib_get_model (void); diff --git a/plugins/gtkui/medialib/medialibwidget.c b/plugins/gtkui/medialib/medialibwidget.c index bb3a2ace84..039a6c6952 100644 --- a/plugins/gtkui/medialib/medialibwidget.c +++ b/plugins/gtkui/medialib/medialibwidget.c @@ -161,7 +161,9 @@ _reload_content (w_medialib_viewer_t *mlv) { scriptableItem_t *presets = plugin->get_queries_scriptable (mlv->source); if (presets) { - char *curr_preset = gtkui_medialib_preset_get (); + scriptableModel_t *model = gtkui_medialib_get_model (); + + char *curr_preset = scriptableModelGetAPI (model)->get_active_name (model); if (curr_preset) { preset = scriptableItemSubItemForName (presets, curr_preset); } diff --git a/plugins/gtkui/scriptable/gtkScriptableSelectViewController.c b/plugins/gtkui/scriptable/gtkScriptableSelectViewController.c index 537538dd9c..948929d777 100644 --- a/plugins/gtkui/scriptable/gtkScriptableSelectViewController.c +++ b/plugins/gtkui/scriptable/gtkScriptableSelectViewController.c @@ -138,6 +138,9 @@ gtkScriptableSelectViewControllerSetDelegate ( static void _update_current_from_model (gtkScriptableSelectViewController_t *self) { + if (self->model == NULL) { + return; + } char *preset = self->model_api->get_active_name (self->model); scriptableItem_t *currentPreset = scriptableItemSubItemForName (self->scriptable, preset); if (currentPreset != NULL) { @@ -197,15 +200,16 @@ gtkScriptableSelectViewControllerIndexOfSelectedItem (gtkScriptableSelectViewCon static void _apply_active_selection_to_model (scriptableItem_t *item, gtkScriptableSelectViewController_t *self) { - if (self->model != NULL) { - const char *name = ""; - if (item != NULL) { - name = scriptableItemPropertyValueForKey (item, "name"); - } - self->updating_model = 1; - self->model_api->set_active_name (self->model, name); - self->updating_model = 0; + if (self->model == NULL) { + return; + } + const char *name = ""; + if (item != NULL) { + name = scriptableItemPropertyValueForKey (item, "name"); } + self->updating_model = 1; + self->model_api->set_active_name (self->model, name); + self->updating_model = 0; } static scriptableItem_t *