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 64 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 83 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 */ 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 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*/ 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 */ 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 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 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 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 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 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 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 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 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 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