The Media Kit: BMediaRoster

The Media Kit Table of Contents | The Media Kit Index

# BMediaRoster

Derived from: BLooper

Declared in: be/media/MediaRoster.h

Library: libmedia.so

Allocation: Constructor only

###### Summary

The BMediaRoster class comprises the functionality that applications that use the Media Kit can access.

An application can only have a single instance of the BMediaRoster class, which is accessed by calling the static member function `BMediaRoster::Roster()`, which creates the media roster, establishes the connection to the Media Server, then returns a pointer to the roster.

The creation of the roster object is thread protected, so you can safely call `BMediaRoster::Roster()` from multiple threads without synchronization, and both threads will safely get the same instance. The cost of this synchronization is low enough that there's no need to cache the returned pointer, but it's perfectly safe to do so if you wish:

       BMediaRoster *gMediaRoster;

       int main(void) {
          status_t err;

          BApplication app("application/x-vnd.me-myself");
          gMediaRoster = BMediaRoster::Roster(&err);

          if (!gMediaRoster || (err != B_OK)) {
             /* the Media Server appears to be dead -- handle that here */
          }

          /* The Media Server connection is in place -- enjoy! */

          return 0;
       }

Because BMediaRoster is derived from BLooper, you should create your BApplication before calling `BMediaRoster::Roster()`, although the BApplication doesn't have to be running yet.

You should never delete the BMediaRoster returned to you by `BMediaRoster::Roster()`. Also, you can't derive a class from BMediaRoster.

If you want to receive notifications from the Media Server when specific changes occur, such as nodes coming online or going offline, for example, you can register to receive such notifications by calling `StartWatching()`.

## Playing Media from Disk

To play a media file from disk, you would follow the following steps:

- Create an entry_ref that refers to the file to be played.

- Call `SniffRef()` to obtain a dormant_node_info reference to the node that is best capable of playing back the media file.

- Call `InstantiateDormantNode()` to instantiate the node; this returns a media_node that you can use for other BMediaRoster calls.

- Use `SetRefFor()` to pass the entry_ref of the file to be played to the node.

- Call `GetFreeOutputs()` to obtain a media_output structure describing an available output on the producer node. This structure contains a media_source you can pass to `Connect()` as the source of the media data.

- The media_output structure returned by `GetFreeOutputsFor()` contains a media_format field that indicates the general type of media data contained by the media file; if you don't already know what type of data you're playing back (audio or video or whatever), this will let you determine what you'll be playing.

- You can use this value to determine what type of destination is needed to output the data (for example, `B_MEDIA_RAW_AUDIO` would go to an audio output, and `B_MEDIA_RAW_VIDEO` would go to a video output).

- Call `GetAudioMixer()` to get a media_node for the default audio mixer (if the media data is audio), or `GetVideoOutput()` to get a media_node for the default video output (if the media data is video).

- Use `GetFreeInputsFor()` to obtain a media_input structure describing an available input on the consumer node (the audio mixer or video output); this structure contains a media_destination you can pass to `Connect()`.

- Call `Connect()` to connect the source to the destination.

- Next, you need to set the time source for the media file's node. Normally you'll set this to the preferred time source. The audio mixer or video output is already slaved to an appropriate time source.

- Finally, you can use `StartNode()` to start the producer, consumer, and time source. The media file should begin playing back.

  Let's look at actual sample code that does this. This example is particular to playing movie files; in particular, it assumes that the video is encoded (`B_MEDIA_ENCODED_VIDEO`) and that the audio is in a raw audio format (`B_MEDIA_RAW_AUDIO`). However, it demonstrates the principles of playing both encoded and raw media formats, and you can easily extrapolate from it any type of playback you need. First it's necessary to identify an appropriate node to handle the file, and to instantiate the node and configure it for the file we want to play:

         bigtime_t      duration;
         media_node      timeSourceNode;

         media_node      mediaFileNode;
         media_output   fileNodeOutput;
         int32         fileOutputCount;

         media_output   fileAudioOutput;
         int32         fileAudioCount;

         media_node      codecNode;
         media_output   codecOutput;
         media_input      codecInput;

         media_node      videoNode;
         media_input      videoInput;
         int32         videoInputCount;

         media_node      audioNode;
         media_input      audioInput;
         int32         audioInputCount;

         dormant_node_info nodeInfo;
         status_t err;

         playingFlag = false;
         roster = BMediaRoster::Roster();

         initStatus = roster->SniffRef(*ref, 0, &nodeInfo);
         if (initStatus) {
            return;
         }

         initStatus = roster->InstantiateDormantNode(nodeInfo, &mediaFileNode);
         if (initStatus) {
            return;
         }

         roster->SetRefFor(mediaFileNode, *ref, false, &duration);
         if ((err = Setup()) != B_OK) {
            printf("Error %08lX in Setup()n", err);
         }
         else {
            Start();
         }

  This code begins by obtaining a pointer to the media roster. It then calls `SniffRef()` to get a `dormant_node_info` structure describing the best-suited node for reading the media data from the file specified by `ref`.

  Once a `dormant_node_info` structure has been filled out, the `InstantiateDormantNode()` function is called to instantiate a node to handle the file. A dormant node is a node whose code resides in an add-on, instead of within the application itself. The `nodeInfo` structure is passed into the function, and on return, the `mediaFileNode` has been set up for the appropriate node.

  Since the media_node `mediaFileNode` is a file handling node, the `SetRefFor()` function is then called to tell the newly-instantiated file handler node what file it should handle. The inputs here are:

  - `mediaFileNode` is the node whose file reference is to be set.

  - `ref` is the file that the node should reference.

  - `false` indicates that the file must already exist. If this flag were true, and the file indicated by ref were nonexistent, the node would create a new file. Since we're playing a file, we don't want to do that.

  - `duration` is a bigtime_t variable that will receive the duration of the media file, in microseconds.

  Once this has been accomplished, it's time to instantiate the other nodes needed to perform the media playback. Note that your code should check the error results from each of these calls and only proceed if `B_OK` is returned.

  The `Setup()` and `Start()` functions used in the example above are given below. `Setup()` actually sets up the connections and instantiates the various other nodes (such as codecs and output nodes) required to play back the media data. Let's take a look at `Setup()` next:

         status_t MediaPlayer::Setup(void) {
            status_t err;
            media_format tryFormat;
            dormant_node_info nodeInfo;
            int32 nodeCount;

            err = roster->GetAudioMixer(&audioNode);
            err = roster->GetVideoOutput(&videoNode);

  First, `GetAudioMixer()` and `GetVideoOutput()` are called to obtain an audio mixer node and a video output node. The nodes returned by this function are based on the user's preferences in the Audio and Video preference applications. By default, video is output to a simple video output consumer that creates a window to contain the video display.

  | The VideoConsumer node will be available with R4.5; it's not provided in R4. In addition, there are no video producer nodes in R4; media add-ons for a variety of movie file formats will also be available beginning with R4.5.

            err = roster->GetTimeSource(&timeSourceNode);
            b_timesource = roster->MakeTimeSourceFor(timeSourceNode);

  This code obtains a media_node for the preferred time source, and then creates a BTimeSource object that refers to the same node; we'll need to be able to make some BTimeSource calls to obtain some specific timing information later.

  A time source is a node that can be used to synchronize other nodes. By default, nodes are slaved to the system time source, which is the computer>s internal clock. However, this time source, while very precise, isn>t good for synchronizing media data, since its concept of time has nothing to do with actual media being performed. For this reason, you typically will want to change nodes> time sources to the preferred time source.

  You can think of a media node (represented by the `media_node` structure) as a component in a home theater system you might have at home. It has inputs for audio and video (possibly multiple inputs for each), and outputs to pass that audio and video along to other components in the system. To use the component, you have to connect wires from the outputs of some other components into the component>s inputs, and the outputs into the inputs of other components.

  The Media Kit works the same way. We need to locate audio outputs from the `mediaFileNode` and find corresponding audio inputs on the `audioNode`. This is analogous to choosing an audio output from your new DVD player and matching it to an audio input jack on your stereo receiver. Since you can>t use ports that are already in use, we call `GetFreeOutputsFor()` to find free output ports on the `mediaFileNode`, and `GetFreeInputsFor()` to locate free input ports on the `audioNode`.

            err = roster->GetFreeOutputsFor(mediaFileNode, &fileAudioOutput, 1,
                        &fileAudioCount, B_MEDIA_RAW_AUDIO);
            err = roster->GetFreeInputsFor(audioNode, &audioInput, fileAudioCount,
                        &audioInputCount, B_MEDIA_RAW_AUDIO);

  We only want a single audio connection between the two nodes (a single connection can carry stereo sound), and the connection is of type `B_MEDIA_RAW_AUDIO`. On return, `fileAudioOutput` and `audioInput` describe the output from the `mediaFlieNode` and the input into the `audioNode` that will eventually be connected to play the movie>s sound.

  We likewise have to find a video output from the `mediaFileNode` and an input into the `videoNode`. In this case, though, we expect the video output from the `mediaFileNode` to be encoded, and the `videoNode` will want to receive raw, uncompressed video. We>ll work that out in a minute; for now, let>s just find the two ports:

            err = roster->GetFreeOutputsFor(mediaFileNode, &fileNodeOutput, 1,
                        &fileOutputCount, B_MEDIA_ENCODED_VIDEO)
            err = roster->GetFreeInputsFor(videoNode, &videoInput, fileOutputCount,
                        &videoInputCount, B_MEDIA_RAW_VIDEO);

  The problem we have now is that the `mediaFileNode` is outputting video that>s encoded somehow (like in Cinepak format, for instance). The `videoNode`, on the other hand, wants to display raw video. Another node must be placed between these to decode the video (much like having an adapter to convert PAL video into NTSC, for example). This node will be the codec that handles decompressing the video into raw form.

  We need to locate a codec node that can handle the video format being output by the `mediaFileNode`. This is accomplished like this:

            nodeCount = 1;
            err = roster->GetDormantNodes(&nodeInfo, &nodeCount,
                        &fileNodeOutput.format);
            if (!nodeCount) {
               return -1;
            }

  This call to `GetDormantNodes()` looks for a dormant node that can handle the media format specified by the `mediaFileNode`>s output `media_format` structure. Information about the node is returned in `nodeInfo`. `nodeCount` indicates the number of matching nodes that were found. If it>s zero, an error is returned.

  Note that in real life you should ask for several nodes, and search through them, looking at the formats until you find one that best meets your needs.

  Then we use `InstantiateDormantNode()` to instantiate the codec node, and locate inputs into the node (that accept encoded video) and outputs from the node (that output raw video):

            err = roster->InstantiateDormantNode(nodeInfo, &codecNode);
            err = roster->GetFreeInputsFor(codecNode, &codecInput, 1, &nodeCount,
                        B_MEDIA_ENCODED_VIDEO);
            err = roster->GetFreeOutputsFor(codecNode, &codecOutput, 1,
                        &nodeCount, B_MEDIA_RAW_VIDEO);

  Now we>re ready to start connecting these nodes together. If we were setting up a home theater system, right about now we>d be getting rug burns on our knees and skinned knuckles on our hands, trying to reach behind the entertainment center to run wires. The Media Kit is way easier than that, and doesn>t involve salespeople telling you to get expensive gold-plated cables.

  We begin by connecting the file node>s video output to the codec>s input:

            tryFormat = fileNodeOutput.format;
            err = roster->Connect(fileNodeOutput.source, codecInput.destination,
                        &tryFormat, &fileNodeOutput, &codecInput);

  `tryFormat` indicates the format of the encoded video that will be output by the `mediaFileNode`. `Connect()`, in essense, runs a wire between the output from the media node>s video output (`fileNodeOutput`) to the codec node>s input.

  You may wonder what>s up with the `fileNodeOutput.source` and `codecInput.destination` structures. These `media_source` and `media_destination` structures are simplified descriptors of the two ends of the connection. They contain only the data absolutely needed for the Media Kit to establish the connection. This saves some time when issuing the `Connect()` call (and time is money, especially in the media business).

  Next it>s necessary to connect the codec to the video output node. This begins by setting up `tryFormat` to describe raw video of the same width and height as the encoded video being fed into the codec, then calling `Connect()` to establish the connection:

            tryFormat.type = B_MEDIA_RAW_VIDEO;
            tryFormat.u.raw_video = media_raw_video_format::wildcard;
            tryFormat.u.raw_video.display.line_width =
                     codecInput.format.u.encoded_video.output.display.line_width;
            tryFormat.u.raw_video.display.line_count =
                     codecInput.format.u.encoded_video.output.display.line_count;
            err = roster->Connect(codecOutput.source, videoInput.destination,
                        &tryFormat, &codecOutput, &videoInput);

  Now we connect the audio from the media file to the audio mixer node. We just copy the `media_format` from the file>s audio output, since both ends of the connection should exactly match.

            tryFormat = fileAudioOutput.format;
            err = roster->Connect(fileAudioOutput.source, audioInput.destination,
                        &tryFormat, &fileAudioOutput, &audioInput);

  The last step of configuring the connections is to ensure that all the nodes are slaved to the preferred time source. This will keep them synchronized with the preferred time source (and by association, with each other):

            err = roster->SetTimeSourceFor(mediaFileNode.node, timeSourceNode.node);
            err = roster->SetTimeSourceFor(videoNode.node, timeSourceNode.node);
            err = roster->SetTimeSourceFor(codecOutput.node.node,
                     timeSourceNode.node);
            err = roster->SetTimeSourceFor(audioNode.node, timeSourceNode.node);
            return B_OK;
         }

  Finally, we return `B_OK` to the caller. Note that this code should be enhanced to check the results of each BMediaRoster call, and to return the result code if it's not `B_OK`. This has been left out of this example for brevity.

  The `Start()` function actually starts the movie playback. Starting playback involves starting, one at a time, all the nodes involved in playing back the audio. This includes the audio mixer (`audioNode`), the media file>s node (`mediaFileNode`), the codec, and the video node.

         status_t MediaPlayer::Start(void) {
            status_t err;
            err = roster->GetStartLatencyFor(timeSourceNode, &startTime);
            startTime += b_timesource->PerformanceTimeFor(BTimeSource::RealTime()
                        + 1000000 / 50);

            err = roster->StartNode(mediaFileNode, startTime);
            err = roster->StartNode(codecNode, startTime);
            err = roster->StartNode(videoNode, startTime);

            return B_OK;
         }

  Because there>s lag time between starting each of these nodes, we pick a time a few moments in the future for playback to begin, and schedule each node to start playing at that time. So we begin by computing that time in the future.

  The `BTimeSource::RealTime()` static member function is called to obtain the current real system time. We add a fiftieth of a second to that time, and convert it into performance time units. This is the time at which the performance of the movie will begin (basically a fiftieth of a second from "now"). This value is saved in `startTime`. These are added to the value returned by `GetStartLatencyFor()`, which returns the time required to actually start the time source and all the nodes slaved to it.

  Then we simply call `BMediaRoster::StartNode()` for each node, specifying `startTime` as the performance time at which playback should begin.

  Again, error handling should be added to actually return the error code from these functions.

  Stopping playback of the movie is even simpler:

            err = roster->StopNode(mediaFileNode, 0, true);
            err = roster->StopNode(codecNode, 0, true);
            err = roster->StopNode(videoNode, 0, true);

  This tells the media file, video codec, and video output nodes to stop immediately. If we wanted them to stop together at some time in the future, we could compute an appropriate performance time and pass that instead of 0. In this case, we would need to specify false for the last argument; when this value is true, `StopNode()` stops the node immediately. We could use this ability to schedule all three nodes to stop at the same time, so that video and audio playback would halt simultaneously.

  | Note that we don't stop the audio mixer node. You should never stop the mixer node, because other applications are probably using it.

  Once you're done playing the movie, and have stopped playback, you should disconnect the nodes from each other:

            err = roster->Disconnect(mediaFileNode.node, fileNodeOutput.source,
                         codecNode.node, codecInput.destination);
            err = roster->Disconnect(codecNode.node, codecOutput.source,
                         videoNode.node, videoInput.destination);
            err = roster->Disconnect(mediaFileNode.node, fileAudioOutput.source,
                         audioNode.node, audioInput.destination);

  This will close out the connections between the media file node and the video codec, the codec and the video output, and between the file node and the audio mixer. You should always stop playback before disconnecting; although nodes aren't allowed to crash if you disconnect them while running, their behavior isn't specified, and may not be what you expect.

  Once the connections are severed, you should release any dormant nodes you instantiated. This includes not only nodes instantiated using `InstantiateNodeFor()`, but also default nodes (those obtained using functions like `GetAudioInput()` and `GetVideoOutput()`, for example):

            roster->ReleaseNode(codecNode);
            roster->ReleaseNode(mediaFileNode);
            roster->ReleaseNode(videoNode);
            roster->ReleaseNode(audioNode);

  | If you want to play audio, you may find it much easier to use the BSound and BSoundPlayer classes to do so. As of R4.5, there are no Be-provided nodes for producing audio from a disk file.

  ### Detecting When Playback Is Complete

  There isn't a Media Kit function that can directly tell you whether or not the media has reached the end of the data during playback. However, the following easy-to-implement code can do the job for you:

         bigtime_t currentTime;
         bool isPlaying = true;

         currentTime = b_timesource->PerformanceTimeFor(BTimeSource::RealTime());
         if (currentTime >= startTime+duration) {
            isPlaying = false;
         }

  This works by obtaining the time source's performance time and comparing it to the time at which playback of the movie was begun plus the movie's duration (both of which were saved when we initially set up and began playback of the movie, as seen in the code in the previous section above).

  If the current performance time is equal to or greater than the sum of the starting time and the movie's duration, then playback is finished, and we set `isPlaying` to `false`; otherwise, this value remains `true`.

  ### Using BMediaRoster Functions from Nodes

  You can issue BMediaRoster function calls from within your own node, however, as a general rule, you shouldn't call BMediaRoster functions from within your control thread, or while the control thread is blocked. Many BMediaRoster functions use synchronous turnarounds, and will deadlock in this situation. You should assume, for safety's sake, that all BMediaRoster functions will deadlock if used in these cases.

  For example, if you have an application that's playing video into a window, and you call StopNode() from the window's MessageReceived() function, a deadlock would occur if the video player node blocks waiting on the window to be unlocked, and the StopNode() function is keeping the window locked while it waits for the video producer node, which is blocked waiting on the consumer node, and so forth. Deadlock results, and that's a bad thing.

  Instead, you should consider creating a seperate BLooper that manages your nodes. Future versions of the Media Kit will provide convenience classes to do some of this for you.

  ## Constructor and Destructor

  ### BMediaRoster()

  `BMediaRoster()`

  You never construct a BMediaRoster yourself. Instead, use the static `Roster()` function to obtain an instance of the BMediaRoster class that you can use.

  ### ~BMediaRoster

  `~BMediaRoster()`

  You never delete a BMediaRoster yourself. Just let it go away automatically when your application shuts down.

  ## Member Functions

  ### AudioBufferSizeFor()

  ssize_t `AudioBufferSizeFor(`int32 channelCount, uint32 sampleFormat, float frameRate, bus_type busKind`) `

  `AudioBufferSizeFor()` returns the size, in bytes, that the Media Kit recommends for audio data with channelCount channels, with the specified sampleFormat and frameRate.

  The busKind argument is a bus_type value (see drivers/config_manager.h) indicating the type of bus the data is moving across. Specify `B_UNKNOWN_BUS` if you don't know.

  ### Connect() , Disconnect()

  status_t `Connect(`const media_source &source,
  const media_destination &destination,
  media_format *ioFormat,
  media_output *outOutput,
  media_input *outInput`)

  `

  status_t `Connect(`const media_source &source,
  const media_destination &destination,
  media_format *ioFormat,
  media_output *outOutput,
  media_input *outInput,
  uint32 inFlags,
  void *_reserved = `NULL``)

  `

  status_t `Disconnect(`media_node_id sourceNode, const media_source &source, media_node_id destinationNode, const media_destination &destination`) `

  `Connect()` negotiates a connection from the source to the destination, using the media format specified in ioFormat as a basis for the negotiation; ioFormat is changed to the negotiated format before this call returns. This describes the format of media data that will flow across the connection.

  The actual connection is returned as an output and an input in outOutput and outInput. These two structures contain the data format as interpreted by the source and destination. There may be differences among these formats if wildcard fields were used in the original format.

  The second form of `Connect()` lets you specify connect flags. Currently the only possible flag is `B_CONNECT_MUTED`, which indicates that the connection should be muted on creation.

  The actual media_source and media_destination used for the connection may vary from those passed into `Connect()` if the source or the destination creates new sources or destinations for each connection request; the outOutput and outInput structures contain the actual media_source and media_destination values resulting from the call.

  For more detailed information on the use of wildcards in format negotiation, see `media_audio_format::wildcard` and `media_video_format::wildcard`. A media_format with a type of `B_MEDIA_UNKNOWN_TYPE` matches any media class and format, although without specific knowledge of the source and destination, this will rarely result in a useful connection.

  `Disconnect()` breaks the connection established between source and destination, which must belong to the nodes sourceNode and destinationNode, repectively.

  The result of breaking a connection that's currently running is undefined, but is not permitted to crash. Your application should stop both nodes involved in a connection prior to disconnecting them.

  | These functions will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error terminating the connection.

  - `B_NAME_NOT_FOUND`. The connection couldn't be made.

  - Other errors. The nodes that are being connected may return other error codes as they see fit.

  ### CurrentRoster() see Roster()

  ### GetAllInputsFor() , GetAllOutputsFor()

  status_t `GetAllInputsFor(`const media_node &node, media_input *outInputs, int32 bufNumInputs int32 *outTotalCount`) `
  status_t `GetAllOutputsFor(`const media_node &node, media_output *outOutputs, int32 bufNumOutputs int32 *outTotalCount`) `

  `GetAllInputsFor()` fills the array of media_input structures specified by outInputs with information about all inputs belonging to node; the number of elements that outInputs can hold is passed in bufNumInputs.

  Similarly, `GetAllOutputsFor()` fills the array outOutputs with information about all outputs from the specified node.

  Both functions return the number of elements actually returned in the buffer in outTotalCount. If this number is less than the number you requested, your buffer was too small to receive all the results of the query. In this case, you might want to resize your array and try again.

  | These functions will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error.

  - `B_MEDIA_BAD_NODE`. The node isn't of the correct type for the call you issued.

  - Other errors. An error occurred communicating with the producer or with the Media Server.

  ### GetAllOutputsFor() see GetAllInputsFor()

  ### GetAudioInput() , GetVideoInput()

  status_t `GetAudioInput(`media_node *outNode`) `
  status_t `GetVideoInput(`media_node *outNode`) `

  These functions return the nodes designated by the user as the preferred nodes for audio and video input. You can then query the returned node, hook into it, and manipulate it, using the reference returned in outNode.

  Once your application has finished using these nodes (and they've been stopped and disconnected), you should release them by calling `ReleaseNode()`.

  RETURN CODES

  `B_OK`. No error locating the default input node.

  - `B_NAME_NOT_FOUND`. The default node couldn't be identified.

  ### GetAudioMixer() see GetAudioOutput()

  ### GetAudioOutput() , GetVideoOutput() , GetAudioMixer()

  status_t `GetAudioOutput(`media_node *outNode`) `
  status_t `GetAudioOutput(`media_node *outNode, int32 *outInputID BString *outInputName`) `
  status_t `GetVideoOutput(`media_node *outNode`) `
  status_t `GetAudioMixer(`media_node *outNode`) `

  These functions return the nodes designated by the user as the preferred nodes for audio and video output. You can then query the returned node, hook into it, and manipulate it, using the reference returned in outNode.

  The second form of GetAudioOutput() returns additional information, including the input ID of the input used for audio output, and the input's name.

  You should usually use `GetAudioMixer()` when getting a node for playing audio instead of using the `GetAudioOutput()` function. `GetAudioOutput()` returns the lower-level node for audio output, which you would typically only need access to if you wanted to do some form of processing on all audio data being played in the system (such as a level meter).

  The `GetAudioMixer()` function returns a reference to the audio mixer, which will perform audio mixing, format conversion, and sample rate conversion for you, then pass along the audio to the output node.

  Once your application has finished using these nodes (and they've been stopped and disconnected), you should release them by calling `ReleaseNode()`.

  RETURN CODES

  `B_OK`. No error locating the default input node.

  - `B_NAME_NOT_FOUND`. The default node couldn't be identified.

  ### GetConnectedInputsFor() , GetFreeInputsFor()

  status_t `GetConnectedInputsFor(`const media_node &node, media_input *outActiveInputsList, int32 numListInputs int32 *outNumInputs`) `

  status_t `GetFreeInputsFor(`const media_node &node,
  media_input *outFreeInputsList,
  int32 numListInputs
  int32 *outNumInputs,
  media_type filterType = B_MEDIA_UNKNOWN_TYPE`)

  `

  `GetConnectedInputsFor()` fills the array of media_input structures specified by outActiveInputsList with information about all inputs belonging to node that are currently connected to some output; the number of elements that outActiveInputsList can hold is passed in numListInputs.

  Similarly, `GetFreeInputsFor()` fills the array outFreeInputsList with information about all inputs that are still available in the specified node. Specifying a filterType other than `B_MEDIA_NO_TYPE` lets you obtain a list of inputs for a specific media type (or for inputs that can handle any media type). This is especially useful if you're only interested in a list of accepted media types your application supports.

  Even though a node may report that a specific number of free inputs are available, it is possible that a node might create more inputs on demand. There is no way to know if this might happen, so `GetFreeInputsFor()` may not tell you whether or not a node can accept all the connections you'd like to make.

  Both functions return the number of elements actually returned in the buffer in outNumInputs. If this number is less than numListInputs, your buffer was too small to receive all the results of the query. In this case, you might want to resize your array and try again.

  | These functions will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error cloning the node.

  - `B_NAME_NOT_FOUND`. The requested node couldn't be cloned.

  ### GetConnectedOutputsFor() , GetFreeOutputsFor()

  status_t `GetConnectedOutputsFor(`const media_node &node, media_output *outActiveOutputsList, int32 numListOutputs int32 *outNumOutputs`) `

  status_t `GetFreeOutputsFor(`const media_node &node,
  media_output *outFreeOutputsList,
  int32 numListOutputs
  int32 *outNumOutputs,
  media_type filterType = B_MEDIA_UNKNOWN_TYPE`)

  `

  `GetConnectedOutputsFor()` fills the array of media_output structures specified by outActiveOutputsList with information about all outputs belonging to node that are currently connected to some input; the number of elements that outActiveOutputsList can hold is passed in numListOutputs.

  Similarly, `GetFreeOutputsFor()` fills the array outFreeOutputsList with information about all outputs that are still available in the specified node. Specifying a filterType other than `B_MEDIA_UNKNOWN_TYPE` lets you obtain a list of outputs for a specific media type (or for outputs that can handle any media type). This is especially useful if you're only interested in a list of accepted media types your application supports.

  Even though a node may report that a specific number of free outputs are available, it is possible that a node might create more outputs on demand. There is no way to know if this might happen, so `GetFreeOutputsFor()` may not tell you whether or not a node can accept all the connections you'd like to make.

  Both functions return the number of elements actually returned in the buffer in outNumOutputs. If this number is less than numListOutputs, your buffer was too small to receive all the results of the query. In this case, you might want to resize your array and try again.

  | These functions will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error.

  - `B_MEDIA_BAD_NODE`. The node isn't a buffer producer.

  - Other errors. An error occurred communicating with the producer or with the Media Server.

  ### GetDormantFlavorInfoFor()

  status_t `GetDormantFlavorInfoFor(`const dormant_node_info &inDormantNode, `dormant_flavor_info *`outFlavor`) `

  This function returns, in outFlavor, information describing the dormant flavors supported by the dormant node inDormantNode.

  RETURN CODES

  `B_OK`. No error.

  - Messaging errors. An error occurred communicating with the Media Server.

  ### GetDormantNodes()

  status_t `GetDormantNodes(`dormant_node_info *outDormantNodeList,
  int32 *inOutNumNodes,
  const media_format *hasInputFormat = NULL,
  const media_format *hasOutputFormat = NULL,
  char *name = NULL,
  uint64 requireKinds = 0,
  uint64 denyKinds = 0`)

  `

  Queries dormant nodes (those nodes that live in add-ons, rather than in the application) and returns those who match the specified inputs. If hasInputFormat isn't `NULL`, the node has to be a BBufferConsumer and have an input format compatible with the format described in hasInputFormat. Likewise, if hasOutputFormat isn't `NULL`, the node has to be a BBufferProducer that's compatible with the format described in hasOutputFormat.

  If name isn't `NULL`, the node has to have a name that equals name, or, if the last character of name is an asterisk ("*"), a name whose initial characters match name up to, but not including, the asterisk.

  The requireKinds and denyKinds arguments specifiy, respectively, the kinds that must be supported, and the kinds that must not be supported by the returned nodes.

  Matching nodes are returned in outDormantNodeList. You should pass the size of the outDormantNodeList array (the number of elements that the array can hold) in inOutNumNodes; when this function returns, the value in inOutNumNodes will be changed to the actual number of matching nodes found, unless an error occurs.

  Nodes you obtain using `GetDormantNodes()` must be released when you're done using them. To do this, be sure they're stopped and disconnected, then call `ReleaseNode()`.

  RETURN CODES

  `B_OK`. No error cloning the node.

  - `B_NAME_NOT_FOUND`. The requested node couldn't be cloned.

  ### GetFileFormatsFor()

  status_t `GetFileFormatsFor(`const media_node &fileInterface, media_file_format *outFormatList, int32 *inOutFormatCount`) `

  Given a BFileInterface node in fileInterface, returns information about the file formats the file interface can deal with in the array outFormatList. On entry, inOutFormatCount points to the number of media_file_format structures that can fit in the array specified by outFormatList. Upon return, it will contain the actual number of formats returned, unless `GetFileFormatsFor()` returns an error.

  | This function will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error sending the set mode request.

  - `B_NAME_NOT_FOUND`. The requested node couldn't be cloned.

  ### GetFormatFor()

  status_t `GetFormatFor(`const media_output &output, `media_format *`ioFormat, uint32 flags = 0`) `
  status_t `GetFormatFor(`const media_input &input, `media_format *`ioFormat, uint32 flags = 0`) `
  status_t `GetFormatFor(`const media_node &node, `media_format *`ioFormat, float quality = B_MEDIA_ANY_QUALITY`) `

  `GetFormatFor()` returns the media_format being used by the given object, which may be a media_output, a media_input, or a media_node. Pass in ioFormat a pointer to a media_format object to be filled out with the object's format.

  The flags currently must be zero.

  RETURN CODES

  `B_OK`. No error.

  - `B_BAD_VALUE`. You can't pass `NULL` for ioFormat.

  - `B_MEDIA_BAD_NODE`. The node isn't of the correct type for the given request.

  - `B_MEDIA_BAD_SOURCE`. The node's media_source is invalid.

  - Messaging errors. An error occurred communicating with the Media Server.

  ### GetFreeInputsFor() see GetConnectedInputsFor()

  ### GetFreeOutputsFor() see GetConnectedOutputsFor()

  ### GetInitialLatencyFor()

  status_t `GetInitialLatencyFor(`media_node &producer, bigtime_t *outLatency, uint32 *outFlags = NULL`) `

  Returns, in outLatency, the additional amount of time in microseconds the specified producer node requires in order to synchronize to a signal. For example, a TV capture card that's started while the capture is in the middle of a field will have to wait until the next field begins before actually starting to produce buffers.

  outFlags is set to the flags returned by the producer. Currently there aren't any flags defined, so this will be returned as zero for now.

  RETURN CODES

  `B_OK`. No error.

  - `B_BAD_VALUE`. outLatency was specified as `NULL`.

  - `B_MEDIA_BAD_NODE`. producer isn't a valid node.

  - Port errors. An error occurred communicating with the producer.

  ### GetInstancesFor()

  status_t `GetInstancesFor(`media_addon_id addon, int32 flavor, media_node_id *outID, int32 *ioCount = 0`) `

  Given the specified addon ID and flavor, this function fills the outID list with up to ioCount node IDs that were derived from the specified add-on. If you specify zero for ioCount, one node ID will be returned. On return, ioCount is changed to indicate how many nodes have been returned in the list.

  RETURN CODES

  `B_OK`. No error.

  - Port errors. Communication with the Media Server failed.

  ### GetLatencyFor()

  status_t `GetLatencyFor(`const media_node &producer, bigtime_t *outLatency`) `

  Reports in outLatency the maximum latency found downstream from the specified BBufferProducer, producer, given the current connections.

  If an error occurs, the value in outLatency is unreliable.

  | This function will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No errors.

  - Other errors. Unable to get the latency.

  ### GetLiveNodes()

  status_t `GetLiveNodes(`live_node_info *outLiveNodeList, int32 *ioTotalCount,
  const media_format *hasInput = NULL,
  const media_format *hasOutput = NULL,
  const char *name = NULL,
  uint64 nodeKinds = 0`)

  `

  Queries the Media Server for a list of all currently active nodes (whether they're running or not), and fills the array specified by outLiveNodeList with information about the nodes. The size of the array should be specified—in terms of how many elements it can contain—by the ioTotalCount argument; the actual number of entries in the returned list will be stored in ioTotalCount before the call returns.

  An active node is a node that is preloaded by the system and is always available for use, as opposed to a dormant node, which resides in an add-on and is only loaded when instantiated using `InstantiateDormantNode()`.

  You can obtain a more specific result list by specifying one or more of the hasInput, hasOutput, name, and nodeKinds arguments. hasInput and hasOutput let you restrict the resulting list to containing nodes that accept as input (or output) the specified format.

  You should always specify 0 for nodeKinds; this parameter is currently not used.

  RETURN CODES

  `B_OK`. No errors.

  - Other errors. Unable to get the list of live nodes.

  ### GetNodeAttributesFor()

  ssize_t `GetNodeAttributesFor(`const media_node &node, media_node_attributes *outArray, size_t inMaxCount`) `

  Fills the array outArray with up to inMaxCount attributes of the given node. Returns the number of attributes returned. If the result is less than zero, an error occurred.

  <<<more on node attributes>>>

  ### GetNodeFor()

  status_t `GetNodeFor(`media_node_id nodeID, media_node *clonedNode`) `

  Given a node specified by node_id, `GetNodeFor()` returns in clonedNode a media_node reference to a clone of the node. You can then use the clonedNode to query the node for available inputs, outputs, and so forth.

  Once your application has finished using the returned node (and it's been stopped and disconnected), you should release it by calling `ReleaseNode()`.

  RETURN CODES

  `B_OK`. No error cloning the node.

  - BMessage errors. The requested node couldn't be cloned.

  ### GetParameterWebFor()

  status_t `GetParameterWebFor(`const media_node & node, BParameterWeb **outWeb`) `

  Instantiates a BParameterWeb that describes the internal layout of a specific controllable node and stores a pointer to the BParameterWeb in outWeb. You can then walk the various BParameters within the web to figure out what there is to control, and to present a user interface to the node's parameters. Delete the web pointed to by outWeb when you're done with it.

  Note that the `StartControlPanel()` function provides an easy, painless way to automatically present user interface for configuring nodes.

  | This function will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error obtaining the BParameterWeb.

  - `B_MEDIA_BAD_NODE`. The requested node is invalid.

  See also: `StartControlPanel()`

  ### GetReadFileFormatListFor() , GetWriteFileFormatListFor()

  status_t `GetReadFileFormatList(`const dormant_node_info &inNode, media_file_format *outReadFormats, int32 inReadCount, int32 *outReadCount`) `
  status_t `GetWriteFileFormatList(`const dormant_node_info &inNode, media_file_format *outWriteFormats, int32 inWriteCount, int32 *outWriteCount`) `

  These two functions return lists of file formats that the dormant node described by inNode can read or write.

  `GetReadFileFormatList()` returns in the array specified by outReadFormats a list of file formats the node can read. Specify in inReadCount the number of formats that can be held by the outReadFormats array. On exit, outReadCount indicates how many formats are being returned in the array.

  GetWriteFileFormatList() returns in the array specified by outWriteFormats a list of file formats the node can write. Specify in inWriteCount the number of formats that can be held by the outWriteFormats array. On exit, outWriteCount indicates how many formats are being returned in the array.

  RETURN CODES

  `B_OK`. The list was returned without error.

  - `B_BAD_VALUE`. outReadFormats or outWriteFormats is NULL.

  - BMessage errors. An error occurred communicating with the Media Server.

  ### GetRealtimeFlags() , SetRealtimeFlags()

  status_t `GetRealtimeFlags(`uint32 *outEnabled`) `
  status_t `SetRealtimeFlags(`uint32 inEnabled`) `

  `GetRealtimeFlags()` returns flags that the Media Server uses to determine whether or not memory needs to be locked down. `SetRealtimeFlags()` sets these flags, and is generally only called by the Media preference application.

  Any or all of these flags can be set, in combination.

  Constant | Description
  --- | ---
  `B_MEDIA_REALTIME_ALLOCATOR` | When set, rtm_alloc() will return locked memory.
  `B_MEDIA_REALTIME_AUDIO` | Audio add-ons in the Media Server are locked in memory, and should lock their thread stacks using `media_init_realtime_thread()`.
  `B_MEDIA_REALTIME_VIDEO` | Video add-ons are locked in memory, and should lock their thread stacks using `media_init_realtime_thread()`.
  `B_MEDIA_REALTIME_ANYKIND` | All Media add-ons are locked in memory, and should lock their thread stacks using `media_init_realtime_thread()`.

  See the BMediaNode overview for a discussion of realtime allocation and thread stack locking.

  RETURN CODES

  `B_OK`. No error.

  - Other errors. Unable to set or retrieve the realtime flags.

  ### GetRefFor() see SetRefFor()

  ### GetStartLatencyFor()

  status_t `GetStartLatencyFor(`const media_node &timeSource, bigtime_t *outLatency`) `

  Reports in outLatency the maximum latency found downstream from the time source specified by timeSource, given the current connections.

  If an error occurs, the value in outLatency is unreliable.

  | This function will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No errors.

  - Other errors. Unable to get the latency.

  ### GetSystemTimeSource()

  status_t `GetSystemTimeSource(`media_node *clonedTimeSource`) `

  This function returns, in clonedTimeSource, a reference to a clone of the system time source. The system time source is the fallback time source used when no other source is available; its time is derived from the `system_time()` real-time clock. As such, it's quite accurate, but has no relevant relationship to the timing of the hardware devices being used for media input and output. Thus it's not a good choice for a master clock—but it's there if nothing else is available.

  By default, new nodes are slaved to the system time source.

  RETURN CODES

  `B_OK`. No error cloning the node.

  - `B_NAME_NOT_FOUND`. The time source couldn't be cloned.

  ### GetTimeSource() , MakeTimeSourceFor()

  status_t `GetTimeSource(`media_node *outNode`) `
  BTimeSource *`MakeTimeSourceFor(`media_node &node`) `

  `GetTimeSource()` returns, in outNode, the preferred master clock to which other nodes can be slaved. By slaving all nodes to a single master clock, good synchronization can be ensured.

  Typically, the preferred master clock will be the same node as the default audio output (assuming that the audio output node is also a BTimeSource, which should be the case). The sound circuitry's DAC is then used as a timing reference. Although this may be less accurate than the system clock (as defined by the global `system_time()` function), glitch-free audio performance is best ensured by using the audio output to synchronize media operations.

  By default, nodes are slaved to the system time source (see `GetSystemTimeSource()` above). Usually you'll want to use this function to obtain a more accurate time source, then slave your nodes to it:

         media_node timeSource;
         roster->GetTimeSource(&media_node);
         roster->SetTimeSourceFor(myNode, timeSource.node);

  This will slave the previously-created node `myNode` to the preferred time source.

  | The time source's reference count isn't incremented by `GetTimeSource()`. You should never call `ReleaseNode()` on a node returned by `GetTimeSource()`.

  `MakeTimeSourceFor()` returns a BTimeSource object corresponding to the specified node's time source. This object can then be used to issue BTimeSource calls to determine and adjust timing issues (for instance, to determine the current performance time). When you're done with the BTimeSource, you should call `BMediaNode::Release()` on it.

  RETURN CODES

  `B_OK`. No error locating the default input node.

  - `B_NAME_NOT_FOUND`. The default node couldn't be identified.

  ### GetVideoInput() see GetAudioInput()

  ### GetVideoOutput() see GetAudioOutput()

  ### GetWriteFileFormatListFor() see GetReadFileFormatListFor()

  ### InstantiateDormantNode()

  status_t `InstantiateDormantNode(`const dormant_node_info &inInfo, media_node *outNode`) `
  status_t `InstantiateDormantNode(`const dormant_node_info &inInfo, media_node *outNode, uint32 flags`) `

  These functions instantiate a node from an add-on, given the information specified in the dormant_node_info structure:

         struct dormant_node_info {
            dormant_node_info();
            ~dormant_node_info();

            media_addon_id addon;
            int32 flavor_id;
            char name[B_MEDIA_NAME_LENGTH];

         private:
            char reserved[128];
         };

  The addon field should be filled out to contain the add-on ID of the add-on from which the node should be instantiated, and the flavor_id should be the flavor ID number the node should be instantiated to process. Typically you'll use a function such as `GetDormantNodes()` to find a `dormant_node_info` structure that describes a suitable node.

  When you're done using the node, and have stopped and disconnected it, you should always call `ReleaseNode()` to let the Media Server know you're finished with it. This lets the Media Server track whether or not the node's add-on can be unloaded, based on the number of applications still using it.

  The difference between these two functions is that the second form lets you specify flags controlling how the node is instantiated. The `B_FLAVOR_IS_GLOBAL` flag`` instantiates the node in the Media Add-on Server's memory space, while the `B_FLAVOR_IS_LOCAL` flag instantiates the node in your application's memory. Using `B_FLAVOR_IS_LOCAL` protects other applications—not to mention the Media Server—from being derailed if the node crashes. Whenever possible, you should instantiate nodes locally. You should only use `B_FLAVOR_IS_GLOBAL` if you need the node to stay around after your application exits.

  RETURN CODES

  `B_OK`. No error instantiating the node.

  - `B_NAME_NOT_FOUND`. The requested node couldn't be instantiated.

  ### MakeTimeSourceFor() see GetTimeSource()

  ### MediaFlags()

  static ssize_t `MediaFlags(`media_flags flag, void *buffer, size_t bufferSize`) `

  Asks the Media Server about its support for specific features and capabilities.

  The specified buffer will be filled with the data indicating the value of the specified flag. If the buffer is too small (as indicated by bufferSize), only the first bufferSize bytes of the result data will be stored in the buffer, but no error will occur.

  Constant | Description
  --- | ---
  `B_MEDIA_FLAGS_VERSION` | Returns the Media Kit version as an int32 value.

  If the result is negative, an error occurred, or the Media Server isn't running.

  ### NodeIDFor()

  media_node_id `NodeIDFor(`port_id sourceOrDestinationPort`) `

  Given a source or destination port, this function returns the corresponding node's ID number.

  ### PrerollNode()

  status_t `PrerollNode(`const media_node &node`) `

  Calling `PrerollNode()` sends a preroll message to the specified node; the node's `Preroll()` hook function will be called. When that hook returns, `PrerollNode()` will also return. A node that's been prerolled should respond very quickly to a `StartNode()` call, because the time-consuming setup operations should have been done already by the `Preroll()` hook.

  While it's not mandatory for an application to call `PrerollNode()` before calling `StartNode()`, it's recommended, because doing so may improve real-time performance once the node is started.

  | This function will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error sending the set mode request.

  - `B_NAME_NOT_FOUND`. The requested node couldn't be cloned.

  ### RegisterNode() , UnregisterNode()

  status_t `RegisterNode(` BMediaNode *node`) `
  status_t `UnregisterNode(` BMediaNode *node`) `

  `RegisterNode()` registers an object of a class derived from BMediaNode with the media roster and assigns it a node_id. This function should be called once a BMediaNode-derived object is fully-constructed and before any attempt is made to connect the node to some other participant in the Media Server.

  `RegisterNode()` is called automatically for nodes instantiated from add-ons, but your application will have to call it for any nodes it creates itself.

  If you create your own subclass of BMediaNode, its constructor can call `RegisterNode()` itself just before returning (it must be the last thing the constructor does).

  `UnregisterNode()` unregisters a node from the Media Server. It's called automatically by the BMediaNode destructor, but it might be convenient to call it sometime before you delete your node instance, depending on your implementation and circumstances.

  These functions are generally only used if you're creating your own node class.

  RETURN CODES

  `B_OK`. No error sending the seek request.

  - `B_BAD_VALUE`. Invalid BMediaNode specified.

  ### ReleaseNode()

  status_t `ReleaseNode(`const media_node &node`) `

  Releases the specified node, which has previously been obtained by using the `InstantiateDormantNode()`, `GetNodeFor()`, or default node functions (such as `GetVideoNode()` or `GetAudioMixer()`).

  RETURN CODES

  `B_OK`. No error releasing the node.

  - BMessage errors. The node couldn't be released.

  ### RollNode()

  status_t `RollNode(`const media_node &node, bigtime_t startPerformanceTime, bigtime_t stopPerformanceTime, bigtime_t atMediaTime = -B_INFINITE_TIMEOUT`) `

  Atomically queues a start and stop for the given node. The node will start playing at the performance time indicated by startPerformanceTime, and will stop playing at the performance time indicated by stopPerformanceTime.

  If the atMediaTime argument is given, a seek to that media time is also queued.

  This function is especially useful for the offline rendering case (the `B_OFFLINE` run mode). It lets you render a certain time range without accidentally going too far; if you queue up a start and stop using `Start()` and `Stop()`, the node may have already rendered past your desired stop time before your `Stop()` call occurs. `RollNode()` avoids that problem.

  RETURN CODES

  `B_OK`. No error.

  - `B_MEDIA_BAD_NODE`. The node isn't valid.

  ### Roster() , CurrentRoster()

  static BMediaRoster *`Roster(`status_t *outError = NULL`) `
  static BMediaRoster *`CurrentRoster(`void`) `

  `Roster()` returns a pointer to the default BMediaRoster instance, or creates the BMediaRoster instance if it doesn't exist yet, then returns a pointer to it. If you don't want to create the roster if it doesn't already exist, use the `CurrentRoster()` function (it returns `NULL` if there's no roster).

  Since `CurrentRoster()` doesn't create a media roster, you obviously must use `Roster()` at least once in your application to create one.

  These static member functions should be called by explicit scope, and never by dereference; this is how you get the BMediaRoster through which all other media roster functions are called. For example:

         BMediaRoster *r = BMediaRoster::Roster();
         status_t err = r->GetFreeOutputsFor(some_node, some_array, 3, &n);

  On return, outError is set to `B_OK` if the default BMediaRoster was successfully returned, or a negative error code if something went wrong (for example, if the Media Server isn't running). If outError is `NULL`, no error code is returned.

  In any case, `Roster()` returns `NULL` if an error occurs.

  ### SeekNode()

  status_t `SeekNode(`const media_node &node, bigtime_t newMediaTime, bigtime_t atPerformanceTime = 0`) `

  Sends the specified node a request that it change its playing location to the media time newMediaTime once the performance time atPerformanceTime is reached.

  If the node isn't running, the seek request is processed immediately, and the atPerformanceTime argument is ignored.

  The error returned by this function only indicates whether or not the request was sent successfully; the node may later run into problems trying to perform the seek operation.

  | If the node is a time source, and you want to operate on the time source aspect of the node (to seek all slaved nodes), you should call `SeekTimeSource()` instead.

  RETURN CODES

  `B_OK`. No error sending the seek request.

  - Other errors, depending on the node.

  See also: `StartNode()`, `StopNode()`

  ### SeekTimeSource()

  status_t `SeekTimeSource(`const media_node &timeSource, bigtime_t newPerformanceTime, bigtime_t atRealTime`) `

  Sends the specified timeSource a request that it change the performance time it outputs to its slaved nodes to the time newPerformanceTime once the performance time atRealTime is reached.

  If the timeSource isn't running, the seek request is processed immediately, and the atRealTime argument is ignored.

  The error returned by this function only indicates whether or not the request was sent successfully; the node may later run into problems trying to perform the seek operation.

  RETURN CODES

  `B_OK`. No error sending the seek request.

  - Other errors, depending on the node.

  See also: `StartTimeSource()`, `StopTimeSource()`

  ### SetAudioInput() , SetVideoInput()

  status_t `SetAudioInput(`const media_node &defaultNode`) `
  status_t `SetAudioInput(`const dormant_node_info &defaultNodeInfo`) `
  status_t `SetVideoInput(`const media_node &defaultNode`) `
  status_t `SetVideoInput(`const dormant_node_info &defaultNodeInfo`) `

  These functions set the preferred nodes for audio and video input. If the specified node isn't capable of being the system default, an error will be returned (for example, nodes defined by an application can't be the system default—only nodes defined by Media Kit add-ons can be system defaults).

  | In general, you shouldn't call these functions unless you're writing software that reimplements the functionality of the BeOS Audio or Video preference panels.

  RETURN CODES

  `B_OK`. No error setting the default input node.

  - `B_NAME_NOT_FOUND`. The default node couldn't be changed.

  ### SetAudioOutput() , SetVideoOutput()

  status_t `SetAudioOutput(`const media_node &defaultNode`) `
  status_t `SetAudioOutput(`const dormant_node_info &defaultNodeInfo`) `
  status_t `SetAudioOutput(`const media_input &inputToOutput`) `
  status_t `SetVideoOutput(`const media_node &defaultNode`) `
  status_t `SetVideoOutput(`const dormant_node_info &defaultNodeInfo`) `

  These functions set the preferred nodes for audio and video output. If the specified node isn't capable of being the system default, an error will be returned (for example, nodes defined by an application can't be the system default—only nodes defined by Media Kit add-ons can be system defaults).

  | In general, you shouldn't call these functions unless you're writing software that reimplements the functionality of the BeOS Audio or Video preference panels.

  RETURN CODES

  `B_OK`. No error setting the default input node.

  - `B_NAME_NOT_FOUND`. The default node couldn't be changed.

  ### SetProducerRate()

  status_t `SetProducerRate(`const media_node &node, int32 numerator, int32 demominator`) `

  This function is called to tell the producer to resample the data rate by the specified factor. Specifying a value of 1 (ie, numerator/denominator = 1) indicates that the data should be output at the same playback rate that it comes into the node at. The format of the data should be unchanged.

  | Nodes are not required to support this mechanism for controlling their data rate, so this call may have no effect.

  RETURN CODES

  `B_OK`. No error.

  - Other errors. Returned by `BBufferProducer::SetPlayRate()`.

  See also: `BBufferProducer::SetPlayRate()`

  ### SetProducerRunModeDelay()

  status_t `SetProducerRunModeDelay(`const media_node &node, bigtime_t delay, BMediaNode::run_mode mode = B_RECORDING`) `

  Sets the run mode for the given producer node to mode. Also sets the specified delay to be added to each buffer sent by the producer. This function should only be called for `B_RECORDING` mode; it's provided to compensate when you connect a node that's in recording mode to a node that isn't.

  RETURN CODES

  `B_OK`. No error.

  - `B_MEDIA_BAD_NODE`. The node is invalid.

  - Port errors. An error occurred communicating with the Media Server.

  ### SetRealtimeFlags() see GetRealtimeFlags()

  ### SetRefFor() , GetRefFor()

  status_t `SetRefFor(`const media_node &fileInterface, entry_ref &file, bool createAndTruncate, bigtime_t *outDuration`) `
  status_t Get`RefFor(`const media_node &fileInterface, entry_ref *outFile, BMimeType *outMimeType = NULL`) `

  `SetRefFor()` tells the BFileInterface fileInterface to work on the file whose entry_ref is specified by file. If createAndTruncate is `true`, any previous file with that reference is deleted and the file will be prepared for new output. If createAndTruncate is `false`, outDuration will, on return, contain the duration of the performance data found in the file.

  `GetRefFor()` fills out the specified entry_ref, outFile, to reference the file with which the specified fileInterface node is working. If outMimeType isn't `NULL`, it'll contain a BMimeType object describing the file's type, unless an error occurs.

  | These functions will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error.

  - `B_MEDIA_BAD_NODE`. The specified node doesn't exist, or isn't a file interface.

  ### SetRunModeNode()

  status_t `SetRunModeNode(`const media_node &node, BMediaNode::run_mode newMode`) `

  Sends the specified node a request that it change its policy for handling situations where it falls behind during real-time processing.

  The error returned by this function only indicates whether or not the request was sent successfully.

  RETURN CODES

  `B_OK`. No error sending the set mode request.

  - `B_BAD_NODE`. The specified node is invalid.

  ### SetTimeSourceFor()

  status_t `SetTimeSourceFor(`media_node_id node, media_node_id timeSource`) `

  Tells the specified node to slave its timing to timeSource. Once this is done, the node will receive its notion of the passage of time from timeSource. As such, it will pause whenever timeSource is stopped, and so forth.

  | By default, nodes are slaved to the system time source, so you only need to call this function if you need to slave a node to a different time source.

  The node will take whatever precautions are necessary to remain faithful to the notion of time presented by timeSource without causing glitches in the presentation of its media. For example, if a sound card node has a DAC that drifts from timeSource, it might try to fix the problem by varying the sampling rate slightly, or by dropping or doubling buffers occasionally. This is why you should usually use the preferred time source—rather than the system time source—as your master time source. The preferred time source will usually be derived directly from the DAC being used to produce the media output.

  RETURN CODES

  `B_OK`. No error.

  - BMessage errors. Unable to set the time source.

  ### SetVideoInput() see SetAudioInput()

  ### SetVideoOutput() see SetAudioOutput()

  ### SniffRef() , SniffRefFor()

  status_t `SniffRef(`const entry_ref &file, uint64 requireNodeKinds, dormant_node_info *outNode, BMimeType outMimeType = NULL`) `
  status_t `SniffRefFor(`const media_node &fileInterface, const entry_ref &file, BMimeType outMimeType, float *outCapability`) `

  `SniffRef()` asks all BMediaAddOn instances that satisfy the requireNodeKinds restraint to identify the file. The requireNodeKinds argument should contain flags composited from the `node_kind` constants.

  The node that returns the greatest outCapability value will be chosen, and a reference to it put in outNode. The MIME type of the file will be put into outMimeType.

  In simpler terms: `SniffRef()` returns the node that can best handle the media data in the specified file.

  `SniffRefFor()`, on the other hand, asks the specified fileInterface node to examine the file. If the node recognizes the file, the MIME type of the file is stored in the buffer outMimeType, and the node's capability to handle the file is returned in outCapability.

  If the node doesn't recognize the file, an error is returned. If the node recognizes the file format but finds no recognizable data within the file, outCapability is set to 0.0 and no error is returned.

  In either case, the higher the outCapability value returned, the more appropriate the node is for handling the media data in the file.

  | These functions will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error sending the set mode request.

  - `B_MEDIA_BAD_NODE`. The specified node is invalid, or isn't a file interface.

  ### SniffRefFor() see SniffRef()

  ### StartControlPanel()

  status_t `StartControlPanel(`const media_node node, BMessenger *outMessenger = NULL`) `

  Tells the specified node to start its custom control panel, which is started outside your application. There's no way to tell when the user has closed the control panel, other than by indirectly detecting possible changes to the node, such as a renegotiation of the format of data being output by the node.

  If a BMessenger is provided as input to `StartControlPanel()`, the function returns in outMessenger a BMessneger that can be used to communicate with the control panel.

  | These functions will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error starting the control panel.

  - `B_MEDIA_BAD_NODE`. The specified node is invalid.

  ### StartNode() , StopNode()

  status_t `StartNode(`const media_node &node, bigtime_t atPerformanceTime`) `
  status_t `StopNode(`const media_node &node, bigtime_t atPerformanceTime, bool immediate = `false``) `

  `StartNode()` sends the specified node a request to start streaming data at the performance time specified by the atPerformanceTime argument, according to that node's time source.

  By default, nodes are in a stopped state upon creation, so you have to call `StartNode()` once you have a reference to it before anything will happen. Starting a node that's already running has no effect.

  `StopNode()` sends node a request to stop streaming data once the specified performance time atPerformanceTime is reached, according to that node's time source. Stopping a node that's already stopped has no effect. If immediate is `true`, the node is instructed to stop immediately and the atPerformanceTime argument is ignored; if immediate is `false`, the node is stopped at the specified performance time.

  In either case, the requested change will occur at the time specified by atPerformanceTime.

  | If the node is a time source, and you want to operate on the time source aspect of the node (to start or stop all slaved nodes), you should call `SeekTimeSource()` instead.

  The error returned by these functions only indicates whether or not the request was sent successfully; the node may later run into problems trying to start or stop its media and you won't know it based on the result of these functions.

  | `StopNode()` will deadlock if called from a node's control thread or while the control thread is blocked.

  RETURN CODES

  `B_OK`. No error sending the start or stop request.

  - Other errors, depending on the node.

  See also: `SeekNode()`

  ### StartTimeSource() , StopTimeSource()

  status_t `StartTimeSource(`const media_node &timeSource, bigtime_t atRealTime`) `
  status_t `StopTimeSource(`const media_node &timeSource, bigtime_t atRealTime, bool immediate = `false``) `

  `StartTimeSource()` sends the specified timeSource a request to start running at the real time specified by the atRealTime argument.

  `StopTimeSource()` sends node a request to stop the specified timeSource once the specified real time atRealTime is reached. Stopping a time source that's already stopped has no effect. If immediate is `true`, the time source is instructed to stop immediately and the atRealTime argument is ignored; if immediate is `false`, the time source is stopped at the specified real time.

  In either case, the requested change will occur at the time specified by atRealTime.

  The error returned by these functions only indicates whether or not the request was sent successfully; the node may later run into problems trying to start or stop and you won't know it based on the result of these functions.

  RETURN CODES

  `B_OK`. No error sending the start or stop request.

  - Other errors, depending on the node.

  See also: `SeekTimeSource()`

  ### StartWatching() , StopWatching()

  status_t `StartWatching(`const BMessenger &notifyHandler`) `
  status_t `StartWatching(`const BMessenger &notifyHandler, int32 notificationType`) `
  status_t `StartWatching(`const BMessenger &notifyHandler, const media_node &node, int32 notificationType`) `
  status_t `StopWatching(`const BMessenger &notifyHandler`) `
  status_t `StopWatching(`const BMessenger &notifyHandler, int32 notificationType`) `
  status_t `StopWatching(`const BMessenger &notifyHandler, const media_node &node, int32 notificationType`) `

  `StartWatching()` registers the specified BHandler or BLooper as a recipient of notification messages from the Media Server. `StopWatching()` cancels this registration so that no further notifications will be sent.

  If you're only interested in a particular notification type, you can specify that code in the notificationType argument. If you don't specify a notification type, `B_MEDIA_WILDCARD` is assumed; this matches all notification types. You can also specify that you want to watch a specific node; if you don't specify a node, you'll receive notifications for all nodes.

  Events are sent to registered BHandlers and BLoopers when certain events happen, such as nodes being created or deleted, or connections being made or broken.

  See "Notification Messages" for a list of the notifications you can receive, and the formats of the corresponding messages.

  Although the Media Server will automatically cancel notifications to BHandlers and BLoopers that go away without explicitly calling `StopWatching()`, this detection is expensive and may briefly interrupt the media system, so you should always call `StopWatching()` before allowing a BHandler or BLooper to go away.

  RETURN CODES

  `B_OK`. No error cloning the node.

  - `B_NAME_NOT_FOUND`. The requested node couldn't be cloned.

  ### StopNode() see StartNode()

  ### StopWatching() see StartWatching()

  ### SyncToNode()

  status_t `SyncNode(`const media_node &node, bigtime_t atPerformanceTime, bigtime_t timeout = B_INFINITE_TIMEOUT`) `

  If you want to detect the arrival of a specific performance time on a given node, you can do that by calling `SyncToNode()`. Specify the node you want to monitor in node, and the time you want to be notified of in atPerformanceTime. You can, optionally, specify a timeout; if the sync hasn't occurred in timeout microseconds, the request will time out.

  This function doesn't return until either the specified performance time arrives, or the sync operation times out.

  RETURN CODES

  `B_OK`. All's well.

  - `B_MEDIA_BAD_NODE`. The specified node is invalid.

  - `B_TIMED_OUT`. The request timed out.

  - Port errors. An error occurred communicating with the Media Server.

  ## Constants

  ### connect_flags

  Declared in: <be/media/MediaRoster.h>

  Constant | Description
  --- | ---
  `B_CONNECT_MUTED` | The connection should be muted on creation.

  The Media Kit Table of Contents | The Media Kit Index

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

  Copyright © 2000 Be, Inc. All rights reserved..