142b7984aSPete Goodeve/* PatchRow.cpp
242b7984aSPete Goodeve * ------------
342b7984aSPete Goodeve *
442b7984aSPete Goodeve * Copyright 2013, Haiku, Inc. All rights reserved.
542b7984aSPete Goodeve * Distributed under the terms of the MIT License.
642b7984aSPete Goodeve *
742b7984aSPete Goodeve * Revisions by Pete Goodeve
842b7984aSPete Goodeve *
942b7984aSPete Goodeve * Copyright 1999, Be Incorporated.   All Rights Reserved.
1042b7984aSPete Goodeve * This file may be used under the terms of the Be Sample Code License.
1142b7984aSPete Goodeve */
1242b7984aSPete Goodeve
1342b7984aSPete Goodeve#include "PatchRow.h"
14e1d5f30eSPhilippe Houdoin
15e1d5f30eSPhilippe Houdoin#include <stdio.h>
16e1d5f30eSPhilippe Houdoin#include <CheckBox.h>
17e1d5f30eSPhilippe Houdoin#include <Debug.h>
18e1d5f30eSPhilippe Houdoin#include <MidiRoster.h>
19e1d5f30eSPhilippe Houdoin#include <MidiConsumer.h>
20e1d5f30eSPhilippe Houdoin#include <MidiProducer.h>
21e1d5f30eSPhilippe Houdoin#include <Window.h>
2282fbbe21SPete Goodeve
23e1d5f30eSPhilippe Houdoin#include "MidiEventMeter.h"
24e1d5f30eSPhilippe Houdoin
25e1d5f30eSPhilippe Houdoinextern const float ROW_LEFT = 50.0f;
26e1d5f30eSPhilippe Houdoinextern const float ROW_TOP = 50.0f;
27e1d5f30eSPhilippe Houdoinextern const float ROW_HEIGHT = 40.0f;
28e1d5f30eSPhilippe Houdoinextern const float COLUMN_WIDTH = 40.0f;
29e1d5f30eSPhilippe Houdoinextern const float METER_PADDING = 15.0f;
30e1d5f30eSPhilippe Houdoinextern const uint32 MSG_CONNECT_REQUEST = 'mCRQ';
31e1d5f30eSPhilippe Houdoin
3242b7984aSPete Goodevestatic const BPoint kBoxOffset(8, 7);
33e1d5f30eSPhilippe Houdoin
34e1d5f30eSPhilippe Houdoin// PatchCheckBox is the check box that describes a connection
35e1d5f30eSPhilippe Houdoin// between a producer and a consumer.
36e1d5f30eSPhilippe Houdoinclass PatchCheckBox : public BCheckBox
37e1d5f30eSPhilippe Houdoin{
38e1d5f30eSPhilippe Houdoinpublic:
39e1d5f30eSPhilippe Houdoin	PatchCheckBox(BRect r, int32 producerID, int32 consumerID)
4042b7984aSPete Goodeve		:
4142b7984aSPete Goodeve		BCheckBox(r, "", "", new BMessage(MSG_CONNECT_REQUEST)),
4242b7984aSPete Goodeve		fProducerID(producerID),
4342b7984aSPete Goodeve		fConsumerID(consumerID)
4442b7984aSPete Goodeve	{}
4542b7984aSPete Goodeve
4642b7984aSPete Goodeve	int32 ProducerID() const
47e1d5f30eSPhilippe Houdoin	{
4842b7984aSPete Goodeve		return fProducerID;
4942b7984aSPete Goodeve	}
5042b7984aSPete Goodeve	int32 ConsumerID() const
5142b7984aSPete Goodeve	{
5242b7984aSPete Goodeve		return fConsumerID;
53e1d5f30eSPhilippe Houdoin	}
54e1d5f30eSPhilippe Houdoin
55e1d5f30eSPhilippe Houdoin	void DoConnect();
56e1d5f30eSPhilippe Houdoin
57e1d5f30eSPhilippe Houdoinprivate:
5842b7984aSPete Goodeve	int32 fProducerID;
5942b7984aSPete Goodeve	int32 fConsumerID;
60e1d5f30eSPhilippe Houdoin};
61e1d5f30eSPhilippe Houdoin
6242b7984aSPete Goodeve
63e1d5f30eSPhilippe HoudoinPatchRow::PatchRow(int32 producerID)
6442b7984aSPete Goodeve	:
6542b7984aSPete Goodeve	BView(BRect(0, 0, 0, 0), "PatchRow", B_FOLLOW_NONE,
6642b7984aSPete Goodeve		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_PULSE_NEEDED),
6742b7984aSPete Goodeve	fProducerID(producerID),
6842b7984aSPete Goodeve	fEventMeter(NULL)
69e1d5f30eSPhilippe Houdoin{
7042b7984aSPete Goodeve	fEventMeter = new MidiEventMeter(fProducerID);
71e1d5f30eSPhilippe Houdoin}
72e1d5f30eSPhilippe Houdoin
7342b7984aSPete Goodeve
74e1d5f30eSPhilippe HoudoinPatchRow::~PatchRow()
75e1d5f30eSPhilippe Houdoin{
7642b7984aSPete Goodeve	delete fEventMeter;
77e1d5f30eSPhilippe Houdoin}
78e1d5f30eSPhilippe Houdoin
7942b7984aSPete Goodeve
8042b7984aSPete Goodeveint32
8142b7984aSPete GoodevePatchRow::ID() const
82e1d5f30eSPhilippe Houdoin{
8342b7984aSPete Goodeve	return fProducerID;
84e1d5f30eSPhilippe Houdoin}
85e1d5f30eSPhilippe Houdoin
8642b7984aSPete Goodeve
8742b7984aSPete Goodevevoid
8842b7984aSPete GoodevePatchRow::Pulse()
89e1d5f30eSPhilippe Houdoin{
9082fbbe21SPete Goodeve	if (fEventMeter != NULL)
9142b7984aSPete Goodeve		fEventMeter->Pulse(this);
92e1d5f30eSPhilippe Houdoin}
93e1d5f30eSPhilippe Houdoin
9442b7984aSPete Goodeve
9542b7984aSPete Goodevevoid
9642b7984aSPete GoodevePatchRow::Draw(BRect)
97e1d5f30eSPhilippe Houdoin{
9882fbbe21SPete Goodeve	if (fEventMeter != NULL)
9942b7984aSPete Goodeve		fEventMeter->Draw(this);
100e1d5f30eSPhilippe Houdoin}
101e1d5f30eSPhilippe Houdoin
10242b7984aSPete Goodeve
10342b7984aSPete Goodevevoid
10442b7984aSPete GoodevePatchRow::AddColumn(int32 consumerID)
105e1d5f30eSPhilippe Houdoin{
10642b7984aSPete Goodeve	BRect rect;
107e1d5f30eSPhilippe Houdoin	int32 numColumns = CountChildren();
10842b7984aSPete Goodeve	rect.left = numColumns * COLUMN_WIDTH + METER_PADDING + kBoxOffset.x;
10942b7984aSPete Goodeve	rect.top = kBoxOffset.y;
11042b7984aSPete Goodeve	rect.right = rect.left + 20;
11142b7984aSPete Goodeve	rect.bottom = rect.top + 20;
112e1d5f30eSPhilippe Houdoin
11342b7984aSPete Goodeve	PatchCheckBox* box = new PatchCheckBox(rect, fProducerID, consumerID);
114e1d5f30eSPhilippe Houdoin	AddChild(box);
115e1d5f30eSPhilippe Houdoin	box->SetTarget(this);
116e1d5f30eSPhilippe Houdoin}
117e1d5f30eSPhilippe Houdoin
11842b7984aSPete Goodeve
11942b7984aSPete Goodevevoid
12042b7984aSPete GoodevePatchRow::RemoveColumn(int32 consumerID)
121e1d5f30eSPhilippe Houdoin{
122e1d5f30eSPhilippe Houdoin	int32 numChildren = CountChildren();
12342b7984aSPete Goodeve	for (int32 i = 0; i < numChildren; i++) {
124e1d5f30eSPhilippe Houdoin		PatchCheckBox* box = dynamic_cast<PatchCheckBox*>(ChildAt(i));
12582fbbe21SPete Goodeve		if (box != NULL && box->ConsumerID() == consumerID) {
126e1d5f30eSPhilippe Houdoin			RemoveChild(box);
127e1d5f30eSPhilippe Houdoin			delete box;
128e1d5f30eSPhilippe Houdoin			while (i < numChildren) {
129e1d5f30eSPhilippe Houdoin				box = dynamic_cast<PatchCheckBox*>(ChildAt(i++));
13082fbbe21SPete Goodeve				if (box != NULL)
131e1d5f30eSPhilippe Houdoin					box->MoveBy(-COLUMN_WIDTH, 0);
132e1d5f30eSPhilippe Houdoin			}
133e1d5f30eSPhilippe Houdoin			break;
134e1d5f30eSPhilippe Houdoin		}
135e1d5f30eSPhilippe Houdoin	}
136e1d5f30eSPhilippe Houdoin}
137e1d5f30eSPhilippe Houdoin
13842b7984aSPete Goodeve
13942b7984aSPete Goodevevoid
14042b7984aSPete GoodevePatchRow::Connect(int32 consumerID)
141e1d5f30eSPhilippe Houdoin{
142e1d5f30eSPhilippe Houdoin	int32 numChildren = CountChildren();
14342b7984aSPete Goodeve	for (int32 i = 0; i < numChildren; i++) {
144e1d5f30eSPhilippe Houdoin		PatchCheckBox* box = dynamic_cast<PatchCheckBox*>(ChildAt(i));
14582fbbe21SPete Goodeve		if (box != NULL && box->ConsumerID() == consumerID)
146e1d5f30eSPhilippe Houdoin			box->SetValue(1);
147e1d5f30eSPhilippe Houdoin	}
148e1d5f30eSPhilippe Houdoin}
149e1d5f30eSPhilippe Houdoin
15042b7984aSPete Goodeve
15142b7984aSPete Goodevevoid
15242b7984aSPete GoodevePatchRow::Disconnect(int32 consumerID)
153e1d5f30eSPhilippe Houdoin{
154e1d5f30eSPhilippe Houdoin	int32 numChildren = CountChildren();
15542b7984aSPete Goodeve	for (int32 i = 0; i < numChildren; i++) {
156e1d5f30eSPhilippe Houdoin		PatchCheckBox* box = dynamic_cast<PatchCheckBox*>(ChildAt(i));
15782fbbe21SPete Goodeve		if (box != NULL && box->ConsumerID() == consumerID)
158e1d5f30eSPhilippe Houdoin			box->SetValue(0);
159e1d5f30eSPhilippe Houdoin	}
160e1d5f30eSPhilippe Houdoin}
161e1d5f30eSPhilippe Houdoin
16242b7984aSPete Goodeve
16342b7984aSPete Goodevevoid
16442b7984aSPete GoodevePatchRow::AttachedToWindow()
165e1d5f30eSPhilippe Houdoin{
166e1d5f30eSPhilippe Houdoin	Window()->SetPulseRate(200000);
167fa19dd44Slooncraz	AdoptParentColors();
168e1d5f30eSPhilippe Houdoin	int32 numChildren = CountChildren();
16942b7984aSPete Goodeve	for (int32 i = 0; i < numChildren; i++) {
170e1d5f30eSPhilippe Houdoin		PatchCheckBox* box = dynamic_cast<PatchCheckBox*>(ChildAt(i));
17182fbbe21SPete Goodeve		if (box != NULL)
172e1d5f30eSPhilippe Houdoin			box->SetTarget(this);
173e1d5f30eSPhilippe Houdoin	}
174e1d5f30eSPhilippe Houdoin}
175e1d5f30eSPhilippe Houdoin
17642b7984aSPete Goodeve
17742b7984aSPete Goodevevoid
17842b7984aSPete GoodevePatchRow::MessageReceived(BMessage* msg)
179e1d5f30eSPhilippe Houdoin{
180e1d5f30eSPhilippe Houdoin	switch (msg->what) {
181e1d5f30eSPhilippe Houdoin	case MSG_CONNECT_REQUEST:
182e1d5f30eSPhilippe Houdoin		{
183e1d5f30eSPhilippe Houdoin			BControl* ctrl;
184e1d5f30eSPhilippe Houdoin			if (msg->FindPointer("source", (void**) &ctrl) == B_OK) {
185e1d5f30eSPhilippe Houdoin				PatchCheckBox* box = dynamic_cast<PatchCheckBox*>(ctrl);
18682fbbe21SPete Goodeve				if (box != NULL)
187e1d5f30eSPhilippe Houdoin					box->DoConnect();
188e1d5f30eSPhilippe Houdoin			}
189e1d5f30eSPhilippe Houdoin		}
190e1d5f30eSPhilippe Houdoin		break;
191e1d5f30eSPhilippe Houdoin	default:
192e1d5f30eSPhilippe Houdoin		BView::MessageReceived(msg);
193e1d5f30eSPhilippe Houdoin		break;
194e1d5f30eSPhilippe Houdoin	}
195e1d5f30eSPhilippe Houdoin}
196e1d5f30eSPhilippe Houdoin
19742b7984aSPete Goodeve
19842b7984aSPete Goodevevoid
19942b7984aSPete GoodevePatchCheckBox::DoConnect()
200e1d5f30eSPhilippe Houdoin{
201e1d5f30eSPhilippe Houdoin	int32 value = Value();
202e1d5f30eSPhilippe Houdoin	int32 inverseValue = (value + 1) % 2;
203e1d5f30eSPhilippe Houdoin
204e1d5f30eSPhilippe Houdoin	BMidiRoster* roster = BMidiRoster::MidiRoster();
20542b7984aSPete Goodeve	if (roster == NULL) {
206e1d5f30eSPhilippe Houdoin		SetValue(inverseValue);
207e1d5f30eSPhilippe Houdoin		return;
208e1d5f30eSPhilippe Houdoin	}
209e1d5f30eSPhilippe Houdoin
21042b7984aSPete Goodeve	BMidiProducer* producer = roster->FindProducer(fProducerID);
21142b7984aSPete Goodeve	BMidiConsumer* consumer = roster->FindConsumer(fConsumerID);
21282fbbe21SPete Goodeve	if (producer != NULL && consumer != NULL) {
213e1d5f30eSPhilippe Houdoin		status_t err;
21482fbbe21SPete Goodeve		if (value != 0)
215e1d5f30eSPhilippe Houdoin			err = producer->Connect(consumer);
21642b7984aSPete Goodeve		else
217e1d5f30eSPhilippe Houdoin			err = producer->Disconnect(consumer);
218e1d5f30eSPhilippe Houdoin
219e1d5f30eSPhilippe Houdoin		if (err != B_OK) {
220e1d5f30eSPhilippe Houdoin			SetValue(inverseValue);
221e1d5f30eSPhilippe Houdoin		}
22242b7984aSPete Goodeve	} else
223e1d5f30eSPhilippe Houdoin		SetValue(inverseValue);
22442b7984aSPete Goodeve
22582fbbe21SPete Goodeve	if (producer != NULL)
22682fbbe21SPete Goodeve		producer->Release();
22782fbbe21SPete Goodeve	if (consumer != NULL)
22882fbbe21SPete Goodeve		consumer->Release();
229e1d5f30eSPhilippe Houdoin}
230