1 /*
2 * dock.cc
3 * Copyright 2020 John Lindgren
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions, and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions, and the following disclaimer in the documentation
13 * provided with the distribution.
14 *
15 * This software is provided "as is" and without any warranty, express or
16 * implied. In no event shall the authors be liable for any damages arising from
17 * the use of this software.
18 */
19
20 #include "dock.h"
21 #include "libaudqt-internal.h"
22 #include "libaudqt.h"
23
24 #include <assert.h>
25
26 #include <libaudcore/audstrings.h>
27 #include <libaudcore/hook.h>
28 #include <libaudcore/plugins.h>
29 #include <libaudcore/runtime.h>
30
31 namespace audqt
32 {
33
34 class SimpleDockItem : public DockItem
35 {
36 public:
SimpleDockItem(const char * id,const char * name,QWidget * widget)37 SimpleDockItem(const char * id, const char * name, QWidget * widget)
38 : DockItem(id, name, widget)
39 {
40 }
41
user_close()42 void user_close() override { dock_hide_simple(id()); }
43
44 static SimpleDockItem * lookup(const char * id);
45 };
46
47 class PluginItem : public DockItem
48 {
49 public:
PluginItem(PluginHandle * plugin,QWidget * widget)50 PluginItem(PluginHandle * plugin, QWidget * widget)
51 : DockItem(aud_plugin_get_basename(plugin), aud_plugin_get_name(plugin),
52 widget),
53 m_plugin(plugin)
54 {
55 }
56
grab_focus()57 void grab_focus() override
58 {
59 DockItem::grab_focus();
60 // invoke plugin-specific focus handling
61 aud_plugin_send_message(m_plugin, "grab focus", nullptr, 0);
62 }
63
64 // explicitly closing the widget disables the plugin
user_close()65 void user_close() override { aud_plugin_enable(m_plugin, false); }
66
67 static PluginItem * lookup(PluginHandle * plugin);
68
69 private:
70 PluginHandle * m_plugin;
71 };
72
73 static DockHost * s_host = nullptr;
74 static Index<DockItem *> s_items;
75
DockItem(const char * id,const char * name,QWidget * widget)76 EXPORT DockItem::DockItem(const char * id, const char * name, QWidget * widget)
77 : m_id(id), m_name(name), m_widget(widget)
78 {
79 assert(s_host);
80 s_host->add_dock_item(this);
81 s_items.append(this);
82 }
83
~DockItem()84 EXPORT DockItem::~DockItem()
85 {
86 assert(s_host);
87 s_items.remove(s_items.find(this), 1);
88 s_host->remove_dock_item(this);
89 delete m_widget;
90 }
91
grab_focus()92 EXPORT void DockItem::grab_focus()
93 {
94 assert(s_host);
95 s_host->focus_dock_item(this);
96 }
97
find_by_plugin(PluginHandle * plugin)98 EXPORT DockItem * DockItem::find_by_plugin(PluginHandle * plugin)
99 {
100 return PluginItem::lookup(plugin);
101 }
102
lookup(const char * id)103 SimpleDockItem * SimpleDockItem::lookup(const char * id)
104 {
105 for (auto item_ : s_items)
106 {
107 auto item = dynamic_cast<SimpleDockItem *>(item_);
108 if (item && !strcmp(item->id(), id))
109 return item;
110 }
111
112 return nullptr;
113 }
114
dock_show_simple(const char * id,const char * name,QWidget * create ())115 void dock_show_simple(const char * id, const char * name, QWidget * create())
116 {
117 if (!s_host)
118 {
119 AUDWARN("No UI can dock the widget %s\n", id);
120 return;
121 }
122
123 auto cfg_key = str_concat({id, "_visible"});
124 aud_set_bool("audqt", cfg_key, true);
125
126 auto item = SimpleDockItem::lookup(id);
127 if (!item)
128 item = new SimpleDockItem(id, name, create());
129
130 item->grab_focus();
131 }
132
dock_hide_simple(const char * id)133 void dock_hide_simple(const char * id)
134 {
135 auto cfg_key = str_concat({id, "_visible"});
136 aud_set_bool("audqt", cfg_key, false);
137
138 delete SimpleDockItem::lookup(id);
139 }
140
lookup(PluginHandle * plugin)141 PluginItem * PluginItem::lookup(PluginHandle * plugin)
142 {
143 for (auto item_ : s_items)
144 {
145 auto item = dynamic_cast<PluginItem *>(item_);
146 if (item && item->m_plugin == plugin)
147 return item;
148 }
149
150 return nullptr;
151 }
152
add_dock_plugin(void * plugin_,void *)153 static void add_dock_plugin(void * plugin_, void *)
154 {
155 auto plugin = (PluginHandle *)plugin_;
156 auto widget = (QWidget *)aud_plugin_get_qt_widget(plugin);
157 if (widget)
158 new PluginItem(plugin, widget);
159 }
160
remove_dock_plugin(void * plugin_,void *)161 static void remove_dock_plugin(void * plugin_, void *)
162 {
163 auto plugin = (PluginHandle *)plugin_;
164 delete PluginItem::lookup(plugin);
165 }
166
register_dock_host(DockHost * host)167 EXPORT void register_dock_host(DockHost * host)
168 {
169 assert(!s_host);
170 s_host = host;
171
172 if (aud_get_bool("audqt", "eq_presets_visible"))
173 eq_presets_show();
174 if (aud_get_bool("audqt", "equalizer_visible"))
175 equalizer_show();
176 if (aud_get_bool("audqt", "queue_manager_visible"))
177 queue_manager_show();
178
179 for (PluginHandle * plugin : aud_plugin_list(PluginType::General))
180 {
181 if (aud_plugin_get_enabled(plugin))
182 add_dock_plugin(plugin, nullptr);
183 }
184
185 for (PluginHandle * plugin : aud_plugin_list(PluginType::Vis))
186 {
187 if (aud_plugin_get_enabled(plugin))
188 add_dock_plugin(plugin, nullptr);
189 }
190
191 hook_associate("dock plugin enabled", add_dock_plugin, nullptr);
192 hook_associate("dock plugin disabled", remove_dock_plugin, nullptr);
193 }
194
unregister_dock_host()195 EXPORT void unregister_dock_host()
196 {
197 assert(s_host);
198
199 hook_dissociate("dock plugin enabled", add_dock_plugin);
200 hook_dissociate("dock plugin disabled", remove_dock_plugin);
201
202 while (s_items.len() > 0)
203 delete s_items[0];
204
205 s_host = nullptr;
206 }
207
208 } // namespace audqt
209