BControllable

Derived from: virtual BMediaNode

Declared in: be/media/Controllable.h

Library: libmedia.so

Allocation: Constructor only

[method summary]

A node whose behavior can be controlled by the user should be derived from BControllable, as well as from whatever other interface classes the node might be derived from. Deriving from BControllable lets the node publish information about the parameters that can be adjusted and how they relate to each other.

A client application can use the published information to build a user interface for the node or pass the information through to a system routine that will build the interface.

A node can also have the ability to start its own control panel under outside control, which can take advantage of special knowledge of the node.

<<<need an example somewhere of how to tie this together with BParameterWeb and BParameter>>>


Constructor


BControllable()

protected:

      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 BControllable::SetParameterWeb() with that object before returning.


Member Functions


ApplyParameterData() see MakeParameterData()


BroadcastChangedParameter()

protected:

      status_t 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.

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 CODES

B_OK. No errors.

BMessenger::SendMessage() errors.


GetParameterValue(), SetParameterValue()

protected:

      virtual status_t GetParameterValue(int32 parameterID, bigtime_t *lastChangeTime,
         void *value, size_t *ioSize) = 0
      virtual void 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.

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 HandleMessage(int32 message, const void *data, size_t size)

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 BControllable::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::HandleBadMessage(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 CODES

B_OK. The message was dispatched.

Other errors, as appropriate. Each message code may respond with various error codes.

See also: BMediaNode::HandleMessage(), About Multiple Virtual Inheritance


MakeParameterData(), ApplyParameterData()

protected:

      status_t MakeParameterData(const int32 *parameterList, int32 numParameters,
         void *buffer, size_t *ioSize)
      status_t ApplyParameterData(const void *value, size_t size)

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::Size(). 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 CODES

B_OK. No errors.

B_NO_MEMORY. The output buffer is too small.


SetParameterValue() see GetParameterValue()


SetParameterWeb(), Web()

protected:

      status_t SetParameterWeb(BParameterWeb *web)
      BParameterWeb *Web(void)

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() on 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()

protected:

      virtual status_t 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 teh 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).

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 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 CODES

B_OK. No errors occurred.

B_ERROR. Node wasn't loaded from an add-on.

B_BAD_VALUE. An error occurred locating the image from which the node was loaded, or the add-on can't be launched as an application.

B_LAUNCH_FAILED. The control panel couldn't be launched for some other reason, such as insufficient memory.


Web() see SetParameterWeb()






The Be Book, in lovely HTML, for BeOS Release 4.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified December 22, 1998.