btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / cortex / MediaRoutingView / MediaRoutingView.cpp
blobd9d060a3e909552cd8b1284ddf8a224b41e742f7
1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
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.
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.
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.
32 // MediaRoutingView.cpp
34 #include "MediaRoutingView.h"
36 // RouteApp
37 #include "RouteApp.h"
38 #include "RouteAppNodeManager.h"
39 #include "RouteWindow.h"
40 #include "NodeSetIOContext.h"
41 // DormantNodeView
42 #include "DormantNodeView.h"
43 // InfoWindow
44 #include "InfoWindowManager.h"
45 // TransportWindow
46 #include "TransportWindow.h"
47 // MediaRoutingView
48 #include "MediaNodePanel.h"
49 #include "MediaWire.h"
50 // NodeManager
51 #include "NodeGroup.h"
52 #include "NodeRef.h"
53 #include "Connection.h"
54 // ParameterWindow
55 #include "ParameterWindowManager.h"
57 // Application Kit
58 #include <Application.h>
59 // Interface Kit
60 #include <Alert.h>
61 #include <Bitmap.h>
62 #include <MenuItem.h>
63 #include <PopUpMenu.h>
64 #include <Window.h>
65 // Media Kit
66 #include <MediaRoster.h>
67 // Storage Kit
68 #include <File.h>
69 #include <NodeInfo.h>
70 #include <Path.h>
71 // Translation Kit
72 #include <BitmapStream.h>
73 #include <TranslatorRoster.h>
75 __USE_CORTEX_NAMESPACE
77 #include <Debug.h>
78 #define D_METHOD(x) //PRINT (x)
79 #define D_MESSAGE(x) //PRINT (x)
80 #define D_MOUSE(x) //PRINT (x)
81 #define D_KEY(x) //PRINT (x)
83 // ---------------------------------------------------------------- //
84 // constants
85 // ---------------------------------------------------------------- //
87 float MediaRoutingView::M_CLEANUP_H_GAP = 25.0;
88 float MediaRoutingView::M_CLEANUP_V_GAP = 10.0;
89 float MediaRoutingView::M_CLEANUP_H_MARGIN = 15.0;
90 float MediaRoutingView::M_CLEANUP_V_MARGIN = 10.0;
92 // ---------------------------------------------------------------- //
93 // m_inactiveNodeState content
94 // ---------------------------------------------------------------- //
96 struct _inactive_node_state_entry {
97 _inactive_node_state_entry(
98 const char* _name, int32 _kind, const BMessage& _state) :
99 name(_name), kind(_kind), state(_state) {}
101 BString name;
102 uint32 kind;
103 BMessage state;
106 // ---------------------------------------------------------------- //
107 // ctor/dtor
108 // ---------------------------------------------------------------- //
110 MediaRoutingView::MediaRoutingView(
111 RouteAppNodeManager *nodeManager,
112 BRect frame,
113 const char *name,
114 uint32 resizeMode)
115 : DiagramView(frame, "MediaRoutingView", true, B_FOLLOW_ALL_SIDES),
116 manager(nodeManager),
117 m_layout(M_ICON_VIEW),
118 m_nextGroupNumber(1),
119 m_lastDroppedNode(0),
120 m_draggedWire(0)
122 D_METHOD(("MediaRoutingView::MediaRoutingView()\n"));
123 ASSERT(manager);
125 setBackgroundColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_2_TINT));
126 SetItemAlignment(5.0, 5.0);
127 _initLayout();
130 MediaRoutingView::~MediaRoutingView() {
131 D_METHOD(("MediaRoutingView::~MediaRoutingView()\n"));
133 _emptyInactiveNodeState();
135 // quit ParameterWindowManager if necessary
136 ParameterWindowManager::shutDown();
138 // quit InfoWindowManager if necessary
139 InfoWindowManager::shutDown();
142 // -------------------------------------------------------- //
143 // *** derived from DiagramView
144 // -------------------------------------------------------- //
146 void MediaRoutingView::connectionAborted(
147 DiagramEndPoint *fromWhich)
149 D_METHOD(("MediaRoutingView::connectionAborted()\n"));
151 be_app->SetCursor(B_HAND_CURSOR);
154 void MediaRoutingView::connectionEstablished(
155 DiagramEndPoint *fromWhich,
156 DiagramEndPoint *toWhich)
158 D_METHOD(("MediaRoutingView::connectionEstablished()\n"));
160 be_app->SetCursor(B_HAND_CURSOR);
163 DiagramWire *MediaRoutingView::createWire(
164 DiagramEndPoint *fromWhich,
165 DiagramEndPoint *toWhich)
167 D_METHOD(("MediaRoutingView::createWire()\n"));
169 MediaJack *outputJack, *inputJack;
170 MediaJack *jack = dynamic_cast<MediaJack *>(fromWhich);
172 if (jack == NULL)
173 return 0;
175 if (jack->isOutput())
177 outputJack = jack;
178 inputJack = dynamic_cast<MediaJack *>(toWhich);
179 if (!inputJack || !inputJack->isInput())
181 return 0;
184 else
186 inputJack = jack;
187 outputJack = dynamic_cast<MediaJack *>(toWhich);
188 if (!outputJack || !outputJack->isOutput())
190 return 0;
193 if (!outputJack->isConnected() && !inputJack->isConnected())
195 media_output output;
196 media_input input;
197 if ((outputJack->getOutput(&output) == B_OK)
198 && (inputJack->getInput(&input) == B_OK))
200 status_t error;
201 Connection connection;
202 error = manager->connect(output, input, &connection);
203 /* if (error)
205 showErrorMessage("Could not connect", error);
207 */ }
209 return 0;
212 DiagramWire *MediaRoutingView::createWire(
213 DiagramEndPoint *fromWhich)
215 D_METHOD(("MediaRoutingView::createWire(temp)\n"));
217 MediaJack *jack = dynamic_cast<MediaJack *>(fromWhich);
218 if (jack)
220 if (jack->isOutput()) // this is the start point
222 return new MediaWire(jack, true);
224 else
226 return new MediaWire(jack, false);
229 return 0;
233 void
234 MediaRoutingView::BackgroundMouseDown(BPoint point, uint32 buttons,
235 uint32 clicks)
237 D_MOUSE(("MediaRoutingView::BackgroundMouseDown()\n"));
239 if ((buttons == B_SECONDARY_MOUSE_BUTTON)
240 || (modifiers() & B_CONTROL_KEY)) {
241 EndRectTracking();
242 showContextMenu(point);
247 void
248 MediaRoutingView::MessageDropped(BPoint point, BMessage *message)
250 D_METHOD(("MediaRoutingView::MessageDropped()\n"));
252 switch (message->what) {
253 case DormantNodeView::M_INSTANTIATE_NODE:
255 D_MESSAGE(("MediaRoutingView::MessageDropped(DormantNodeView::M_INSTANTIATE_NODE)\n"));
256 type_code type;
257 int32 count;
258 if (message->GetInfo("which", &type, &count) == B_OK) {
259 for (int32 n = 0; n < count; n++) {
260 dormant_node_info info;
261 const void *data;
262 ssize_t dataSize;
263 if (message->FindData("which", B_RAW_TYPE, &data, &dataSize) == B_OK) {
264 memcpy(reinterpret_cast<void *>(&info), data, dataSize);
265 NodeRef* droppedNode;
266 status_t error;
267 error = manager->instantiate(info, &droppedNode);
268 if (!error) {
269 m_lastDroppedNode = droppedNode->id();
270 BPoint dropPoint, dropOffset;
271 dropPoint = message->DropPoint(&dropOffset);
272 m_lastDropPoint = Align(ConvertFromScreen(dropPoint - dropOffset));
273 } else {
274 BString s;
275 s << "Could not instantiate '" << info.name << "'";
276 showErrorMessage(s, error);
281 break;
284 case B_SIMPLE_DATA:
286 D_MESSAGE(("MediaRoutingView::MessageDropped(B_SIMPLE_DATA)\n"));
287 entry_ref fileRef;
288 if (message->FindRef("refs", &fileRef) == B_OK)
289 _checkDroppedFile(&fileRef, ConvertFromScreen(message->DropPoint()));
290 break;
293 case B_PASTE:
295 D_MESSAGE(("MediaRoutingView::MessageDropped(B_PASTE)\n"));
296 ssize_t size;
297 const rgb_color *color; // [e.moon 21nov99] fixed const error
298 if (message->FindData("RGBColor", B_RGB_COLOR_TYPE,
299 reinterpret_cast<const void **>(&color), &size) == B_OK)
300 _changeBackground(*color);
301 break;
304 default:
305 DiagramView::MessageDropped(point, message);
310 void
311 MediaRoutingView::SelectionChanged()
313 D_METHOD(("MediaRoutingView::selectionChanged()\n"));
314 _broadcastSelection();
317 // ---------------------------------------------------------------- //
318 // *** BView impl.
319 // ---------------------------------------------------------------- //
321 void MediaRoutingView::AttachedToWindow()
323 D_METHOD(("MediaRoutingView::AttachedToWindow()\n"));
324 _inherited::AttachedToWindow();
326 // attach to manager
327 ASSERT(manager);
328 add_observer(this, manager);
330 // add the context-menu shortcuts to the window
331 _addShortcuts();
333 // populate with existing nodes & connections
334 _initContent();
336 // [e.moon 29nov99] moved from AllAttached()
337 cleanUp();
340 void MediaRoutingView::AllAttached()
342 D_METHOD(("MediaRoutingView::AllAttached()\n"));
343 _inherited::AllAttached();
345 _adjustScrollBars();
347 // grab keyboard events
348 MakeFocus();
351 void MediaRoutingView::DetachedFromWindow()
353 D_METHOD(("MediaRoutingView::DetachedFromWindow()\n"));
354 _inherited::DetachedFromWindow();
356 status_t error;
358 // detach from manager
359 if (manager)
361 Autolock lock(manager);
362 void *cookie = 0;
363 NodeRef *ref;
364 while (manager->getNextRef(&ref, &cookie) == B_OK)
366 remove_observer(this, ref);
368 error = remove_observer(this, manager);
369 const_cast<RouteAppNodeManager *&>(manager) = 0;
373 void MediaRoutingView::KeyDown(
374 const char *bytes,
375 int32 numBytes)
377 D_METHOD(("MediaRoutingView::KeyDown()\n"));
379 switch (bytes[0])
381 case B_ENTER:
383 D_KEY(("MediaRoutingView::KeyDown(B_ENTER)\n"));
384 _openParameterWindowsForSelection();
385 break;
387 case B_DELETE:
389 D_KEY(("MediaRoutingView::KeyDown(B_DELETE)\n"));
390 _deleteSelection();
391 break;
393 case B_SPACE:
395 // [e.moon 1dec99]
396 BWindow* w = Window();
397 ASSERT(w);
398 BMessenger(w).SendMessage(RouteWindow::M_TOGGLE_GROUP_ROLLING);
399 break;
401 default:
403 DiagramView::KeyDown(bytes, numBytes);
404 break;
409 void MediaRoutingView::Pulse()
411 // do the animation
414 // ---------------------------------------------------------------- //
415 // BHandler impl
416 // ---------------------------------------------------------------- //
418 void MediaRoutingView::MessageReceived(
419 BMessage* message)
421 D_METHOD(("MediaRoutingView::MessageReceived()\n"));
423 switch (message->what)
425 case B_MEDIA_NODE_CREATED:
427 D_MESSAGE(("MediaRoutingView::MessageReceived(B_MEDIA_NODE_CREATED)\n"));
428 type_code type;
429 int32 count;
430 if (message->GetInfo("media_node_id", &type, &count) == B_OK)
432 for(int32 n = 0; n < count; n++)
434 int32 id;
435 if (message->FindInt32("media_node_id", n, &id) == B_OK)
437 // [e.moon 8dec99] allow for existing panel
438 MediaNodePanel* panel;
439 if(_findPanelFor(id, &panel) < B_OK)
440 _addPanelFor(id, BPoint(5.0, 5.0));
444 break;
446 case B_MEDIA_NODE_DELETED:
448 D_MESSAGE(("MediaRoutingView::MessageReceived(B_MEDIA_NODE_DELETED)\n"));
449 type_code type;
450 int32 count;
451 if (message->GetInfo("media_node_id", &type, &count) == B_OK)
453 for (int32 n = 0; n < count; n++)
455 int32 id;
456 if (message->FindInt32("media_node_id", n, &id) == B_OK)
458 _removePanelFor(id);
462 break;
464 case B_MEDIA_CONNECTION_MADE:
466 D_MESSAGE(("MediaRoutingView::MessageReceived(B_MEDIA_CONNECTION_MADE)\n"));
467 type_code type;
468 int32 count;
469 if (message->GetInfo("output", &type, &count) == B_OK)
471 for (int32 n = 0; n < count; n++)
473 media_output output;
474 const void *data;
475 ssize_t dataSize;
476 if (message->FindData("output", B_RAW_TYPE, n, &data, &dataSize) == B_OK)
478 output = *reinterpret_cast<const media_output *>(data);
479 Connection connection;
480 if (manager->findConnection(output.node.node, output.source, &connection) == B_OK)
482 _addWireFor(connection);
487 break;
489 case B_MEDIA_CONNECTION_BROKEN:
491 D_MESSAGE(("MediaRoutingView::MessageReceived(B_MEDIA_CONNECTION_BROKEN)\n"));
492 type_code type;
493 int32 count;
494 if (message->GetInfo("__connection_id", &type, &count) == B_OK)
496 for (int32 n = 0; n < count; n++)
498 int32 id;
499 if (message->FindInt32("__connection_id", n, &id) == B_OK)
501 _removeWireFor(id);
505 break;
507 case B_MEDIA_FORMAT_CHANGED:
509 D_MESSAGE(("MediaRoutingView::MessageReceived(B_MEDIA_FORMAT_CHANGED)\n"));
511 media_node_id nodeID;
512 if(message->FindInt32("__source_node_id", &nodeID) < B_OK)
513 break;
515 uint32 connectionID;
516 if(message->FindInt32("__connection_id", (int32*)&connectionID) < B_OK)
517 break;
519 media_source* source;
520 ssize_t dataSize;
521 if(message->FindData("be:source", B_RAW_TYPE, (const void**)&source, &dataSize) < B_OK)
522 break;
524 MediaWire* wire;
525 if(_findWireFor(connectionID, &wire) == B_OK) {
526 // copy new connection data
527 manager->findConnection(nodeID, *source, &wire->connection);
529 break;
531 case M_CLEANUP_REQUESTED:
533 D_MESSAGE(("MediaRoutingView::MessageReceived(M_M_CLEANUP_REQUESTED)\n"));
534 cleanUp();
535 break;
537 case M_SELECT_ALL:
539 D_MESSAGE(("MediaRoutingView::MessageReceived(M_SELECT_ALL)\n"));
540 SelectAll(DiagramItem::M_BOX);
541 break;
543 case M_DELETE_SELECTION:
545 D_MESSAGE(("MediaRoutingView::MessageReceived(M_DELETE_SELECTION)\n"));
546 _deleteSelection();
547 break;
549 case M_NODE_CHANGE_CYCLING:
551 D_MESSAGE(("MediaRoutingView::MessageReceived(M_NODE_CYCLING_CHANGED)\n"));
552 bool cycle;
553 if (message->FindBool("cycle", &cycle) == B_OK)
555 _changeCyclingForSelection(cycle);
557 break;
559 case M_NODE_CHANGE_RUN_MODE:
561 D_MESSAGE(("MediaRoutingView::MessageReceived(M_NODE_RUNMODE_CHANGED)\n"));
562 int32 mode;
563 if (message->FindInt32("run_mode", &mode) == B_OK)
565 _changeRunModeForSelection(static_cast<uint32>(mode));
567 break;
569 case M_LAYOUT_CHANGED:
571 D_MESSAGE(("MediaRoutingView::MessageReceived(M_LAYOUT_CHANGED)\n"));
572 layout_t layout;
573 if (message->FindInt32("layout", (int32*)&layout) == B_OK)
575 if (layout != m_layout)
577 layoutChanged(layout);
578 updateDataRect();
579 Invalidate();
582 break;
584 case M_NODE_START_TIME_SOURCE:
586 D_MESSAGE(("MediaRoutingView::MessageReceived(M_NODE_START_TIME_SOURCE)\n"));
587 int32 id;
588 if(message->FindInt32("nodeID", &id) < B_OK)
589 break;
590 NodeRef* ref;
591 if(manager->getNodeRef(id, &ref) < B_OK)
592 break;
594 bigtime_t when = system_time();
595 status_t err = manager->roster->StartTimeSource(ref->node(), when);
596 if(err < B_OK) {
597 PRINT((
598 "! StartTimeSource(%" B_PRId32 "): '%s'\n",
599 ref->id(), strerror(err)));
601 break;
603 case M_NODE_STOP_TIME_SOURCE:
605 D_MESSAGE(("MediaRoutingView::MessageReceived(M_NODE_STOP_TIME_SOURCE)\n"));
606 int32 id;
607 if(message->FindInt32("nodeID", &id) < B_OK)
608 break;
609 NodeRef* ref;
610 if(manager->getNodeRef(id, &ref) < B_OK)
611 break;
613 bigtime_t when = system_time();
614 status_t err = manager->roster->StopTimeSource(ref->node(), when);
615 if(err < B_OK) {
616 PRINT((
617 "! StopTimeSource(%" B_PRId32 "): '%s'\n",
618 ref->id(), strerror(err)));
620 break;
622 case M_NODE_TWEAK_PARAMETERS: {
623 D_MESSAGE((" -> M_NODE_TWEAK_PARAMETERS\n"));
624 _openParameterWindowsForSelection();
625 break;
627 case M_NODE_START_CONTROL_PANEL: {
628 D_MESSAGE((" -> M_NODE_START_CONTROL_PANEL\n"));
629 _startControlPanelsForSelection();
630 break;
632 case M_GROUP_SET_LOCKED:
634 D_MESSAGE(("MediaRoutingView::MessageReceived(M_GROUP_SET_LOCKED)\n"));
635 int32 groupID;
636 if(message->FindInt32("groupID", &groupID) < B_OK)
637 break;
638 bool locked;
639 if(message->FindBool("locked", &locked) < B_OK)
640 break;
641 NodeGroup* group;
642 if(manager->findGroup(groupID, &group) < B_OK)
643 break;
644 uint32 f = locked ?
645 group->groupFlags() | NodeGroup::GROUP_LOCKED :
646 group->groupFlags() & ~NodeGroup::GROUP_LOCKED;
647 group->setGroupFlags(f);
648 break;
650 case M_BROADCAST_SELECTION: {
651 D_MESSAGE((" -> M_BROADCAST_SELECTION\n"));
652 _broadcastSelection();
653 break;
655 case InfoWindowManager::M_INFO_WINDOW_REQUESTED:
657 D_MESSAGE(("MediaRoutingView::MessageReceived(InfoView::M_INFO_WINDOW_REQUESTED)\n"));
658 type_code type;
659 int32 count;
660 if (message->GetInfo("input", &type, &count) == B_OK)
662 for (int32 i = 0; i < count; i++)
664 media_input input;
665 const void *data;
666 ssize_t dataSize;
667 if (message->FindData("input", B_RAW_TYPE, i, &data, &dataSize) == B_OK)
669 input = *reinterpret_cast<const media_input *>(data);
670 InfoWindowManager *manager = InfoWindowManager::Instance();
671 if (manager && manager->Lock()) {
672 manager->openWindowFor(input);
673 manager->Unlock();
678 else if (message->GetInfo("output", &type, &count) == B_OK)
680 for (int32 i = 0; i < count; i++)
682 media_output output;
683 const void *data;
684 ssize_t dataSize;
685 if (message->FindData("output", B_RAW_TYPE, i, &data, &dataSize) == B_OK)
687 output = *reinterpret_cast<const media_output *>(data);
688 InfoWindowManager *manager = InfoWindowManager::Instance();
689 if (manager && manager->Lock()) {
690 manager->openWindowFor(output);
691 manager->Unlock();
696 else
698 _openInfoWindowsForSelection();
700 break;
702 case NodeManager::M_RELEASED:
704 D_MESSAGE(("MediaRoutingView::MessageReceived(NodeManager::M_RELEASED)\n"));
705 remove_observer(this, manager);
706 const_cast<RouteAppNodeManager*&>(manager) = 0;
707 // +++++ disable view!
708 break;
710 case NodeRef::M_RELEASED:
712 D_MESSAGE(("MediaRoutingView::MessageReceived(NodeRef::M_RELEASED)\n"));
713 // only relevant on shutdown; do nothing
714 break;
716 default:
718 DiagramView::MessageReceived(message);
723 // ---------------------------------------------------------------- //
724 // *** operations (public)
725 // ---------------------------------------------------------------- //
727 BPoint MediaRoutingView::findFreePositionFor(
728 const MediaNodePanel* panel) const
730 D_METHOD(("MediaRoutingView::_findFreeSpotFor()\n"));
732 BPoint p(M_CLEANUP_H_MARGIN, M_CLEANUP_V_MARGIN);
733 if (panel)
735 switch (m_layout)
737 case M_ICON_VIEW:
739 // find the target column by node_kind
740 p.x += M_CLEANUP_H_GAP + MediaNodePanel::M_DEFAULT_WIDTH;
741 if (panel->ref->kind() & B_BUFFER_PRODUCER)
743 p.x -= M_CLEANUP_H_GAP + MediaNodePanel::M_DEFAULT_WIDTH;
745 if (panel->ref->kind() & B_BUFFER_CONSUMER)
747 p.x += M_CLEANUP_H_GAP + MediaNodePanel::M_DEFAULT_WIDTH;
749 // find the bottom item in the column
750 float bottom = 0.0;
751 for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++)
753 BRect r = ItemAt(i, DiagramItem::M_BOX)->Frame();
754 if ((r.left >= p.x)
755 && (r.left <= p.x + MediaNodePanel::M_DEFAULT_WIDTH))
757 bottom = (r.bottom > bottom) ? r.bottom : bottom;
760 if (bottom >= p.y)
762 p.y = bottom + M_CLEANUP_V_GAP;
764 break;
766 case M_MINI_ICON_VIEW:
768 // find the target row by node_kind
769 p.y += M_CLEANUP_V_GAP + MediaNodePanel::M_DEFAULT_HEIGHT;
770 if (panel->ref->kind() & B_BUFFER_PRODUCER)
772 p.y -= M_CLEANUP_V_GAP + MediaNodePanel::M_DEFAULT_HEIGHT;
774 if (panel->ref->kind() & B_BUFFER_CONSUMER)
776 p.y += M_CLEANUP_V_GAP + MediaNodePanel::M_DEFAULT_HEIGHT;
778 // find the right-most item in the row
779 float right = 0.0;
780 for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++)
782 BRect r = ItemAt(i, DiagramItem::M_BOX)->Frame();
783 if ((r.top >= p.y)
784 && (r.top <= p.y + MediaNodePanel::M_DEFAULT_HEIGHT))
786 right = (r.right > right) ? r.right : right;
789 if (right >= p.x)
791 p.x = right + M_CLEANUP_H_GAP;
793 break;
797 return p;
800 // ---------------------------------------------------------------- //
801 // *** operations (protected)
802 // ---------------------------------------------------------------- //
804 void MediaRoutingView::layoutChanged(
805 layout_t layout)
807 D_METHOD(("MediaRoutingView::layoutChanged()\n"));
809 switch (layout)
811 case M_ICON_VIEW:
813 float temp;
815 // swap the cleanup defaults
816 temp = M_CLEANUP_H_GAP;
817 M_CLEANUP_H_GAP = M_CLEANUP_V_GAP;
818 M_CLEANUP_V_GAP = temp;
819 temp = M_CLEANUP_H_MARGIN;
820 M_CLEANUP_H_MARGIN = M_CLEANUP_V_MARGIN;
821 M_CLEANUP_V_MARGIN = temp;
823 // swap the default dimensions for MediaJacks
824 temp = MediaJack::M_DEFAULT_WIDTH;
825 MediaJack::M_DEFAULT_WIDTH = MediaJack::M_DEFAULT_HEIGHT;
826 MediaJack::M_DEFAULT_HEIGHT = temp;
828 // Add space for the 3-letter i/o-abbreviation
829 BFont font(be_plain_font);
830 font.SetSize(font.Size() - 2.0);
831 for (int i = 0; i < MediaJack::M_MAX_ABBR_LENGTH; i++)
833 MediaJack::M_DEFAULT_WIDTH += font.StringWidth("M");
835 MediaJack::M_DEFAULT_WIDTH += 2.0; // add some padding
837 // Adjust the default size for MediaNodePanels
838 float labelWidth, bodyWidth;
839 float labelHeight, bodyHeight;
840 font_height fh;
841 be_plain_font->GetHeight(&fh);
842 labelWidth = 4 * MediaNodePanel::M_LABEL_H_MARGIN
843 + be_plain_font->StringWidth(" Be Audio Mixer ");
844 bodyWidth = 2 * MediaNodePanel::M_BODY_H_MARGIN + B_LARGE_ICON
845 + 2 * MediaJack::M_DEFAULT_WIDTH;
846 labelHeight = 2 * MediaNodePanel::M_LABEL_V_MARGIN
847 + fh.ascent + fh.descent + fh.leading + 1.0;
848 bodyHeight = 2 * MediaNodePanel::M_BODY_V_MARGIN + B_LARGE_ICON;
849 MediaNodePanel::M_DEFAULT_WIDTH = labelWidth > bodyWidth ? labelWidth : bodyWidth;
850 MediaNodePanel::M_DEFAULT_HEIGHT = labelHeight + bodyHeight;
851 Align(&MediaNodePanel::M_DEFAULT_WIDTH, &MediaNodePanel::M_DEFAULT_HEIGHT);
852 break;
854 case M_MINI_ICON_VIEW:
856 float temp;
858 // Swap the cleanup defaults
859 temp = M_CLEANUP_H_GAP;
860 M_CLEANUP_H_GAP = M_CLEANUP_V_GAP;
861 M_CLEANUP_V_GAP = temp;
862 temp = M_CLEANUP_H_MARGIN;
863 M_CLEANUP_H_MARGIN = M_CLEANUP_V_MARGIN;
864 M_CLEANUP_V_MARGIN = temp;
866 // Subtract space for the 3-letter i/o-abbreviation
867 BFont font(be_plain_font);
868 font.SetSize(font.Size() - 2.0);
869 for (int i = 0; i < MediaJack::M_MAX_ABBR_LENGTH; i++)
871 MediaJack::M_DEFAULT_WIDTH -= font.StringWidth("M");
873 MediaJack::M_DEFAULT_WIDTH -= 2.0; // substract the padding
875 // Swap the default dimensions for MediaJacks
876 temp = MediaJack::M_DEFAULT_WIDTH;
877 MediaJack::M_DEFAULT_WIDTH = MediaJack::M_DEFAULT_HEIGHT;
878 MediaJack::M_DEFAULT_HEIGHT = temp;
880 // Adjust the default size for MediaNodePanels
881 float labelWidth, bodyWidth;
882 float labelHeight, bodyHeight;
883 font_height fh;
884 be_plain_font->GetHeight(&fh);
885 labelWidth = 4 * MediaNodePanel::M_LABEL_H_MARGIN
886 + be_plain_font->StringWidth(" Be Audio Mixer ");
887 bodyWidth = 2 * MediaNodePanel::M_BODY_H_MARGIN + B_MINI_ICON;
888 labelHeight = 3 * MediaNodePanel::M_LABEL_V_MARGIN
889 + fh.ascent + fh.descent + fh.leading
890 + 2 * MediaJack::M_DEFAULT_HEIGHT;
891 bodyHeight = 2 * MediaNodePanel::M_BODY_V_MARGIN + B_MINI_ICON;
892 MediaNodePanel::M_DEFAULT_WIDTH = labelWidth + bodyWidth;
893 MediaNodePanel::M_DEFAULT_HEIGHT = labelHeight > bodyHeight ? labelHeight : bodyHeight;
894 Align(&MediaNodePanel::M_DEFAULT_WIDTH, &MediaNodePanel::M_DEFAULT_HEIGHT);
895 break;
898 m_layout = layout;
899 for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++)
901 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(ItemAt(i, DiagramItem::M_BOX));
902 if (panel)
904 panel->layoutChanged(layout);
908 _adjustScrollBars();
911 void MediaRoutingView::cleanUp()
913 D_METHOD(("MediaRoutingView::cleanUp()\n"));
915 SortItems(DiagramItem::M_BOX, compareID);
917 // move all the panels offscreen
918 for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++)
920 ItemAt(i, DiagramItem::M_BOX)->moveTo(BPoint(-200.0, -200.0));
923 // move all panels to their 'ideal' position
924 for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++)
926 MediaNodePanel *panel;
927 panel = dynamic_cast<MediaNodePanel *>(ItemAt(i, DiagramItem::M_BOX));
928 BPoint p = findFreePositionFor(panel);
929 panel->moveTo(p);
932 SortItems(DiagramItem::M_BOX, compareSelectionTime);
933 Invalidate();
934 updateDataRect();
937 void MediaRoutingView::showContextMenu(
938 BPoint point)
940 D_METHOD(("MediaRoutingView::showContextMenu()\n"));
942 BPopUpMenu *menu = new BPopUpMenu("MediaRoutingView PopUp", false, false, B_ITEMS_IN_COLUMN);
943 menu->SetFont(be_plain_font);
945 // add layout options
946 BMenuItem *item;
947 BMessage *message = new BMessage(M_LAYOUT_CHANGED);
948 message->AddInt32("layout", M_ICON_VIEW);
949 menu->AddItem(item = new BMenuItem("Icon view", message));
950 if (m_layout == M_ICON_VIEW)
952 item->SetMarked(true);
954 message = new BMessage(M_LAYOUT_CHANGED);
955 message->AddInt32("layout", M_MINI_ICON_VIEW);
956 menu->AddItem(item = new BMenuItem("Mini icon view", message));
957 if (m_layout == M_MINI_ICON_VIEW)
959 item->SetMarked(true);
961 menu->AddSeparatorItem();
963 // add 'CleanUp' command
964 menu->AddItem(new BMenuItem("Clean up", new BMessage(M_CLEANUP_REQUESTED), 'K'));
966 // add 'Select All' command
967 menu->AddItem(new BMenuItem("Select all", new BMessage(M_SELECT_ALL), 'A'));
969 menu->SetTargetForItems(this);
970 ConvertToScreen(&point);
971 point -= BPoint(1.0, 1.0);
972 menu->Go(point, true, true, true);
975 void MediaRoutingView::showErrorMessage(
976 BString text,
977 status_t error)
979 D_METHOD(("MediaRoutingView::showErrorMessage()\n"));
981 if (error) {
982 text << " (" << strerror(error) << ")";
985 BMessage message(M_SHOW_ERROR_MESSAGE);
986 message.AddString("text", text.String());
987 if (error) {
988 message.AddBool("error", true);
990 BMessenger messenger(0, Window());
991 if (!messenger.IsValid()
992 || (messenger.SendMessage(&message) != B_OK)) {
993 BAlert *alert = new BAlert("Error", text.String(), "OK", 0, 0,
994 B_WIDTH_AS_USUAL, B_WARNING_ALERT);
995 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
996 alert->Go();
1000 // -------------------------------------------------------- //
1001 // *** IStateArchivable
1002 // -------------------------------------------------------- //
1004 status_t MediaRoutingView::importState(
1005 const BMessage* archive) {
1007 status_t err;
1009 _emptyInactiveNodeState();
1011 layout_t layout;
1012 err = archive->FindInt32("layout", (int32*)&layout);
1013 if(err == B_OK && layout != m_layout) {
1014 layoutChanged(layout);
1017 const char* path;
1018 err = archive->FindString("bgBitmap", &path);
1019 if(err == B_OK) {
1020 BEntry entry(path);
1021 entry_ref ref;
1022 err = entry.GetRef(&ref);
1023 if(err == B_OK)
1024 _changeBackground(&ref);
1026 else {
1027 rgb_color color;
1028 color.alpha = 255;
1030 archive->FindInt8("bgRed", (int8*)&color.red) == B_OK &&
1031 archive->FindInt8("bgGreen", (int8*)&color.green) == B_OK &&
1032 archive->FindInt8("bgBlue", (int8*)&color.blue) == B_OK)
1033 _changeBackground(color);
1036 for(int32 n = 0; ; ++n) {
1038 // find panel state info; stop when exhausted
1039 BMessage m;
1040 err = archive->FindMessage("panel", n, &m);
1041 if(err < B_OK)
1042 break;
1044 const char* nodeName;
1045 err = archive->FindString("nodeName", n, &nodeName);
1046 if(err < B_OK)
1047 break;
1049 uint32 nodeKind;
1050 err = archive->FindInt32("nodeKind", n, (int32*)&nodeKind);
1051 if(err < B_OK)
1052 break;
1054 // look up matching panel +++++ SLOW +++++
1055 uint32 panelIndex;
1056 uint32 items = CountItems(DiagramItem::M_BOX);
1057 for(
1058 panelIndex = 0;
1059 panelIndex < items;
1060 ++panelIndex) {
1062 MediaNodePanel* panel = dynamic_cast<MediaNodePanel*>(
1063 ItemAt(panelIndex, DiagramItem::M_BOX));
1065 if(panel &&
1066 !strcmp(panel->ref->name(), nodeName) &&
1067 panel->ref->kind() == nodeKind) {
1069 // found match; hand message to panel
1070 panel->importState(&m);
1071 break;
1074 if(panelIndex == items) {
1075 // no panel found
1076 // if a "system node" hang onto (and re-export) state info
1077 bool sysOwned;
1078 if(m.FindBool("sysOwned", &sysOwned) == B_OK && sysOwned) {
1079 m_inactiveNodeState.AddItem(
1080 new _inactive_node_state_entry(
1081 nodeName, nodeKind, m));
1086 updateDataRect();
1088 return B_OK;
1091 // +++++ export state info for currently inactive system nodes +++++
1092 status_t MediaRoutingView::exportState(
1093 BMessage* archive) const {
1095 // store layout mode
1096 archive->AddInt32("layout", m_layout);
1098 // store background settings
1099 if(m_backgroundBitmapEntry.InitCheck() == B_OK) {
1100 BPath path;
1101 m_backgroundBitmapEntry.GetPath(&path);
1102 archive->AddString("bgBitmap", path.Path());
1103 } else {
1104 rgb_color c = backgroundColor();
1105 archive->AddInt8("bgRed", c.red);
1106 archive->AddInt8("bgGreen", c.green);
1107 archive->AddInt8("bgBlue", c.blue);
1110 // store panel positions w/ node names & signatures
1111 for(uint32 n = 0; n < CountItems(DiagramItem::M_BOX); ++n) {
1112 MediaNodePanel* panel = dynamic_cast<MediaNodePanel*>(
1113 ItemAt(n, DiagramItem::M_BOX));
1114 if(!panel)
1115 continue;
1117 if(panel->ref->isInternal())
1118 // skip internal nodes
1119 continue;
1121 BMessage m;
1122 panel->exportState(&m);
1123 archive->AddString("nodeName", panel->ref->name());
1124 archive->AddInt32("nodeKind", panel->ref->kind());
1125 archive->AddMessage("panel", &m);
1128 // copy inactive node state info
1129 for(int32 n = 0; n < m_inactiveNodeState.CountItems(); ++n) {
1130 _inactive_node_state_entry* e = reinterpret_cast<_inactive_node_state_entry*>(
1131 m_inactiveNodeState.ItemAt(n));
1133 archive->AddString("nodeName", e->name.String());
1134 archive->AddInt32("nodeKind", e->kind);
1135 archive->AddMessage("panel", &e->state);
1138 return B_OK;
1141 // [e.moon 8dec99] subset support
1143 status_t MediaRoutingView::importStateFor(
1144 const NodeSetIOContext* context,
1145 const BMessage* archive) {
1147 status_t err;
1149 for(int32 archiveIndex = 0;; ++archiveIndex) {
1151 // fetch archived key & panel data
1152 const char* key;
1153 err = archive->FindString("nodeKey", archiveIndex, &key);
1154 if(err < B_OK)
1155 break;
1157 BMessage m;
1158 err = archive->FindMessage("panel", archiveIndex, &m);
1159 if(err < B_OK) {
1160 PRINT((
1161 "!!! MediaRoutingView::importStateFor(): missing panel %"
1162 B_PRId32 "\n", archiveIndex));
1163 continue;
1166 // find corresponding node
1167 media_node_id id;
1168 err = context->getNodeFor(key, &id);
1169 if(err < B_OK) {
1170 PRINT((
1171 "!!! MediaRoutingView::importStateFor(): missing node '%s'\n",
1172 key));
1173 continue;
1176 // look for panel, create it if necessary
1177 MediaNodePanel* panel;
1178 err = _findPanelFor(id, &panel);
1179 if(err < B_OK) {
1180 // create it
1181 err = _addPanelFor(
1183 BPoint(5.0, 5.0));
1184 if(err < B_OK) {
1185 PRINT((
1186 "!!! MediaRoutingView::importStateFor(): _addPanelFor():\n"
1187 " %s\n", strerror(err)));
1188 continue;
1191 err = _findPanelFor(id, &panel);
1192 if(err < B_OK) {
1193 PRINT((
1194 "!!! MediaRoutingView::importStateFor(): _findPanelFor():\n"
1195 " %s\n", strerror(err)));
1196 continue;
1200 // pass state data along
1201 panel->importState(&m);
1203 // select the panel
1204 SelectItem(panel, false);
1207 return B_OK;
1210 status_t MediaRoutingView::exportStateFor(
1211 const NodeSetIOContext* context,
1212 BMessage* archive) const {
1214 status_t err;
1216 for(uint32 n = 0; n < context->countNodes(); ++n) {
1217 MediaNodePanel* panel;
1218 err = _findPanelFor(
1219 context->nodeAt(n),
1220 &panel);
1221 if(err < B_OK) {
1222 PRINT((
1223 "!!! MediaRoutingView::exportStateFor():\n"
1224 " no panel for node %" B_PRId32 "\n",
1225 context->nodeAt(n)));
1226 return B_BAD_VALUE;
1229 const char* key = context->keyAt(n);
1231 archive->AddString("nodeKey", key);
1232 BMessage m;
1233 panel->exportState(&m);
1234 archive->AddMessage("panel", &m);
1237 return B_OK;
1240 // -------------------------------------------------------- //
1241 // *** children management
1242 // -------------------------------------------------------- //
1244 status_t MediaRoutingView::_addPanelFor(
1245 media_node_id id,
1246 BPoint atPoint)
1248 D_METHOD(("MediaRoutingView::_addPanelFor()\n"));
1250 manager->lock();
1251 NodeRef *ref;
1252 status_t error = manager->getNodeRef(id, &ref);
1253 manager->unlock();
1254 if (!error)
1256 add_observer(this, ref);
1257 MediaNodePanel *panel = 0;
1258 if (id == m_lastDroppedNode) // this was instantiated thru drag & drop
1260 AddItem(panel = new MediaNodePanel(m_lastDropPoint, ref));
1261 SelectItem(panel, true);
1262 m_lastDroppedNode = 0;
1264 else // this was an externally created node, must find a nice position first
1266 panel = new MediaNodePanel(BPoint(0.0, 0.0), ref);
1267 AddItem(panel);
1268 BMessage state;
1269 if(_fetchInactiveNodeState(panel, &state) == B_OK)
1270 panel->importState(&state);
1271 else {
1272 BPoint p = findFreePositionFor(panel);
1273 panel->moveTo(p);
1275 Invalidate(panel->Frame());
1278 updateDataRect();
1279 return error;
1282 status_t MediaRoutingView::_findPanelFor(
1283 media_node_id id,
1284 MediaNodePanel **outPanel) const
1286 D_METHOD(("MediaRoutingView::_findPanelFor()\n"));
1288 for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++)
1290 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(ItemAt(i, DiagramItem::M_BOX));
1291 if (panel)
1293 if (panel->ref->id() == id)
1295 *outPanel = panel;
1296 return B_OK;
1300 return B_ERROR;
1303 status_t MediaRoutingView::_removePanelFor(
1304 media_node_id id)
1306 D_METHOD(("MediaRoutingView::_removePanelFor()\n"));
1308 MediaNodePanel *panel;
1309 if (_findPanelFor(id, &panel) == B_OK)
1311 if (RemoveItem(panel))
1313 remove_observer(this, panel->ref);
1314 Invalidate(panel->Frame());
1315 delete panel;
1316 return B_OK;
1319 return B_ERROR;
1322 status_t MediaRoutingView::_addWireFor(
1323 Connection& connection)
1325 D_METHOD(("MediaRoutingView::_addWireFor()\n"));
1327 MediaNodePanel *source, *destination;
1328 if ((_findPanelFor(connection.sourceNode(), &source) == B_OK)
1329 && (_findPanelFor(connection.destinationNode(), &destination) == B_OK))
1331 status_t error;
1333 media_output output;
1334 error = connection.getOutput(&output);
1335 if (error)
1337 return error;
1339 MediaJack *outputJack = new MediaJack(output);
1340 source->AddItem(outputJack);
1342 media_input input;
1343 error = connection.getInput(&input);
1344 if (error)
1346 return error;
1348 MediaJack *inputJack = new MediaJack(input);
1349 destination->AddItem(inputJack);
1351 MediaWire *wire = new MediaWire(connection, outputJack, inputJack);
1352 AddItem(wire);
1353 source->updateIOJacks();
1354 source->arrangeIOJacks();
1355 destination->updateIOJacks();
1356 destination->arrangeIOJacks();
1357 updateDataRect();
1359 // [e.moon 21nov99] group creation/merging now performed by
1360 // RouteAppNodeManager
1362 Invalidate(source->Frame());
1363 Invalidate(destination->Frame());
1364 Invalidate(wire->Frame());
1365 return B_OK;
1367 else
1369 return B_ERROR;
1373 status_t MediaRoutingView::_findWireFor(
1374 uint32 connectionID,
1375 MediaWire **outWire) const
1377 D_METHOD(("MediaRoutingView::_findWireFor()\n"));
1379 for (uint32 i = 0; i < CountItems(DiagramItem::M_WIRE); i++)
1381 MediaWire *wire = dynamic_cast<MediaWire *>(ItemAt(i, DiagramItem::M_WIRE));
1382 if (wire && wire->connection.id() == connectionID)
1384 *outWire = wire;
1385 return B_OK;
1388 return B_ERROR;
1391 status_t MediaRoutingView::_removeWireFor(
1392 uint32 connectionID)
1394 D_METHOD(("MediaRoutingView::_removeWireFor()\n"));
1396 MediaWire *wire;
1397 if (_findWireFor(connectionID, &wire) == B_OK)
1399 MediaNodePanel *source, *destination;
1400 _findPanelFor(wire->connection.sourceNode(), &source);
1401 _findPanelFor(wire->connection.destinationNode(), &destination);
1402 RemoveItem(wire);
1403 Invalidate(wire->Frame());
1404 delete wire;
1405 if (source)
1407 source->updateIOJacks();
1408 source->arrangeIOJacks();
1409 Invalidate(source->Frame());
1411 if (destination)
1413 destination->updateIOJacks();
1414 destination->arrangeIOJacks();
1415 Invalidate(destination->Frame());
1418 // [e.moon 21nov99] group split/remove now performed by
1419 // RouteAppNodeManager
1421 updateDataRect();
1422 return B_OK;
1424 return B_ERROR;
1427 // -------------------------------------------------------- //
1428 // *** internal methods
1429 // -------------------------------------------------------- //
1431 void MediaRoutingView::_addShortcuts()
1433 Window()->AddShortcut('A', B_COMMAND_KEY,
1434 new BMessage(M_SELECT_ALL), this);
1435 Window()->AddShortcut('K', B_COMMAND_KEY,
1436 new BMessage(M_CLEANUP_REQUESTED), this);
1437 Window()->AddShortcut('T', B_COMMAND_KEY,
1438 new BMessage(M_DELETE_SELECTION), this);
1439 Window()->AddShortcut('P', B_COMMAND_KEY,
1440 new BMessage(M_NODE_TWEAK_PARAMETERS), this);
1441 Window()->AddShortcut('P', B_COMMAND_KEY | B_SHIFT_KEY,
1442 new BMessage(M_NODE_START_CONTROL_PANEL), this);
1443 Window()->AddShortcut('I', B_COMMAND_KEY,
1444 new BMessage(InfoWindowManager::M_INFO_WINDOW_REQUESTED), this);
1447 void MediaRoutingView::_initLayout()
1449 D_METHOD(("MediaRoutingView::_initLayout()\n"));
1451 switch (m_layout)
1453 case M_ICON_VIEW:
1455 // Adjust the jack width for displaying the abbreviated
1456 // input/output name
1457 BFont font(be_plain_font);
1458 font.SetSize(font.Size() - 2.0);
1459 for (int i = 0; i < MediaJack::M_MAX_ABBR_LENGTH; i++)
1461 MediaJack::M_DEFAULT_WIDTH += font.StringWidth("M");
1463 MediaJack::M_DEFAULT_WIDTH += 2.0; // add some padding
1465 // Adjust the default size for MediaNodePanels to fit the
1466 // size of be_plain_font
1467 float labelWidth, bodyWidth;
1468 float labelHeight, bodyHeight;
1469 font_height fh;
1470 be_plain_font->GetHeight(&fh);
1471 labelWidth = 4 * MediaNodePanel::M_LABEL_H_MARGIN
1472 + be_plain_font->StringWidth(" Be Audio Mixer ");
1473 bodyWidth = 2 * MediaNodePanel::M_BODY_H_MARGIN + B_LARGE_ICON
1474 + 2 * MediaJack::M_DEFAULT_WIDTH;
1475 labelHeight = 2 * MediaNodePanel::M_LABEL_V_MARGIN
1476 + fh.ascent + fh.descent + fh.leading + 1.0;
1477 bodyHeight = 2 * MediaNodePanel::M_BODY_V_MARGIN + B_LARGE_ICON;
1478 MediaNodePanel::M_DEFAULT_WIDTH = labelWidth > bodyWidth ? labelWidth : bodyWidth;
1479 MediaNodePanel::M_DEFAULT_HEIGHT = labelHeight + bodyHeight;
1480 Align(&MediaNodePanel::M_DEFAULT_WIDTH, &MediaNodePanel::M_DEFAULT_HEIGHT);
1482 // Adjust the cleanup settings
1483 M_CLEANUP_H_GAP += MediaNodePanel::M_DEFAULT_WIDTH;
1484 break;
1486 case M_MINI_ICON_VIEW:
1488 // Adjust the default size for MediaNodePanels to fit the
1489 // size of be_plain_font
1490 float labelWidth, bodyWidth;
1491 float labelHeight, bodyHeight;
1492 font_height fh;
1493 be_plain_font->GetHeight(&fh);
1494 labelWidth = 4 * MediaNodePanel::M_LABEL_H_MARGIN
1495 + be_plain_font->StringWidth(" Be Audio Mixer ");
1496 bodyWidth = 2 * MediaNodePanel::M_BODY_H_MARGIN + B_MINI_ICON;
1497 labelHeight = 3 * MediaNodePanel::M_LABEL_V_MARGIN
1498 + fh.ascent + fh.descent + fh.leading
1499 + 2 * MediaJack::M_DEFAULT_HEIGHT;
1500 bodyHeight = 2 * MediaNodePanel::M_BODY_V_MARGIN + B_MINI_ICON;
1501 MediaNodePanel::M_DEFAULT_WIDTH = labelWidth + bodyWidth;
1502 MediaNodePanel::M_DEFAULT_HEIGHT = labelHeight > bodyHeight ? labelHeight : bodyHeight;
1503 Align(&MediaNodePanel::M_DEFAULT_WIDTH, &MediaNodePanel::M_DEFAULT_HEIGHT);
1505 // Adjust the cleanup settings
1506 M_CLEANUP_V_GAP += MediaNodePanel::M_DEFAULT_HEIGHT;
1507 break;
1512 void MediaRoutingView::_initContent()
1514 D_METHOD(("MediaRoutingView::_initContent()\n"));
1516 Autolock lock(manager);
1518 void *cookie = 0;
1519 NodeRef *ref;
1520 while (manager->getNextRef(&ref, &cookie) == B_OK)
1522 // add self as observer
1523 add_observer(this, ref);
1524 // create & place node view (+++++ defer until observer status confirmed!)
1525 _addPanelFor(ref->id(), BPoint(M_CLEANUP_H_MARGIN, M_CLEANUP_V_MARGIN));
1527 cookie = 0;
1528 Connection connection;
1529 while (manager->getNextConnection(&connection, &cookie) == B_OK)
1531 _addWireFor(connection);
1534 // create default groups
1535 NodeGroup* group;
1536 NodeRef* videoIn = manager->videoInputNode();
1537 if (videoIn)
1539 group = manager->createGroup("Video input");
1540 group->setRunMode(BMediaNode::B_RECORDING);
1541 group->addNode(videoIn);
1543 NodeRef* audioIn = manager->audioInputNode();
1544 if (audioIn)
1546 group = manager->createGroup("Audio input");
1547 group->setRunMode(BMediaNode::B_RECORDING);
1548 group->addNode(audioIn);
1550 NodeRef* videoOut = manager->videoOutputNode();
1551 if (videoOut)
1553 group = manager->createGroup("Video output");
1554 group->addNode(videoOut);
1558 void MediaRoutingView::_changeCyclingForSelection(
1559 bool cycle)
1561 D_METHOD(("MediaRoutingView::_changeCyclingForSelection()\n"));
1563 if (SelectedType() == DiagramItem::M_BOX)
1565 manager->lock();
1566 for (uint32 i = 0; i < CountSelectedItems(); i++)
1568 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(SelectedItemAt(i));
1569 if (panel && (panel->ref->isCycling() != cycle))
1571 panel->ref->setCycling(cycle);
1574 manager->unlock();
1578 void MediaRoutingView::_changeRunModeForSelection(
1579 uint32 mode)
1581 D_METHOD(("MediaRoutingView::_changeRunModeForSelection()\n"));
1583 if (SelectedType() == DiagramItem::M_BOX)
1585 manager->lock();
1586 for (uint32 i = 0; i < CountSelectedItems(); i++)
1588 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(SelectedItemAt(i));
1589 if (panel && (panel->ref->runMode() != mode))
1591 panel->ref->setRunMode(mode);
1594 manager->unlock();
1598 void MediaRoutingView::_openInfoWindowsForSelection() {
1599 D_METHOD(("MediaRoutingView::_openInfoWindowsForSelection()\n"));
1601 InfoWindowManager *manager = InfoWindowManager::Instance();
1602 if (!manager) {
1603 return;
1606 if (SelectedType() == DiagramItem::M_BOX) {
1607 for (uint32 i = 0; i < CountSelectedItems(); i++) {
1608 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(SelectedItemAt(i));
1609 if (panel && manager->Lock()) {
1610 manager->openWindowFor(panel->ref);
1611 manager->Unlock();
1615 else if (SelectedType() == DiagramItem::M_WIRE) {
1616 for (uint32 i = 0; i < CountSelectedItems(); i++) {
1617 MediaWire *wire = dynamic_cast<MediaWire *>(SelectedItemAt(i));
1618 if (wire && manager->Lock()) {
1619 manager->openWindowFor(wire->connection);
1620 manager->Unlock();
1626 void MediaRoutingView::_openParameterWindowsForSelection() {
1627 D_METHOD(("MediaRoutingView::_openParameterWindowsForSelection()\n"));
1629 if (SelectedType() != DiagramItem::M_BOX) {
1630 // can only open parameter window for nodes
1631 return;
1634 for (uint32 i = 0; i < CountSelectedItems(); i++) {
1635 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(SelectedItemAt(i));
1636 if (panel && (panel->ref->kind() & B_CONTROLLABLE)) {
1637 ParameterWindowManager *paramMgr= ParameterWindowManager::Instance();
1638 if (paramMgr && paramMgr->Lock()) {
1639 paramMgr->openWindowFor(panel->ref);
1640 paramMgr->Unlock();
1646 void MediaRoutingView::_startControlPanelsForSelection() {
1647 D_METHOD(("MediaRoutingView::_startControlPanelsForSelection()\n"));
1649 if (SelectedType() != DiagramItem::M_BOX) {
1650 // can only start control panel for nodes
1651 return;
1654 for (uint32 i = 0; i < CountSelectedItems(); i++) {
1655 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(SelectedItemAt(i));
1656 if (panel && (panel->ref->kind() & B_CONTROLLABLE)) {
1657 ParameterWindowManager *paramMgr= ParameterWindowManager::Instance();
1658 if (paramMgr && paramMgr->Lock()) {
1659 paramMgr->startControlPanelFor(panel->ref);
1660 paramMgr->Unlock();
1666 void MediaRoutingView::_deleteSelection()
1668 D_METHOD(("MediaRoutingView::_deleteSelection()\n"));
1669 if (SelectedType() == DiagramItem::M_BOX)
1671 for (uint32 i = 0; i < CountSelectedItems(); i++)
1673 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(SelectedItemAt(i));
1674 if (panel && panel->ref->isInternal())
1676 status_t error = panel->ref->releaseNode();
1677 if (error)
1679 BString s;
1680 s << "Could not release '" << panel->ref->name() << "'";
1681 showErrorMessage(s, error);
1686 else if (SelectedType() == DiagramItem::M_WIRE)
1688 for (uint32 i = 0; i < CountSelectedItems(); i++)
1690 MediaWire *wire = dynamic_cast<MediaWire *>(SelectedItemAt(i));
1691 if (wire && !(wire->connection.flags() & Connection::LOCKED))
1693 status_t error = manager->disconnect(wire->connection);
1694 if (error)
1696 showErrorMessage("Could not disconnect", error);
1701 // make sure none of the deleted items is still displaying its mouse cursor !
1702 be_app->SetCursor(B_HAND_CURSOR);
1705 void MediaRoutingView::_checkDroppedFile(
1706 entry_ref *ref,
1707 BPoint dropPoint)
1709 D_METHOD(("MediaRoutingView::_checkDroppedFile()\n"));
1711 // [cell 26apr00] traverse links
1712 BEntry entry(ref, true);
1713 entry.GetRef(ref);
1715 BNode node(ref);
1716 if (node.InitCheck() == B_OK)
1718 BNodeInfo nodeInfo(&node);
1719 if (nodeInfo.InitCheck() == B_OK)
1721 char mimeString[B_MIME_TYPE_LENGTH];
1722 if (nodeInfo.GetType(mimeString) == B_OK)
1724 BMimeType mimeType(mimeString);
1725 BMimeType superType;
1727 // [e.moon 22dec99] handle dropped node-set files
1728 if(mimeType == RouteApp::s_nodeSetType) {
1729 BMessage m(B_REFS_RECEIVED);
1730 m.AddRef("refs", ref);
1731 be_app_messenger.SendMessage(&m);
1733 else if (mimeType.GetSupertype(&superType) == B_OK)
1735 if (superType == "image")
1737 _changeBackground(ref);
1739 else if ((superType == "audio") || (superType == "video"))
1741 NodeRef* droppedNode;
1742 status_t error;
1743 error = manager->instantiate(*ref, B_BUFFER_PRODUCER, &droppedNode);
1744 if (!error)
1746 media_output encVideoOutput;
1747 if (droppedNode->findFreeOutput(&encVideoOutput, B_MEDIA_ENCODED_VIDEO) == B_OK)
1749 droppedNode->setFlags(droppedNode->flags() | NodeRef::NO_POSITION_REPORTING);
1751 m_lastDroppedNode = droppedNode->id();
1752 m_lastDropPoint = Align(dropPoint);
1754 else
1756 char fileName[B_FILE_NAME_LENGTH];
1757 BEntry entry(ref);
1758 entry.GetName(fileName);
1759 BString s;
1760 s << "Could not load '" << fileName << "'";
1761 showErrorMessage(s, error);
1770 void MediaRoutingView::_changeBackground(
1771 entry_ref *ref)
1773 D_METHOD(("MediaRoutingView::_changeBackground()\n"));
1775 status_t error;
1776 BBitmap *background = 0;
1777 BFile file(ref, B_READ_ONLY);
1778 error = file.InitCheck();
1779 if (!error)
1781 BTranslatorRoster *roster = BTranslatorRoster::Default();
1782 BBitmapStream stream;
1783 error = roster->Translate(&file, NULL, NULL, &stream, B_TRANSLATOR_BITMAP);
1784 if (!error)
1786 stream.DetachBitmap(&background);
1787 setBackgroundBitmap(background);
1788 Invalidate();
1790 // [e.moon 1dec99] persistence, yay
1791 m_backgroundBitmapEntry.SetTo(ref);
1794 delete background;
1797 void MediaRoutingView::_changeBackground(
1798 rgb_color color)
1800 D_METHOD(("MediaRoutingView::_changeBackground()\n"));
1801 setBackgroundColor(color);
1802 Invalidate();
1804 // [e.moon 1dec99] persistence, yay
1805 m_backgroundBitmapEntry.Unset();
1808 void
1809 MediaRoutingView::_adjustScrollBars()
1811 D_METHOD(("MediaRoutingView::_adjustScrollBars()\n"));
1813 BScrollBar *scrollBar;
1815 // adjust horizontal scroll bar
1816 scrollBar = ScrollBar(B_HORIZONTAL);
1817 if (scrollBar) {
1818 float bigStep = floor(MediaNodePanel::M_DEFAULT_WIDTH + M_CLEANUP_H_GAP);
1819 scrollBar->SetSteps(floor(bigStep / 10.0), bigStep);
1822 // adjust vertical scroll bar
1823 scrollBar = ScrollBar(B_VERTICAL);
1824 if (scrollBar) {
1825 float bigStep = floor(MediaNodePanel::M_DEFAULT_HEIGHT + M_CLEANUP_V_GAP);
1826 scrollBar->SetSteps(floor(bigStep / 10.0), bigStep);
1830 void
1831 MediaRoutingView::_broadcastSelection() const
1833 int32 selectedGroup = 0;
1835 if (SelectedType() == DiagramItem::M_BOX) {
1836 // iterate thru the list of selected node panels and make the
1837 // first group we find the selected group
1838 for (uint32 i = 0; i < CountSelectedItems(); i++) {
1839 MediaNodePanel *panel = dynamic_cast<MediaNodePanel *>(SelectedItemAt(i));
1840 if (panel && panel->ref->group()) {
1841 selectedGroup = panel->ref->group()->id();
1842 BMessenger messenger(Window());
1843 BMessage groupMsg(M_GROUP_SELECTED);
1844 groupMsg.AddInt32("groupID", selectedGroup);
1845 messenger.SendMessage(&groupMsg);
1846 return;
1851 // currently no group is selected
1852 BMessenger messenger(Window());
1853 BMessage groupMsg(M_GROUP_SELECTED);
1854 groupMsg.AddInt32("groupID", selectedGroup);
1855 messenger.SendMessage(&groupMsg);
1858 status_t
1859 MediaRoutingView::_fetchInactiveNodeState(MediaNodePanel *forPanel, BMessage *outMessage)
1861 // copy inactive node state info
1862 int32 c = m_inactiveNodeState.CountItems();
1863 for(int32 n = 0; n < c; n++) {
1864 _inactive_node_state_entry* e = reinterpret_cast<_inactive_node_state_entry*>(
1865 m_inactiveNodeState.ItemAt(n));
1866 ASSERT(e);
1867 if(e->name != forPanel->ref->name())
1868 continue;
1870 if(e->kind != forPanel->ref->kind())
1871 continue;
1873 // found match; extract message & remove entry
1874 *outMessage = e->state;
1875 m_inactiveNodeState.RemoveItem(n);
1876 return B_OK;
1879 return B_BAD_VALUE;
1882 void
1883 MediaRoutingView::_emptyInactiveNodeState()
1885 int32 c = m_inactiveNodeState.CountItems();
1886 for(int32 n = 0; n < c; n++) {
1887 _inactive_node_state_entry* e = reinterpret_cast<_inactive_node_state_entry*>(
1888 m_inactiveNodeState.ItemAt(n));
1889 ASSERT(e);
1890 delete e;
1892 m_inactiveNodeState.MakeEmpty();
1896 // END -- MediaRoutingView.cpp --