1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32 // ParameterWindowManager.cpp
33
34 #include "ParameterWindowManager.h"
35 #include "ParameterWindow.h"
36 // NodeManager
37 #include "NodeRef.h"
38
39 // Application Kit
40 #include <AppDefs.h>
41 // Media Kit
42 #include <MediaRoster.h>
43 // Support Kit
44 #include <List.h>
45
46 __USE_CORTEX_NAMESPACE
47
48 #include <Debug.h>
49 #define D_ACCESS(x) //PRINT (x)
50 #define D_ALLOC(x) //PRINT (x)
51 #define D_INTERNAL(x) //PRINT (x)
52 #define D_MESSAGE(x) //PRINT (x)
53 #define D_WINDOW(x) //PRINT (x)
54
55 // -------------------------------------------------------- //
56 // internal types
57 // -------------------------------------------------------- //
58
59 // used to remember the list of ParameterWindows
60 struct window_map_entry {
61
62 public: // *** ctor/dtor
63
window_map_entrywindow_map_entry64 window_map_entry(
65 const NodeRef *ref,
66 BWindow *window)
67 : ref(ref),
68 window(window)
69 { }
70
71 public: // *** data members
72
73 const NodeRef *ref;
74
75 BWindow *window;
76 };
77
78 // used to remember the list of ControlPanels
79 struct panel_map_entry {
80
81 public: // *** ctor/dtor
82
panel_map_entrypanel_map_entry83 panel_map_entry(
84 int32 id,
85 const BMessenger &messenger)
86 : id(id),
87 messenger(messenger)
88 { }
89
90 public: // *** data members
91
92 int32 id;
93
94 const BMessenger messenger;
95 };
96
97 // -------------------------------------------------------- //
98 // static member init
99 // -------------------------------------------------------- //
100
101 const BPoint ParameterWindowManager::M_DEFAULT_OFFSET = BPoint(20.0, 20.0);
102 const BPoint ParameterWindowManager::M_INIT_POSITION = BPoint(90.0, 90.0);
103
104 ParameterWindowManager *ParameterWindowManager::s_instance = 0;
105
106 // -------------------------------------------------------- //
107 // *** ctor/dtor
108 // -------------------------------------------------------- //
109
110 /* hidden */
ParameterWindowManager()111 ParameterWindowManager::ParameterWindowManager()
112 : BLooper("ParameterWindowManager",
113 B_NORMAL_PRIORITY),
114 m_windowList(0),
115 m_panelList(0),
116 m_lastWindowPosition(M_INIT_POSITION - M_DEFAULT_OFFSET) {
117 D_ALLOC(("ParameterWindowManager::ParameterWindowManager()\n"));
118
119 m_windowList = new BList();
120 m_panelList = new BList();
121 Run();
122 }
123
~ParameterWindowManager()124 ParameterWindowManager::~ParameterWindowManager() {
125 D_ALLOC(("ParameterWindowManager::~ParameterWindowManager()\n"));
126
127 while (m_windowList->CountItems() > 0) {
128 window_map_entry *entry = static_cast<window_map_entry *>
129 (m_windowList->ItemAt(0));
130 if (entry && entry->window) {
131 remove_observer(this, entry->ref);
132 entry->window->Lock();
133 entry->window->Quit();
134 }
135 m_windowList->RemoveItem(reinterpret_cast<void *>(entry));
136 delete entry;
137 }
138 delete m_windowList;
139
140 while (m_panelList->CountItems() > 0) {
141 panel_map_entry *entry = static_cast<panel_map_entry *>
142 (m_panelList->ItemAt(0));
143 if (entry && entry->messenger.IsValid()) {
144 entry->messenger.SendMessage(B_QUIT_REQUESTED);
145 }
146 m_panelList->RemoveItem(reinterpret_cast<void *>(entry));
147 delete entry;
148 }
149 delete m_panelList;
150
151 s_instance = 0;
152 }
153
154 // -------------------------------------------------------- //
155 // *** singleton access
156 // -------------------------------------------------------- //
157
158 /*static*/
Instance()159 ParameterWindowManager *ParameterWindowManager::Instance() {
160 D_ACCESS(("ParameterWindowManager::Instance()\n"));
161
162 if (!s_instance) {
163 D_ACCESS((" -> create instance\n"));
164 s_instance = new ParameterWindowManager();
165 }
166
167 return s_instance;
168 }
169
170 /* static */
shutDown()171 void ParameterWindowManager::shutDown() {
172 D_WINDOW(("ParameterWindowManager::shutDown()\n"));
173
174 if (s_instance) {
175 s_instance->Lock();
176 s_instance->Quit();
177 }
178 }
179
180 // -------------------------------------------------------- //
181 // *** operations
182 // -------------------------------------------------------- //
183
openWindowFor(const NodeRef * ref)184 status_t ParameterWindowManager::openWindowFor(
185 const NodeRef *ref) {
186 D_WINDOW(("ParameterWindowManager::openWindowFor()\n"));
187
188 // make absolutely sure we're locked
189 if (!IsLocked()) {
190 debugger("The looper must be locked !");
191 }
192
193 // make sure the ref is valid
194 if (!ref) {
195 return B_ERROR;
196 }
197
198 BWindow *window = 0;
199 if (_findWindowFor(ref->id(), &window)) {
200 // window for this node already exists, activate it
201 window->SetWorkspaces(B_CURRENT_WORKSPACE);
202 window->Activate();
203 return B_OK;
204 }
205
206 BMessenger messenger(0, this);
207 live_node_info nodeInfo = ref->nodeInfo();
208 m_lastWindowPosition += M_DEFAULT_OFFSET;
209 window = new ParameterWindow(m_lastWindowPosition,
210 nodeInfo, &messenger);
211 if (_addWindowFor(ref, window)) {
212 window->Show();
213 return B_OK;
214 }
215 delete window;
216
217 return B_ERROR;
218 }
219
startControlPanelFor(const NodeRef * ref)220 status_t ParameterWindowManager::startControlPanelFor(
221 const NodeRef *ref) {
222 D_WINDOW(("ParameterWindowManager::startControlPanelFor()\n"));
223
224 // make absolutely sure we're locked
225 if (!IsLocked()) {
226 debugger("The looper must be locked !");
227 }
228
229 BMediaRoster *roster = BMediaRoster::CurrentRoster();
230 if (!roster) {
231 D_WINDOW((" -> MediaRoster not available\n"));
232 return B_ERROR;
233 }
234
235 BMessenger messenger;
236 if (_findPanelFor(ref->id(), &messenger)) {
237 // find out if the messengers target still exists
238 if (messenger.IsValid()) {
239 return B_OK;
240 }
241 else {
242 _removePanelFor(ref->id());
243 }
244 }
245
246 status_t error = roster->StartControlPanel(ref->node(),
247 &messenger);
248 if (error) {
249 D_INTERNAL((" -> StartControlPanel() failed (%s)\n",
250 strerror(error)));
251 return error;
252 }
253
254 _addPanelFor(ref->id(), messenger);
255 return B_OK;
256 }
257
258 // -------------------------------------------------------- //
259 // *** BLooper impl
260 // -------------------------------------------------------- //
261
MessageReceived(BMessage * message)262 void ParameterWindowManager::MessageReceived(
263 BMessage *message) {
264 D_MESSAGE(("ParameterWindowManager::MessageReceived()\n"));
265
266 switch (message->what) {
267 case ParameterWindow::M_CLOSED: {
268 D_MESSAGE((" -> ParameterWindow::M_CLOSED\n"));
269 int32 nodeID;
270 if (message->FindInt32("nodeID", &nodeID) != B_OK) {
271 return;
272 }
273 _removeWindowFor(nodeID);
274 break;
275 }
276 case ParameterWindow::M_CONTROL_PANEL_STARTED: {
277 D_MESSAGE((" -> ParameterWindow::M_CONTROL_PANEL_STARTED\n"));
278 int32 nodeID;
279 if (message->FindInt32("nodeID", &nodeID) != B_OK) {
280 return;
281 }
282 BMessenger messenger;
283 if (message->FindMessenger("messenger", &messenger) != B_OK) {
284 return;
285 }
286 _addPanelFor(nodeID, messenger);
287 break;
288 }
289 case NodeRef::M_RELEASED: {
290 D_MESSAGE((" -> NodeRef::M_RELEASED\n"));
291 int32 nodeID;
292 if (message->FindInt32("nodeID", &nodeID) != B_OK) {
293 return;
294 }
295 BWindow *window;
296 if (_findWindowFor(nodeID, &window)) {
297 window->Lock();
298 window->Quit();
299 _removeWindowFor(nodeID);
300 }
301 break;
302 }
303 default: {
304 BLooper::MessageReceived(message);
305 }
306 }
307 }
308
309 // -------------------------------------------------------- //
310 // *** internal operations
311 // -------------------------------------------------------- //
312
_addWindowFor(const NodeRef * ref,BWindow * window)313 bool ParameterWindowManager::_addWindowFor(
314 const NodeRef *ref,
315 BWindow *window) {
316 D_INTERNAL(("ParameterWindowManager::_addWindowFor()\n"));
317
318 window_map_entry *entry = new window_map_entry(ref,
319 window);
320 if (m_windowList->AddItem(reinterpret_cast<void *>(entry))) {
321 add_observer(this, entry->ref);
322 return true;
323 }
324
325 return false;
326 }
327
_findWindowFor(int32 id,BWindow ** outWindow)328 bool ParameterWindowManager::_findWindowFor(
329 int32 id,
330 BWindow **outWindow) {
331 D_INTERNAL(("ParameterWindowManager::_findWindowFor()\n"));
332
333 for (int32 i = 0; i < m_windowList->CountItems(); i++) {
334 window_map_entry *entry = static_cast<window_map_entry *>
335 (m_windowList->ItemAt(i));
336 if (entry->ref->id() == id) {
337 *outWindow = entry->window;
338 return true;
339 }
340 }
341
342 return false;
343 }
344
_removeWindowFor(int32 id)345 void ParameterWindowManager::_removeWindowFor(
346 int32 id) {
347 D_INTERNAL(("ParameterWindowManager::_removeWindowFor()\n"));
348
349 for (int32 i = 0; i < m_windowList->CountItems(); i++) {
350 window_map_entry *entry = static_cast<window_map_entry *>
351 (m_windowList->ItemAt(i));
352 if (entry->ref->id() == id) {
353 m_windowList->RemoveItem(reinterpret_cast<void *>(entry));
354 remove_observer(this, entry->ref);
355 delete entry;
356 }
357 }
358
359 // try to shutdown
360 if (m_windowList->CountItems() == 0) {
361 int32 i = 0;
362 while (true) {
363 // take all invalid messengers out of the panel list
364 panel_map_entry *entry = static_cast<panel_map_entry *>
365 (m_panelList->ItemAt(i));
366 if (!entry) {
367 // end of list
368 break;
369 }
370 if (!entry->messenger.IsValid()) {
371 // this control panel doesn't exist anymore
372 m_panelList->RemoveItem(entry);
373 continue;
374 }
375 }
376 if (m_panelList->CountItems() == 0) {
377 // neither windows nor panels to manage, go to sleep
378 PostMessage(B_QUIT_REQUESTED);
379 }
380 }
381 }
382
_addPanelFor(int32 id,const BMessenger & messenger)383 bool ParameterWindowManager::_addPanelFor(
384 int32 id,
385 const BMessenger &messenger) {
386 D_INTERNAL(("ParameterWindowManager::_addPanelFor()\n"));
387
388 panel_map_entry *entry = new panel_map_entry(id,
389 messenger);
390 if (m_panelList->AddItem(reinterpret_cast<void *>(entry))) {
391 return true;
392 }
393
394 return false;
395 }
396
_findPanelFor(int32 id,BMessenger * outMessenger)397 bool ParameterWindowManager::_findPanelFor(
398 int32 id,
399 BMessenger *outMessenger) {
400 D_INTERNAL(("ParameterWindowManager::_findPanelFor()\n"));
401
402 for (int32 i = 0; i < m_panelList->CountItems(); i++) {
403 panel_map_entry *entry = static_cast<panel_map_entry *>
404 (m_panelList->ItemAt(i));
405 if (entry->id == id) {
406 *outMessenger = entry->messenger;
407 return true;
408 }
409 }
410
411 return false;
412 }
413
_removePanelFor(int32 id)414 void ParameterWindowManager::_removePanelFor(
415 int32 id) {
416 D_INTERNAL(("ParameterWindowManager::_removeWindowFor()\n"));
417
418 for (int32 i = 0; i < m_panelList->CountItems(); i++) {
419 panel_map_entry *entry = static_cast<panel_map_entry *>
420 (m_panelList->ItemAt(i));
421 if (entry->id == id) {
422 m_panelList->RemoveItem(reinterpret_cast<void *>(entry));
423 delete entry;
424 }
425 }
426 }
427
428 // END -- ParameterWindowManager.cpp --
429