/* * Copyright (c) 1999-2000, Eric Moon. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions, and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // InfoWindowManager.cpp #include "InfoWindowManager.h" // InfoWindow #include "AppNodeInfoView.h" #include "ConnectionInfoView.h" #include "DormantNodeInfoView.h" #include "EndPointInfoView.h" #include "FileNodeInfoView.h" #include "LiveNodeInfoView.h" #include "InfoWindow.h" // NodeManager #include "AddOnHostProtocol.h" #include "Connection.h" #include "NodeRef.h" // Application Kit #include #include #include // Media Kit #include #include // Support Kit #include __USE_CORTEX_NAMESPACE #include #define D_ACCESS(x) //PRINT (x) #define D_ALLOC(x) //PRINT (x) #define D_INTERNAL(x) //PRINT (x) #define D_MESSAGE(x) //PRINT (x) #define D_WINDOW(x) //PRINT (x) // -------------------------------------------------------- // // internal types // -------------------------------------------------------- // // used to remember window for live nodes struct live_node_window { public: // *** ctor/dtor live_node_window( const NodeRef *ref, BWindow *window) : ref(ref), window(window) { } public: // *** data members const NodeRef *ref; BWindow *window; }; // used to remember windows for dormant nodes struct dormant_node_window { public: // *** ctor/dtor dormant_node_window( const dormant_node_info &info, BWindow *window) : info(info), window(window) { } public: // *** data members const dormant_node_info info; BWindow *window; }; // used to remember windows for connections struct connection_window { public: // *** ctor/dtor connection_window( const media_source &source, const media_destination &destination, BWindow *window) : source(source), destination(destination), window(window) { } public: // *** data members media_source source; media_destination destination; BWindow *window; }; // used to remember windows for media_inputs struct input_window { public: // *** ctor/dtor input_window( const media_destination &destination, BWindow *window) : destination(destination), window(window) { } public: // *** data members media_destination destination; BWindow *window; }; // used to remember windows for media_outputs struct output_window { public: // *** ctor/dtor output_window( const media_source &source, BWindow *window) : source(source), window(window) { } public: // *** data members media_source source; BWindow *window; }; // -------------------------------------------------------- // // static member init // -------------------------------------------------------- // const BPoint InfoWindowManager::M_DEFAULT_OFFSET = BPoint(20.0, 20.0); const BPoint InfoWindowManager::M_INIT_POSITION = BPoint(90.0, 90.0); InfoWindowManager *InfoWindowManager::s_instance = 0; // -------------------------------------------------------- // // *** ctor/dtor // -------------------------------------------------------- // /* hidden */ InfoWindowManager::InfoWindowManager() : BLooper("InfoWindowManager", B_NORMAL_PRIORITY), m_liveNodeWindows(0), m_dormantNodeWindows(0), m_connectionWindows(0), m_inputWindows(0), m_outputWindows(0), m_nextWindowPosition(M_INIT_POSITION) { D_ALLOC(("InfoWindowManager::InfoWindowManager()\n")); Run(); BMediaRoster *roster = BMediaRoster::CurrentRoster(); if (roster) { roster->StartWatching(BMessenger(0, this), B_MEDIA_CONNECTION_BROKEN); } } InfoWindowManager::~InfoWindowManager() { D_ALLOC(("InfoWindowManager::~InfoWindowManager()\n")); BMediaRoster *roster = BMediaRoster::CurrentRoster(); if (roster) { roster->StopWatching(BMessenger(0, this), B_MEDIA_CONNECTION_BROKEN); } if (m_liveNodeWindows) { while (m_liveNodeWindows->CountItems() > 0) { live_node_window *entry = static_cast (m_liveNodeWindows->ItemAt(0)); if (entry && entry->window) { remove_observer(this, entry->ref); BMessenger messenger(0, entry->window); messenger.SendMessage(B_QUIT_REQUESTED); } m_liveNodeWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } delete m_liveNodeWindows; m_liveNodeWindows = 0; } if (m_dormantNodeWindows) { while (m_dormantNodeWindows->CountItems() > 0) { dormant_node_window *entry = static_cast (m_dormantNodeWindows->ItemAt(0)); if (entry && entry->window) { BMessenger messenger(0, entry->window); messenger.SendMessage(B_QUIT_REQUESTED); } m_dormantNodeWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } delete m_dormantNodeWindows; m_dormantNodeWindows = 0; } if (m_connectionWindows) { while (m_connectionWindows->CountItems() > 0) { connection_window *entry = static_cast (m_connectionWindows->ItemAt(0)); if (entry && entry->window) { BMessenger messenger(0, entry->window); messenger.SendMessage(B_QUIT_REQUESTED); } m_connectionWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } delete m_connectionWindows; m_connectionWindows = 0; } if (m_inputWindows) { while (m_inputWindows->CountItems() > 0) { input_window *entry = static_cast (m_inputWindows->ItemAt(0)); if (entry && entry->window) { BMessenger messenger(0, entry->window); messenger.SendMessage(B_QUIT_REQUESTED); } m_inputWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } delete m_inputWindows; m_inputWindows = 0; } if (m_outputWindows) { while (m_outputWindows->CountItems() > 0) { output_window *entry = static_cast (m_outputWindows->ItemAt(0)); if (entry && entry->window) { BMessenger messenger(0, entry->window); messenger.SendMessage(B_QUIT_REQUESTED); } m_outputWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } delete m_outputWindows; m_outputWindows = 0; } } // -------------------------------------------------------- // // *** singleton access // -------------------------------------------------------- // /*static*/ InfoWindowManager *InfoWindowManager::Instance() { D_ACCESS(("InfoWindowManager::Instance()\n")); if (!s_instance) { D_ACCESS((" -> create instance\n")); s_instance = new InfoWindowManager(); } return s_instance; } /* static */ void InfoWindowManager::shutDown() { D_WINDOW(("InfoWindowManager::shutDown()\n")); if (s_instance) { s_instance->Lock(); s_instance->Quit(); s_instance = 0; } } // -------------------------------------------------------- // // *** operations // -------------------------------------------------------- // status_t InfoWindowManager::openWindowFor( const NodeRef *ref) { D_WINDOW(("InfoWindowManager::openWindowFor(live_node)\n")); // make absolutely sure we're locked if (!IsLocked()) { debugger("The looper must be locked !"); } // make sure the ref is valid if (!ref) { return B_ERROR; } BWindow *window = 0; if (_findWindowFor(ref->id(), &window)) { // window for this node already exists, activate it window->SetWorkspaces(B_CURRENT_WORKSPACE); window->Activate(); return B_OK; } BRect frame = InfoView::M_DEFAULT_FRAME; frame.OffsetTo(m_nextWindowPosition); m_nextWindowPosition += M_DEFAULT_OFFSET; window = new InfoWindow(frame); if (_addWindowFor(ref, window)) { // find the correct InfoView sub-class BMediaRoster *roster = BMediaRoster::CurrentRoster(); dormant_node_info dormantNodeInfo; if (ref->kind() & B_FILE_INTERFACE) { window->AddChild(new FileNodeInfoView(ref)); } else if (roster->GetDormantNodeFor(ref->node(), &dormantNodeInfo) != B_OK) { port_info portInfo; app_info appInfo; if ((get_port_info(ref->node().port, &portInfo) == B_OK) && (be_roster->GetRunningAppInfo(portInfo.team, &appInfo) == B_OK)) { app_info thisAppInfo; if ((be_app->GetAppInfo(&thisAppInfo) != B_OK) || ((strcmp(appInfo.signature, thisAppInfo.signature) != 0) && (strcmp(appInfo.signature, addon_host::g_appSignature) != 0))) { window->AddChild(new AppNodeInfoView(ref)); } else { window->AddChild(new LiveNodeInfoView(ref)); } } else { window->AddChild(new LiveNodeInfoView(ref)); } } else { window->AddChild(new LiveNodeInfoView(ref)); } // display the window window->Show(); return B_OK; } // failed delete window; return B_ERROR; } status_t InfoWindowManager::openWindowFor( const dormant_node_info &info) { D_WINDOW(("InfoWindowManager::openWindowFor(dormant_node)\n")); // make absolutely sure we're locked if (!IsLocked()) { debugger("The looper must be locked !"); } BWindow *window = 0; if (_findWindowFor(info, &window)) { // window for this node already exists, activate it window->SetWorkspaces(B_CURRENT_WORKSPACE); window->Activate(); return B_OK; } BRect frame = InfoView::M_DEFAULT_FRAME; frame.OffsetTo(m_nextWindowPosition); m_nextWindowPosition += M_DEFAULT_OFFSET; window = new InfoWindow(frame); if (_addWindowFor(info, window)) { window->AddChild(new DormantNodeInfoView(info)); window->Show(); return B_OK; } // failed delete window; return B_ERROR; } status_t InfoWindowManager::openWindowFor( const Connection &connection) { D_WINDOW(("InfoWindowManager::openWindowFor(connection)\n")); // make absolutely sure we're locked if (!IsLocked()) { debugger("The looper must be locked !"); } BWindow *window = 0; if (_findWindowFor(connection.source(), connection.destination(), &window)) { // window for this node already exists, activate it window->SetWorkspaces(B_CURRENT_WORKSPACE); window->Activate(); return B_OK; } BRect frame = InfoView::M_DEFAULT_FRAME; frame.OffsetTo(m_nextWindowPosition); m_nextWindowPosition += M_DEFAULT_OFFSET; window = new InfoWindow(frame); if (_addWindowFor(connection, window)) { window->AddChild(new ConnectionInfoView(connection)); window->Show(); return B_OK; } // failed delete window; return B_ERROR; } status_t InfoWindowManager::openWindowFor( const media_input &input) { D_WINDOW(("InfoWindowManager::openWindowFor(input)\n")); // make absolutely sure we're locked if (!IsLocked()) { debugger("The looper must be locked !"); } BWindow *window = 0; if (_findWindowFor(input.destination, &window)) { // window for this node already exists, activate it window->SetWorkspaces(B_CURRENT_WORKSPACE); window->Activate(); return B_OK; } BRect frame = InfoView::M_DEFAULT_FRAME; frame.OffsetTo(m_nextWindowPosition); m_nextWindowPosition += M_DEFAULT_OFFSET; window = new InfoWindow(frame); if (_addWindowFor(input, window)) { window->AddChild(new EndPointInfoView(input)); window->Show(); return B_OK; } // failed delete window; return B_ERROR; } status_t InfoWindowManager::openWindowFor( const media_output &output) { D_WINDOW(("InfoWindowManager::openWindowFor(output)\n")); // make absolutely sure we're locked if (!IsLocked()) { debugger("The looper must be locked !"); } BWindow *window = 0; if (_findWindowFor(output.source, &window)) { // window for this node already exists, activate it window->SetWorkspaces(B_CURRENT_WORKSPACE); window->Activate(); return B_OK; } BRect frame = InfoView::M_DEFAULT_FRAME; frame.OffsetTo(m_nextWindowPosition); m_nextWindowPosition += M_DEFAULT_OFFSET; window = new BWindow(frame, "", B_DOCUMENT_WINDOW, 0); if (_addWindowFor(output, window)) { window->AddChild(new EndPointInfoView(output)); window->Show(); return B_OK; } // failed delete window; return B_ERROR; } // -------------------------------------------------------- // // *** BLooper impl // -------------------------------------------------------- // void InfoWindowManager::MessageReceived( BMessage *message) { D_MESSAGE(("InfoWindowManager::MessageReceived()\n")); switch (message->what) { case M_LIVE_NODE_WINDOW_CLOSED: { D_MESSAGE((" -> M_LIVE_NODE_WINDOW_CLOSED\n")); int32 nodeID; if (message->FindInt32("nodeID", &nodeID) != B_OK) { return; } _removeWindowFor(nodeID); break; } case M_DORMANT_NODE_WINDOW_CLOSED: { D_MESSAGE((" -> M_DORMANT_NODE_WINDOW_CLOSED\n")); dormant_node_info info; if (message->FindInt32("addOnID", &info.addon) != B_OK) { return; } if (message->FindInt32("flavorID", &info.flavor_id) != B_OK) { return; } _removeWindowFor(info); break; } case M_CONNECTION_WINDOW_CLOSED: { D_MESSAGE((" -> M_CONNECTION_WINDOW_CLOSED\n")); media_source source; if (message->FindInt32("source_port", &source.port) != B_OK) { return; } if (message->FindInt32("source_id", &source.id) != B_OK) { return; } media_destination destination; if (message->FindInt32("destination_port", &destination.port) != B_OK) { return; } if (message->FindInt32("destination_id", &destination.id) != B_OK) { return; } _removeWindowFor(source, destination); break; } case M_INPUT_WINDOW_CLOSED: { D_MESSAGE((" -> M_INPUT_WINDOW_CLOSED\n")); media_destination destination; if (message->FindInt32("destination_port", &destination.port) != B_OK) { return; } if (message->FindInt32("destination_id", &destination.id) != B_OK) { return; } _removeWindowFor(destination); break; } case M_OUTPUT_WINDOW_CLOSED: { D_MESSAGE((" -> M_OUTPUT_WINDOW_CLOSED\n")); media_source source; if (message->FindInt32("source_port", &source.port) != B_OK) { return; } if (message->FindInt32("source_id", &source.id) != B_OK) { return; } _removeWindowFor(source); break; } case NodeRef::M_RELEASED: { D_MESSAGE((" -> NodeRef::M_RELEASED\n")); int32 nodeID; if (message->FindInt32("nodeID", &nodeID) != B_OK) { return; } BWindow *window; if (_findWindowFor(nodeID, &window)) { window->Lock(); window->Quit(); _removeWindowFor(nodeID); } break; } case B_MEDIA_CONNECTION_BROKEN: { D_MESSAGE((" -> B_MEDIA_CONNECTION_BROKEN\n")); const void *data; ssize_t dataSize; if (message->FindData("source", B_RAW_TYPE, &data, &dataSize) != B_OK) { return; } const media_source source = *reinterpret_cast(data); if (message->FindData("destination", B_RAW_TYPE, &data, &dataSize) != B_OK) { return; } const media_destination destination = *reinterpret_cast(data); BWindow *window; if (_findWindowFor(source, destination, &window)) { window->Lock(); window->Quit(); _removeWindowFor(source, destination); } break; } default: { BLooper::MessageReceived(message); } } } // -------------------------------------------------------- // // *** internal operations // -------------------------------------------------------- // bool InfoWindowManager::_addWindowFor( const NodeRef *ref, BWindow *window) { D_INTERNAL(("InfoWindowManager::_addWindowFor(live_node)\n")); if (!m_liveNodeWindows) { m_liveNodeWindows = new BList(); } live_node_window *entry = new live_node_window(ref, window); if (m_liveNodeWindows->AddItem(reinterpret_cast(entry))) { add_observer(this, entry->ref); return true; } return false; } bool InfoWindowManager::_findWindowFor( int32 nodeID, BWindow **outWindow) { D_INTERNAL(("InfoWindowManager::_findWindowFor(live_node)\n")); if (!m_liveNodeWindows) { return false; } for (int32 i = 0; i < m_liveNodeWindows->CountItems(); i++) { live_node_window *entry = static_cast (m_liveNodeWindows->ItemAt(i)); if (entry->ref->id() == nodeID) { *outWindow = entry->window; return true; } } return false; } void InfoWindowManager::_removeWindowFor( int32 nodeID) { D_INTERNAL(("InfoWindowManager::_removeWindowFor(live_node)\n")); if (!m_liveNodeWindows) { return; } for (int32 i = 0; i < m_liveNodeWindows->CountItems(); i++) { live_node_window *entry = static_cast (m_liveNodeWindows->ItemAt(i)); if (entry->ref->id() == nodeID) { m_liveNodeWindows->RemoveItem(reinterpret_cast(entry)); remove_observer(this, entry->ref); delete entry; } } if (m_liveNodeWindows->CountItems() <= 0) { delete m_liveNodeWindows; m_liveNodeWindows = 0; } } bool InfoWindowManager::_addWindowFor( const dormant_node_info &info, BWindow *window) { D_INTERNAL(("InfoWindowManager::_addWindowFor(dormant_node)\n")); if (!m_dormantNodeWindows) { m_dormantNodeWindows = new BList(); } dormant_node_window *entry = new dormant_node_window(info, window); return m_dormantNodeWindows->AddItem(reinterpret_cast(entry)); } bool InfoWindowManager::_findWindowFor( const dormant_node_info &info, BWindow **outWindow) { D_INTERNAL(("InfoWindowManager::_findWindowFor(dormant_node)\n")); if (!m_dormantNodeWindows) { return false; } for (int32 i = 0; i < m_dormantNodeWindows->CountItems(); i++) { dormant_node_window *entry = static_cast (m_dormantNodeWindows->ItemAt(i)); if ((entry->info.addon == info.addon) && (entry->info.flavor_id == info.flavor_id)) { *outWindow = entry->window; return true; } } return false; } void InfoWindowManager::_removeWindowFor( const dormant_node_info &info) { D_INTERNAL(("InfoWindowManager::_removeWindowFor(dormant_node)\n")); if (!m_dormantNodeWindows) { return; } for (int32 i = 0; i < m_dormantNodeWindows->CountItems(); i++) { dormant_node_window *entry = static_cast (m_dormantNodeWindows->ItemAt(i)); if ((entry->info.addon == info.addon) && (entry->info.flavor_id == info.flavor_id)) { m_dormantNodeWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } } if (m_dormantNodeWindows->CountItems() >= 0) { delete m_dormantNodeWindows; m_dormantNodeWindows = 0; } } bool InfoWindowManager::_addWindowFor( const Connection &connection, BWindow *window) { D_INTERNAL(("InfoWindowManager::_addWindowFor(connection)\n")); if (!m_connectionWindows) { m_connectionWindows = new BList(); } connection_window *entry = new connection_window(connection.source(), connection.destination(), window); return m_connectionWindows->AddItem(reinterpret_cast(entry)); } bool InfoWindowManager::_findWindowFor( const media_source &source, const media_destination &destination, BWindow **outWindow) { D_INTERNAL(("InfoWindowManager::_findWindowFor(connection)\n")); if (!m_connectionWindows) { return false; } for (int32 i = 0; i < m_connectionWindows->CountItems(); i++) { connection_window *entry = static_cast (m_connectionWindows->ItemAt(i)); if ((entry->source == source) && (entry->destination == destination)) { *outWindow = entry->window; return true; } } return false; } void InfoWindowManager::_removeWindowFor( const media_source &source, const media_destination &destination) { D_INTERNAL(("InfoWindowManager::_removeWindowFor(connection)\n")); if (!m_connectionWindows) { return; } for (int32 i = 0; i < m_connectionWindows->CountItems(); i++) { connection_window *entry = static_cast (m_connectionWindows->ItemAt(i)); if ((entry->source == source) && (entry->destination == destination)) { m_connectionWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } } if (m_connectionWindows->CountItems() >= 0) { delete m_connectionWindows; m_connectionWindows = 0; } } bool InfoWindowManager::_addWindowFor( const media_input &input, BWindow *window) { D_INTERNAL(("InfoWindowManager::_addWindowFor(input)\n")); if (!m_inputWindows) { m_inputWindows = new BList(); } input_window *entry = new input_window(input.destination, window); return m_inputWindows->AddItem(reinterpret_cast(entry)); } bool InfoWindowManager::_findWindowFor( const media_destination &destination, BWindow **outWindow) { D_INTERNAL(("InfoWindowManager::_findWindowFor(input)\n")); if (!m_inputWindows) { return false; } for (int32 i = 0; i < m_inputWindows->CountItems(); i++) { input_window *entry = static_cast (m_inputWindows->ItemAt(i)); if (entry->destination == destination) { *outWindow = entry->window; return true; } } return false; } void InfoWindowManager::_removeWindowFor( const media_destination &destination) { D_INTERNAL(("InfoWindowManager::_removeWindowFor(input)\n")); if (!m_inputWindows) { return; } for (int32 i = 0; i < m_inputWindows->CountItems(); i++) { input_window *entry = static_cast (m_inputWindows->ItemAt(i)); if (entry->destination == destination) { m_inputWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } } if (m_inputWindows->CountItems() >= 0) { delete m_inputWindows; m_inputWindows = 0; } } bool InfoWindowManager::_addWindowFor( const media_output &output, BWindow *window) { D_INTERNAL(("InfoWindowManager::_addWindowFor(output)\n")); if (!m_outputWindows) { m_outputWindows = new BList(); } output_window *entry = new output_window(output.source, window); return m_outputWindows->AddItem(reinterpret_cast(entry)); } bool InfoWindowManager::_findWindowFor( const media_source &source, BWindow **outWindow) { D_INTERNAL(("InfoWindowManager::_findWindowFor(output)\n")); if (!m_outputWindows) { return false; } for (int32 i = 0; i < m_outputWindows->CountItems(); i++) { output_window *entry = static_cast (m_outputWindows->ItemAt(i)); if (entry->source == source) { *outWindow = entry->window; return true; } } return false; } void InfoWindowManager::_removeWindowFor( const media_source &source) { D_INTERNAL(("InfoWindowManager::_removeWindowFor(output)\n")); if (!m_outputWindows) { return; } for (int32 i = 0; i < m_outputWindows->CountItems(); i++) { output_window *entry = static_cast (m_outputWindows->ItemAt(i)); if (entry->source == source) { m_outputWindows->RemoveItem(reinterpret_cast(entry)); delete entry; } } if (m_outputWindows->CountItems() >= 0) { delete m_outputWindows; m_outputWindows = 0; } } // END -- InfoWindowManager.cpp --