Changeset 8510f80 in ingen


Ignore:
Timestamp:
10/30/15 10:02:07 (2 years ago)
Author:
David Robillard <d@…>
Branches:
master, groups, nodeless, parallel, parameters, sequencefix
Children:
9c2bb9e0
Parents:
2fe35cd
Message:

Update clients when plugins are unloaded/reloaded

git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5808 a436a847-0d15-0410-975c-d299462d15a1

Files:
2 added
21 edited

Legend:

Unmodified
Added
Removed
  • bundles/ingen.lv2/ingen.ttl

    re1ea991 r8510f80  
    7272    rdfs:label "sprung layout" ; 
    7373    rdfs:comment """Whether or not the graph has a "sprung" force-directed layout.""" . 
     74 
     75ingen:loadedBundle 
     76    a rdf:Property , 
     77        owl:ObjectProperty ; 
     78    rdfs:label "loaded bundle" ; 
     79    rdfs:comment "Whether or not a bundle is loaded into Ingen." . 
    7480 
    7581ingen:value 
  • ingen/client/ClientStore.hpp

    rdd79e76 r8510f80  
    110110    INGEN_SIGNAL(new_object, void, SPtr<ObjectModel>); 
    111111    INGEN_SIGNAL(new_plugin, void, SPtr<PluginModel>); 
     112    INGEN_SIGNAL(plugin_deleted, void, Raul::URI); 
    112113 
    113114private: 
  • src/client/ClientStore.cpp

    r0dff280 r8510f80  
    212212    if (Node::uri_is_path(uri)) { 
    213213        remove_object(Node::uri_to_path(uri)); 
     214    } else { 
     215        Plugins::iterator p = _plugins->find(uri); 
     216        if (p != _plugins->end()) { 
     217            _plugins->erase(p); 
     218            _signal_plugin_deleted.emit(uri); 
     219        } 
    214220    } 
    215221} 
  • src/gui/GraphCanvas.cpp

    r965a74a r8510f80  
    8989    , _human_names(true) 
    9090    , _show_port_names(true) 
     91    , _menu_dirty(false) 
    9192{ 
    9293    Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("canvas_menu"); 
     
    158159    _app.store()->signal_new_plugin().connect( 
    159160        sigc::mem_fun(this, &GraphCanvas::add_plugin)); 
     161    _app.store()->signal_plugin_deleted().connect( 
     162        sigc::mem_fun(this, &GraphCanvas::remove_plugin)); 
    160163 
    161164    // Connect widget signals to do things 
     
    179182    _app.request_plugins_if_necessary(); 
    180183 
    181     if (!_internal_menu) 
     184    if (!_internal_menu || _menu_dirty) 
    182185        build_menus(); 
    183186 
     
    206209 
    207210    // Build skeleton LV2 plugin class heirarchy for 'Plugin' menu 
    208     if (!_plugin_menu) { 
     211    if (_plugin_menu) { 
     212        _plugin_menu->clear(); 
     213    } else { 
    209214        _plugin_menu = Gtk::manage(new PluginMenu(*_app.world())); 
    210215        _menu->items().push_back( 
     
    224229        add_plugin(p.second); 
    225230    } 
     231 
     232    _menu_dirty = false; 
    226233} 
    227234 
     
    306313        _plugin_menu->add_plugin(p); 
    307314    } 
     315} 
     316 
     317void 
     318GraphCanvas::remove_plugin(const Raul::URI& uri) 
     319{ 
     320    // Flag menus as dirty so they will be rebuilt when needed next 
     321    _menu_dirty = true; 
    308322} 
    309323 
  • src/gui/GraphCanvas.hpp

    r3353177 r8510f80  
    6464 
    6565    void add_plugin(SPtr<Client::PluginModel> pm); 
     66    void remove_plugin(const Raul::URI& uri); 
    6667    void add_block(SPtr<const Client::BlockModel> bm); 
    6768    void remove_block(SPtr<const Client::BlockModel> bm); 
     
    150151    bool _human_names; 
    151152    bool _show_port_names; 
     153    bool _menu_dirty; 
    152154}; 
    153155 
  • src/gui/PluginMenu.cpp

    r3353177 r8510f80  
    2626    , _classless_menu(NULL, NULL) 
    2727{ 
     28    clear(); 
     29} 
     30 
     31void 
     32PluginMenu::clear() 
     33{ 
    2834    const LilvWorld*         lworld     = _world.lilv_world(); 
    2935    const LilvPluginClass*   lv2_plugin = lilv_world_get_plugin_class(lworld); 
    3036    const LilvPluginClasses* classes    = lilv_world_get_plugin_classes(lworld); 
    3137 
     38    // Empty completely 
     39    _classless_menu = MenuRecord(NULL, NULL); 
     40    _class_menus.clear(); 
     41    items().clear(); 
     42 
     43    // Build skeleton 
    3244    LV2Children children; 
    3345    LILV_FOREACH(plugin_classes, i, classes) { 
     
    4557    items().push_back(Gtk::Menu_Helpers::MenuElem("_Uncategorized")); 
    4658    _classless_menu.item = &(items().back()); 
    47     _classless_menu.menu = new Gtk::Menu(); 
     59    _classless_menu.menu = Gtk::manage(new Gtk::Menu()); 
    4860    _classless_menu.item->set_submenu(*_classless_menu.menu); 
    4961    _classless_menu.item->hide(); 
     
    110122        Gtk::MenuItem* menu_item = &(menu->items().back()); 
    111123 
    112         Gtk::Menu* submenu = new Gtk::Menu(); 
     124        Gtk::Menu* submenu = Gtk::manage(new Gtk::Menu()); 
    113125        menu_item->set_submenu(*submenu); 
    114126 
  • src/gui/PluginMenu.hpp

    r3353177 r8510f80  
    4444    PluginMenu(Ingen::World& world); 
    4545 
     46    void clear(); 
    4647    void add_plugin(SPtr<Client::PluginModel> p); 
    4748 
  • src/server/BlockFactory.cpp

    r3b22d3c r8510f80  
    6060    ThreadManager::assert_thread(THREAD_PRE_PROCESS); 
    6161    if (!_has_loaded) { 
    62         _has_loaded = true; 
    63         // TODO: Plugin list refreshing 
    6462        load_lv2_plugins(); 
    6563        _has_loaded = true; 
    6664    } 
    6765    return _plugins; 
     66} 
     67 
     68std::set<PluginImpl*> 
     69BlockFactory::refresh() 
     70{ 
     71    // Record current plugins, and those that are currently zombies 
     72    const Plugins         old_plugins(_plugins); 
     73    std::set<PluginImpl*> zombies; 
     74    for (const auto& p : _plugins) { 
     75        if (p.second->is_zombie()) { 
     76            zombies.insert(p.second); 
     77        } 
     78    } 
     79 
     80    // Re-load plugins 
     81    load_lv2_plugins(); 
     82 
     83    // Add any new plugins to response 
     84    std::set<PluginImpl*> new_plugins; 
     85    for (const auto& p : _plugins) { 
     86        Plugins::const_iterator o = old_plugins.find(p.first); 
     87        if (o == old_plugins.end()) { 
     88            new_plugins.insert(p.second); 
     89        } 
     90    } 
     91 
     92    // Add any resurrected plugins to response 
     93    for (const auto& z : zombies) { 
     94        if (!z->is_zombie()) { 
     95            new_plugins.insert(z); 
     96        } 
     97    } 
     98 
     99    return new_plugins; 
    68100} 
    69101 
     
    183215        } 
    184216 
    185         if (_plugins.find(uri) == _plugins.end()) { 
     217        Plugins::iterator p = _plugins.find(uri); 
     218        if (p == _plugins.end()) { 
    186219            LV2Plugin* const plugin = new LV2Plugin(_world, lv2_plug); 
    187220            _plugins.insert(make_pair(uri, plugin)); 
     221        } else if (lilv_plugin_verify(lv2_plug)) { 
     222            p->second->set_is_zombie(false); 
    188223        } 
    189224    } 
  • src/server/BlockFactory.hpp

    r3b22d3c r8510f80  
    1919 
    2020#include <map> 
     21#include <set> 
    2122 
    2223#include "ingen/World.hpp" 
     
    4041    ~BlockFactory(); 
    4142 
     43    /** Reload plugin list. 
     44     * 
     45     * @return The set of newly loaded plugins. 
     46     */ 
     47    std::set<PluginImpl*> refresh(); 
     48 
    4249    void load_plugin(const Raul::URI& uri); 
    4350 
  • src/server/LV2Plugin.cpp

    r67dea1f r8510f80  
    4040    set_property(_uris.rdf_type, _uris.lv2_Plugin); 
    4141 
    42     LilvNode* minor = lilv_world_get(world->lilv_world(), 
    43                                      lilv_plugin_get_uri(lplugin), 
     42    update_properties(); 
     43} 
     44 
     45void 
     46LV2Plugin::update_properties() 
     47{ 
     48    LilvNode* minor = lilv_world_get(_world->lilv_world(), 
     49                                     lilv_plugin_get_uri(_lilv_plugin), 
    4450                                     _uris.lv2_minorVersion, 
    4551                                     NULL); 
    46     LilvNode* micro = lilv_world_get(world->lilv_world(), 
    47                                      lilv_plugin_get_uri(lplugin), 
     52    LilvNode* micro = lilv_world_get(_world->lilv_world(), 
     53                                     lilv_plugin_get_uri(_lilv_plugin), 
    4854                                     _uris.lv2_minorVersion, 
    4955                                     NULL); 
     
    5157    if (lilv_node_is_int(minor) && lilv_node_is_int(micro)) { 
    5258        set_property(_uris.lv2_minorVersion, 
    53                      world->forge().make(lilv_node_as_int(minor))); 
     59                     _world->forge().make(lilv_node_as_int(minor))); 
    5460        set_property(_uris.lv2_microVersion, 
    55                      world->forge().make(lilv_node_as_int(micro))); 
     61                     _world->forge().make(lilv_node_as_int(micro))); 
    5662    } 
    5763 
  • src/server/LV2Plugin.hpp

    r3b22d3c r8510f80  
    5353    const LilvPlugin* lilv_plugin() const { return _lilv_plugin; } 
    5454 
     55    void update_properties(); 
     56 
    5557    void load_presets(); 
     58 
     59    Raul::URI bundle_uri() const { 
     60        const LilvNode* bundle = lilv_plugin_get_bundle_uri(_lilv_plugin); 
     61        return Raul::URI(lilv_node_as_uri(bundle)); 
     62    } 
    5663 
    5764private: 
  • src/server/PluginImpl.hpp

    rdd79e76 r8510f80  
    5050        : Resource(uris, uri) 
    5151        , _type(type) 
     52        , _is_zombie(false) 
    5253    {} 
    5354 
     
    6465    const Atom& type() const            { return _type; } 
    6566    void        set_type(const Atom& t) { _type = t; } 
     67    bool        is_zombie() const       { return _is_zombie; } 
     68    void        set_is_zombie(bool t)   { _is_zombie = t; } 
    6669 
    6770    typedef std::pair<Raul::URI, std::string> Preset; 
     
    7679    } 
    7780 
     81    virtual void update_properties() {} 
     82 
    7883    virtual void load_presets() { _presets_loaded = true; } 
     84 
     85    virtual Raul::URI bundle_uri() const { return Raul::URI("ingen:/"); } 
    7986 
    8087protected: 
     
    8289    Presets _presets; 
    8390    bool    _presets_loaded; 
     91    bool    _is_zombie; 
    8492}; 
    8593 
  • src/server/events/CreateBlock.hpp

    r1a33b80 r8510f80  
    2020#include "ingen/Resource.hpp" 
    2121 
     22#include "ClientUpdate.hpp" 
    2223#include "Event.hpp" 
    23 #include "events/Get.hpp" 
    2424 
    2525namespace Ingen { 
     
    5555    Raul::Path            _path; 
    5656    Resource::Properties& _properties; 
    57     Events::Get::Response _update; 
     57    ClientUpdate          _update; 
    5858    GraphImpl*            _graph; 
    5959    BlockImpl*            _block; 
  • src/server/events/CreateGraph.hpp

    r94d2f7c r8510f80  
    5656    const Raul::Path         _path; 
    5757    Resource::Properties     _properties; 
    58     Events::Get::Response    _update; 
     58    ClientUpdate             _update; 
    5959    GraphImpl*               _graph; 
    6060    GraphImpl*               _parent; 
  • src/server/events/Delta.cpp

    r2fe35cd r8510f80  
    161161 *     patch:subject </> ; 
    162162 *     patch:body [ 
    163  *         ingen:loadedBundle <file:///old.lv2> 
     163 *         ingen:loadedBundle <file:///old.lv2/> 
    164164 *     ] . 
    165165 * 
     
    169169 *     patch:subject </> ; 
    170170 *     patch:remove [ 
    171  *         ingen:loadedBundle <file:///old.lv2> 
     171 *         ingen:loadedBundle <file:///old.lv2/> 
    172172 *     ]; 
    173173 *     patch:add [ 
    174  *         ingen:loadedBundle <file:///new.lv2> 
     174 *         ingen:loadedBundle <file:///new.lv2/> 
    175175 *     ] . 
    176176 * @endcode 
     
    278278            LilvNode*  bundle = get_file_node(lworld, uris, value); 
    279279            if (bundle) { 
     280                for (const auto& p : _engine.block_factory()->plugins()) { 
     281                    if (p.second->bundle_uri() == lilv_node_as_string(bundle)) { 
     282                        p.second->set_is_zombie(true); 
     283                        _update.del(p.second->uri()); 
     284                    } 
     285                } 
    280286                lilv_world_unload_bundle(lworld, bundle); 
     287                _engine.block_factory()->refresh(); 
    281288                lilv_node_free(bundle); 
    282289            } else { 
     
    424431            if (bundle) { 
    425432                lilv_world_load_bundle(lworld, bundle); 
     433                const std::set<PluginImpl*> new_plugins = 
     434                    _engine.block_factory()->refresh(); 
     435 
     436                for (PluginImpl* p : new_plugins) { 
     437                    if (p->bundle_uri() == lilv_node_as_string(bundle)) { 
     438                        _update.put_plugin(p); 
     439                    } 
     440                } 
    426441                lilv_node_free(bundle); 
    427442            } else { 
     
    569584 
    570585    if (respond() == Status::SUCCESS) { 
     586        _update.send(_engine.broadcaster()); 
     587 
    571588        switch (_type) { 
    572589        case Type::SET: 
     
    584601            if (_type == Type::PUT && _subject.substr(0, 5) == "file:") { 
    585602                // Preset save 
    586                 Get::Response response; 
     603                ClientUpdate response; 
    587604                response.put(_preset->uri(), _preset->properties()); 
    588605                response.send(_engine.broadcaster()); 
  • src/server/events/Delta.hpp

    r2fe35cd r8510f80  
    9999    Resource::Properties     _properties; 
    100100    Resource::Properties     _remove; 
     101    ClientUpdate             _update; 
    101102    Ingen::Resource*         _object; 
    102103    GraphImpl*               _graph; 
  • src/server/events/Get.cpp

    r67dea1f r8510f80  
    3434namespace Server { 
    3535namespace Events { 
    36  
    37 void 
    38 Get::Response::put(const Raul::URI&            uri, 
    39                    const Resource::Properties& props, 
    40                    Resource::Graph             ctx) 
    41 { 
    42     const Get::Response::Put put = { uri, props, ctx }; 
    43     puts.push_back(put); 
    44 } 
    45  
    46 void 
    47 Get::Response::put_port(const PortImpl* port) 
    48 { 
    49     if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { 
    50         Resource::Properties props = port->properties(); 
    51         props.erase(port->bufs().uris().ingen_value); 
    52         props.insert(std::make_pair(port->bufs().uris().ingen_value, 
    53                                     port->value())); 
    54         put(port->uri(), props); 
    55     } else { 
    56         put(port->uri(), port->properties()); 
    57     } 
    58 } 
    59  
    60 void 
    61 Get::Response::put_block(const BlockImpl* block) 
    62 { 
    63     const PluginImpl* const plugin = block->plugin_impl(); 
    64     const URIs&             uris   = plugin->uris(); 
    65  
    66     if (uris.ingen_Graph == plugin->type()) { 
    67         put_graph((const GraphImpl*)block); 
    68     } else { 
    69         put(block->uri(), block->properties()); 
    70         for (size_t j = 0; j < block->num_ports(); ++j) { 
    71             put_port(block->port_impl(j)); 
    72         } 
    73     } 
    74 } 
    75  
    76 void 
    77 Get::Response::put_graph(const GraphImpl* graph) 
    78 { 
    79     put(graph->uri(), 
    80         graph->properties(Resource::Graph::INTERNAL), 
    81         Resource::Graph::INTERNAL); 
    82  
    83     put(graph->uri(), 
    84         graph->properties(Resource::Graph::EXTERNAL), 
    85         Resource::Graph::EXTERNAL); 
    86  
    87     // Enqueue blocks 
    88     for (const auto& b : graph->blocks()) { 
    89         put_block(&b); 
    90     } 
    91  
    92     // Enqueue ports 
    93     for (uint32_t i = 0; i < graph->num_ports_non_rt(); ++i) { 
    94         put_port(graph->port_impl(i)); 
    95     } 
    96  
    97     // Enqueue arcs 
    98     for (const auto& a : graph->arcs()) { 
    99         const SPtr<const Arc> arc     = a.second; 
    100         const Connect         connect = { arc->tail_path(), arc->head_path() }; 
    101         connects.push_back(connect); 
    102     } 
    103 } 
    104  
    105 void 
    106 Get::Response::put_plugin(PluginImpl* plugin) 
    107 { 
    108     put(plugin->uri(), plugin->properties()); 
    109  
    110     for (const auto& p : plugin->presets()) { 
    111         put_preset(plugin->uris(), plugin->uri(), p.first, p.second); 
    112     } 
    113 } 
    114  
    115 void 
    116 Get::Response::put_preset(const URIs&        uris, 
    117                           const Raul::URI&   plugin, 
    118                           const Raul::URI&   preset, 
    119                           const std::string& label) 
    120 { 
    121     Resource::Properties props{ 
    122         { uris.rdf_type, uris.pset_Preset.urid }, 
    123         { uris.rdfs_label, uris.forge.alloc(label) }, 
    124         { uris.lv2_appliesTo, uris.forge.make_urid(plugin) }}; 
    125     put(preset, props); 
    126 } 
    127  
    128 /** Returns true if a is closer to the root than b. */ 
    129 static inline bool 
    130 put_higher_than(const Get::Response::Put& a, const Get::Response::Put& b) 
    131 { 
    132     return (std::count(a.uri.begin(), a.uri.end(), '/') < 
    133             std::count(b.uri.begin(), b.uri.end(), '/')); 
    134 } 
    135  
    136 void 
    137 Get::Response::send(Interface* dest) 
    138 { 
    139     // Sort puts by increasing depth so parents are sent first 
    140     std::stable_sort(puts.begin(), puts.end(), put_higher_than); 
    141     for (const Response::Put& put : puts) { 
    142         dest->put(put.uri, put.properties, put.ctx); 
    143     } 
    144     for (const Response::Connect& connect : connects) { 
    145         dest->connect(connect.tail, connect.head); 
    146     } 
    147 } 
    14836 
    14937Get::Get(Engine&          engine, 
  • src/server/events/Get.hpp

    rdd79e76 r8510f80  
    2020#include <vector> 
    2121 
     22#include "BlockFactory.hpp" 
     23#include "ClientUpdate.hpp" 
    2224#include "Event.hpp" 
    23 #include "BlockFactory.hpp" 
    2425#include "types.hpp" 
    2526 
     
    5152    void post_process(); 
    5253 
    53     /** A sequence of puts and connects to respond to client with. 
    54      * This is constructed in the pre_process() and later sent in 
    55      * post_process() to avoid the need to lock. 
    56      * 
    57      * Ideally events (both server and client) would always be in a standard 
    58      * message format so the Ingen protocol went the whole way through the 
    59      * system, but for now things are controlled procedurally through 
    60      * Interface, so this interim structure is necessary. 
    61      */ 
    62     struct Response { 
    63         void put(const Raul::URI&            uri, 
    64                  const Resource::Properties& props, 
    65                  Resource::Graph             ctx=Resource::Graph::DEFAULT); 
    66  
    67         void put_port(const PortImpl* port); 
    68         void put_block(const BlockImpl* block); 
    69         void put_graph(const GraphImpl* graph); 
    70         void put_plugin(PluginImpl* plugin); 
    71         void put_preset(const URIs&        uris, 
    72                         const Raul::URI&   plugin, 
    73                         const Raul::URI&   preset, 
    74                         const std::string& label); 
    75  
    76         void send(Interface* dest); 
    77  
    78         struct Put { 
    79             Raul::URI            uri; 
    80             Resource::Properties properties; 
    81             Resource::Graph      ctx; 
    82         }; 
    83  
    84         struct Connect { 
    85             Raul::Path tail; 
    86             Raul::Path head; 
    87         }; 
    88  
    89         std::vector<Put>     puts; 
    90         std::vector<Connect> connects; 
    91     }; 
    92  
    9354private: 
    9455    const Raul::URI       _uri; 
     
    9657    PluginImpl*           _plugin; 
    9758    BlockFactory::Plugins _plugins; 
    98     Response              _response; 
     59    ClientUpdate          _response; 
    9960}; 
    10061 
  • src/server/internals/Controller.cpp

    r965a74a r8510f80  
    4242} 
    4343 
    44 ControllerNode::ControllerNode(InternalPlugin*     plugin, 
    45                                BufferFactory&      bufs, 
    46                                const Raul::Symbol& symbol, 
    47                                bool                polyphonic, 
    48                                GraphImpl*          parent, 
    49                                SampleRate          srate) 
     44ControllerNode::ControllerNode(InternalPlugin*      plugin, 
     45                               BufferFactory&       bufs, 
     46                               const Raul::Symbol&  symbol, 
     47                               bool                 polyphonic, 
     48                               GraphImpl*           parent, 
     49                               SampleRate           srate) 
    5050    : InternalBlock(plugin, symbol, false, parent, srate) 
    5151    , _learning(false) 
  • src/server/internals/Controller.hpp

    r732bfb33 r8510f80  
    3939{ 
    4040public: 
    41     ControllerNode(InternalPlugin*     plugin, 
    42                    BufferFactory&      bufs, 
    43                    const Raul::Symbol& symbol, 
    44                    bool                polyphonic, 
    45                    GraphImpl*          parent, 
    46                    SampleRate          srate); 
     41    ControllerNode(InternalPlugin*      plugin, 
     42                   BufferFactory&       bufs, 
     43                   const Raul::Symbol&  symbol, 
     44                   bool                 polyphonic, 
     45                   GraphImpl*           parent, 
     46                   SampleRate           srate); 
    4747 
    4848    void run(ProcessContext& context); 
  • src/server/wscript

    r732bfb33 r8510f80  
    1010            Buffer.cpp 
    1111            BufferFactory.cpp 
     12            ClientUpdate.cpp 
    1213            Context.cpp 
    1314            ControlBindings.cpp 
Note: See TracChangeset for help on using the changeset viewer.