BControllable¶
Constructor and Destructor¶
BControllable()
explicit BControllable::BControllable()
The BControllable constructor. You should override this in your
derived class to create a BParameterWeb
object, configure it
to describe the available parameters, and call
SetParameterWeb()
with that object before
returning.
Member Functions¶
BroadcastChangedParameter()
status_t BControllable::BroadcastChangedParameter(int32 parameterID)
When the configuration of a specific parameter changes, you should call this function with the ID of the changed parameter so that clients know that they need to check with the node to determine the parameter’s new configuration.
Note
The configuration of a parameter changes only when the range of possible
values for the parameter changes. For example, if the parameter’s value is
a CD track number, the configuration would change (thus requiring a call to
BroadcastChangedParameter()
) if the user put in
a different CD with a different number of tracks on it.
Return Code |
Description |
---|---|
|
No errors. |
Other errors. |
BroadcastNewParameterValue()
status_t BControllable::BroadcastNewParameterValue(bigtime_t when, int32 id, void *newValue, size_t valueSize)
Call this function when a parameter value change takes effect and you want
people that are interested in knowing about the change to stay in sync with
you. Unlike BroadcastChangedParameter()
, this
function actually passes along the new value of the parameter.
The when argument indicates the performance time at which the change took effect. The id indicates the parameter ID of the parameter whose value changed. newValue is a pointer to the parameter’s data, and valueSize defines the size of that data.
Return Code |
Description |
---|---|
|
No error. |
Other errors. |
An error occurred communicating with the Media Server, or with a node in the roster. |
GetParameterValue(), SetParameterValue()
virtual status_t BControllable::GetParameterValue(int32 parameterID, bigtime_t *lastChangeTime, void *value, size_t *ioSize) = 0
virtual void BControllable::SetParameterValue(int32 parameterID, bigtime_t changeTime, const void *value, size_t size) = 0
You should implement GetParameterValue() to store the value of the parameter with the specified parameterID in the memory pointed to by value. The size_t value pointed to by ioSize specifies the size of the value buffer; prior to returning, your implementation of GetParameterValue() should change ioSize to the actual size of the returned data.
Also, you should set lastChangeTime to the time at which the control’s value most recently changed.
GetParameterValue() should return B_OK
when
done, or an appropriate error code if something goes wrong.
Likewise, you should implement SetParameterValue() to change the value of the parameter; the changeTime argument is the performance time at which the change should occur; in other words, you may need to queue the request so it can be handled at the requested time. value points to the value to which the parameter should be set, and size is the number of bytes of data in the value.
Note
It’s possible that a single parameter may have several channels of values,
if that parameter is a multi-channel parameter. For example, if the
parameter is a two-channel slider (such as a stereo gain control, where the
left and right channels are controlled individually within a single
parameter), the value argument would point to an array of two
floats, and size would be 8 (sizeof(float) * 2
).
HandleMessage()
virtual status_t BControllable::HandleMessage(int32 message, const void *data, size_t *size_t)
When your node’s service loop receives a message, in addition to passing it
to BMediaNode
and other superclasses of your node, you should
also pass it to HandleMessage(). You should start at the
most-derived class’ implementation of HandleMessage() and work
your way upward until B_OK
is returned.
If it’s a message intended for the BControllable
interface,
it’ll be dispatched and B_OK
will be returned; otherwise,
HandleMessage() will return an error so you know to try
something else.
/* Message received */
if ((BControllable::HandleMessage(message, data, size) != B_OK) &&
(BMediaNode::HandleMessage(message, data, size) != B_OK)) {
BMediaNode::HandleMessage(message, data, size);
}
In this example, the BControllable implementation of
HandleMessage() gets the first crack at handling the request. If
it doesn’t know what to do with the message, it’s forwarded to
BMediaNode
’s implementation. If the message still isn’t
handled, it’s then sent to BMediaNode::HandleBadMessage()
to be
dealt with.
Return Code |
Description |
---|---|
|
The message was dispatched. |
Other errors. |
Each message code may respond with various error codes. |
See also: “About Multiple Virtual Inheritance
”
LockParameterWeb(), UnlockParameterWeb()
bool BControllable::LockParameterWeb()
void BControllable::UnlockParameterWeb()
LockParameterWeb() locks the web to prevent access to it while you’re working on it, and UnlockParameterWeb() releases it when you’re done. You should surround your accesses to the web with these calls:
LockParameterWeb();
Web()->MakeGroup("EqualizerControls");
...
UnlockParameterWeb();
MakeParameterData(), ApplyParameterData()
status_t BControllable::MakeParameterData(const int32 *parameterList, int32 numParameters, void *buffer, size_t *ioSize)
status_t BControllable::ApplyParameterData(const void *value, size_t ioSize)
The MakeParameterData() utility function takes a list of
parameter IDs from parameterList and calls
GetParameterValue()
for each of them, storing
the values in the specified buffer until the size specified in
ioSize is filled, or all the parameters are read. The number of
bytes of the buffer used will be returned in ioSize.
If your BControllable is also a BBufferConsumer
that
accepts B_MEDIA_PARAMETERS
type data on some input, call
ApplyParameterData() with value set to the result of
BBuffer::Data()
and size set to
BBuffer::SizeUsed()
. This function will then parse the
parameter change requests in the buffer and dispatch them to your
SetParameterValue() function to fulfill the requests.
This lets your node support easy automation of parameter information. Even
more benefit can be obtained by also deriving from
BBufferProducer
, and providing an output for the
B_MEDIA_PARAMETERS
data format, so that changes can be
recorded as they occur. This provides a mechanism for automating the
parameters by recording a user’s changes to them, then playing back the
changes later.
Return Code |
Description |
---|---|
|
No errors. |
|
The output buffer is too small. |
SetParameterWeb()
status_t BControllable::SetParameterWeb(BParameterWeb *web)
BParameterWeb *BControllable::SetParameterWeb()
Your constructor should create a BParameterWeb
object and call
SetParameterWeb() with it as an argument. This will describe to
the outside world what parameters are available and how they relate to each
other; in other words, this describes your internal signal path, and how it
can be manipulated.
If the web argument isn’t NULL, and is different from
the previously-established web for the BControllable node, a
B_MEDIA_WEB_CHANGED
message is sent to everyone watching
for media notifications. See StartWatching()
for
more information.
SetParameterWeb() will return B_OK
if the web
was set without errors; otherwise an error code will be returned.
The Web() function returns the BParameterWeb
assigned to the BControllable.
StartControlPanel()
virtual status_t BControllable::StartControlPanel(BMessenger *outMessenger)
This hook function is called whenever a client application wants the node to present its own control panel user interface (so that the user can configure the node).
On return, outMessenger is a BMessenger
that you can
use to communicate with the control panel.
Because the add-on lives in the Media Server, and a problem in the user interface could bring down the entire system, it’s recommended that the control panel run as its own team. This can be done easily by writing your node as both a Media Server add-on (by exporting make_media_addon()) and an application (by implementing main() and including start_dyn.o among the link libraries). Be sure you have the multi-launch application flags set on your add-on, or this won’t work right.
Then your StartControlPanel() implementation can simply launch the add-on as an application, and if the user double-clicks the add-on, they’ll be presented with the control panel. In addition, the user benefits by only having to install a single file for your add-on to work properly.
The first argv argument to your main() function will be a string of the format “node=%d” with the node ID in question as “%d”.
Note
The above implementation suggestion (providing your control panel by
launching the add-on as an application) is the default behavior of
StartControlPanel(), so if that’s how you implement your
BControllable, you don’t have to override
StartControlPanel() at all. In this case, the returned
BMessenger
is for the control panel application, and not for a
particular BWindow
or BView
therein.
Return Code |
Description |
---|---|
|
No errors occurred. |
|
Node wasn’t loaded from an add-on. |
|
An error occurred locating the image from which the node was loaded, or the add-on can’t be launched as an application. |
|
The control panel couldn’t be launched for some other reason, such as insufficient memory. |