haiku-website/static/legacy-docs/bebook/BMediaRoster_Overview.html

432 lines
49 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>The Be Book - System Overview - The Media Kit</title><link rel="stylesheet" href="be_book.css" type="text/css" media="all" /><link rel="shortcut icon" type="image/vnd.microsoft.icon" href="./images/favicon.ico" /><!--[if IE]>
<link rel="stylesheet" type="text/css" href="be_book_ie.css" />
<![endif]--><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /><meta name="keywords" content="Access, BeOS, BeBook, API" /><link rel="start" href="index.html" title="The Be Book" /><link rel="up" href="TheMediaKit_Overview.html" title="The Media Kit" /><link rel="prev" href="BMediaNode_Overview.html" title="BMediaNode" /><link rel="next" href="BMediaTheme_Overview.html" title="BMediaTheme" /></head><body><div id="header"><div id="headerT"><div id="headerTL"><a accesskey="p" href="BMediaNode_Overview.html" title="BMediaNode"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a accesskey="u" href="TheMediaKit_Overview.html" title="The Media Kit"><img src="./images/navigation/up.png" alt="Up" /></a> <a accesskey="n" href="BMediaTheme_Overview.html" title="BMediaTheme"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="headerTR"><div id="navigpeople"><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div><div class="navigboxed" id="navigindex"><a accesskey="i" href="ClassIndex.html" title="Index">I</a></div><div class="navigboxed" id="naviglang" title="English">en</div></div><div id="headerTC">The Be Book - System Overview - The Media Kit</div></div><div id="headerB">Prev: <a href="BMediaNode_Overview.html">BMediaNode</a>  Up: <a href="TheMediaKit_Overview.html">The Media Kit</a>  Next: <a href="BMediaTheme_Overview.html">BMediaTheme</a></div><hr /></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMediaRoster_Overview"></a>BMediaRoster</h2></div></div></div><a id="id587191" class="indexterm"></a><p>The <a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a>
class comprises the functionality that applications that
use the Media Kit can access.</p><p>An application can only have a single instance of the
<a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a> class,
which is accessed by calling the static member function
<a class="link" href="BMediaRoster.html#BMediaRoster_Roster" title="Roster(), CurrentRoster()"><code class="methodname">BMediaRoster::Roster()</code></a>,
which creates the media roster, establishes the
connection to the Media Server, then returns a pointer to the roster.</p><p>The creation of the roster object is thread protected, so you can safely
call <a class="link" href="BMediaRoster.html#BMediaRoster_Roster" title="Roster(), CurrentRoster()"><code class="methodname">BMediaRoster::Roster()</code></a>
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:</p><pre class="programlisting example cpp"><span class="type">BMediaRoster *</span><code class="varname">gMediaRoster</code>;
<span class="type">int</span> <code class="function">main</code>(<span class="type">void</span>) {
<span class="type">status_t</span> <code class="varname">err</code>;
<code class="classname">BApplication</code> <code class="varname">app</code>("application/x-vnd.me-myself");
<code class="varname">gMediaRoster</code> = <code class="classname">BMediaRoster</code>::<code class="methodname">Roster</code>(&amp;<code class="varname">err</code>);
if (!<code class="varname">gMediaRoster</code> || (<code class="varname">err</code> != <code class="constant">B_OK</code>)) {
<span class="comment">/* the Media Server appears to be dead -- handle that here */</span>
}
<span class="comment">/* The Media Server connection is in place -- enjoy! */</span>
return 0;
}</pre><p>Because <a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a>
is derived from <a class="link" href="BLooper.html" title="BLooper"><code class="classname">BLooper</code></a>,
you should create your
<a class="link" href="BApplication.html" title="BApplication"><code class="classname">BApplication</code></a>
before calling
<a class="link" href="BMediaRoster.html#BMediaRoster_Roster" title="Roster(), CurrentRoster()"><code class="methodname">BMediaRoster::Roster()</code></a>,
although the
<a class="link" href="BApplication.html" title="BApplication"><code class="classname">BApplication</code></a>
doesn't have to be running yet.</p><p>You should never delete the
<a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a> returned to you by
<a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a>.
Also, you can't derive a class from
<a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a>.</p><p>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
<a class="link" href="BMediaRoster.html#BMediaRoster_StartWatching" title="StartWatching(), StopWatching()"><code class="methodname">StartWatching()</code></a>.</p><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id587420"></a>Playing Media from Disk</h3></div></div></div><p>To play a media file from disk, you would follow the following steps:</p><ul class="itemizedlist"><li><p>Create an
<a class="link" href="BEntry.html#entry_ref" title="entry_ref"><span class="type">entry_ref</span></a>
that refers to the file to be played.</p></li><li><p>Call
<a class="link" href="BMediaRoster.html#BMediaRoster_SniffRef" title="SniffRef(), SniffRefFor()"><code class="methodname">SniffRef()</code></a>
to obtain a
<a class="link" href="BMediaAddOn.html#dormant_node_info" title="dormant_node_info"><span class="type">dormant_node_info</span></a>
reference to the node that is best capable of playing back the media file.</p></li><li><p>Call
<a class="link" href="BMediaRoster.html#BMediaRoster_InstantiateDormantNode" title="InstantiateDormantNode()"><code class="methodname">InstantiateDormantNode()</code></a>
to instantiate the node; this returns a
<a class="link" href="TheMediaKit_DefinedTypes.html#media_node" title="media_node"><span class="type">media_node</span></a>
that you can use for other
<a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a> calls.</p></li><li><p>Use
<a class="link" href="BMediaRoster.html#BMediaRoster_SetRefFor" title="SetRefFor(), GetRefFor()"><code class="methodname">SetRefFor()</code></a>
to pass the <a class="link" href="BEntry.html#entry_ref" title="entry_ref"><span class="type">entry_ref</span></a>
of the file to be played to the node.</p></li><li><p>Call
<a class="link" href="BMediaRoster.html#BMediaRoster_GetFreeOutputsFor"><code class="methodname">GetFreeOutputsFor()</code></a>
to obtain a
<a class="link" href="TheMediaKit_DefinedTypes.html#media_output" title="media_output"><span class="type">media_output</span></a>
structure describing an available output on the producer node. This structure contains a
<a class="link" href="TheMediaKit_DefinedTypes.html#media_source" title="media_source"><span class="type">media_source</span></a>
you can pass to
<a class="link" href="BMediaRoster.html#BMediaRoster_Connect" title="Connect(), Disconnect()"><code class="methodname">Connect()</code></a>
as the source of the media data.</p></li><li><p>The
<a class="link" href="TheMediaKit_DefinedTypes.html#media_output" title="media_output"><span class="type">media_output</span></a>
structure returned by
<a class="link" href="BMediaRoster.html#BMediaRoster_GetFreeOutputsFor"><code class="methodname">GetFreeOutputsFor()</code></a>
contains a
<a class="link" href="TheMediaKit_DefinedTypes.html#media_format" title="media_format"><span class="type">media_format</span></a>
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.</p></li><li><p>You can use this value to determine what type of destination is
needed to output the data (for example, <code class="constant">B_MEDIA_RAW_AUDIO</code> would go to
an audio output, and <code class="constant">B_MEDIA_RAW_VIDEO</code> would go to a video output).</p></li><li><p>Call
<a class="link" href="BMediaRoster.html#BMediaRoster_StartWatching" title="StartWatching(), StopWatching()"><code class="methodname">GetAudioMixer()</code></a>
to get a <a class="link" href="TheMediaKit_DefinedTypes.html#media_node" title="media_node"><span class="type">media_node</span></a>
for the default audio mixer (if the media data is audio), or
<a class="link" href="BMediaRoster.html#BMediaRoster_GetVideoOutput"><code class="methodname">GetVideoOutput()</code></a>
to get a <a class="link" href="TheMediaKit_DefinedTypes.html#media_node" title="media_node"><span class="type">media_node</span></a>
for the default video output (if the media data is video).</p></li><li><p>Use
<a class="link" href="BMediaRoster.html#BMediaRoster_GetFreeInputsFor"><code class="methodname">GetFreeInputsFor()</code></a>
to obtain a <a class="link" href="TheMediaKit_DefinedTypes.html#media_input" title="media_input"><span class="type">media_input</span></a>
structure describing
an available input on the consumer node (the audio mixer or video
output); this structure contains a
<a class="link" href="TheMediaKit_DefinedTypes.html#media_destination" title="media_destination"><span class="type">media_destination</span></a>
you can pass to
<a class="link" href="BMediaRoster.html#BMediaRoster_Connect" title="Connect(), Disconnect()"><code class="methodname">Connect()</code></a>.</p></li><li><p>Call <a class="link" href="BMediaRoster.html#BMediaRoster_Connect" title="Connect(), Disconnect()"><code class="methodname">Connect()</code></a>
to connect the source to the destination.</p></li><li><p>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.</p></li><li><p>Finally, you can use
<a class="link" href="BMediaRoster.html#BMediaRoster_StartNode" title="StartNode(), StopNode()"><code class="methodname">StartNode()</code></a>
to start the producer, consumer, and
time source. The media file should begin playing back.</p></li></ul><p>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 (<code class="constant">B_MEDIA_ENCODED_VIDEO</code>) and that the audio is in a raw
audio format (<code class="constant">B_MEDIA_RAW_AUDIO</code>). 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:</p><pre class="programlisting example cpp"><span class="type">bigtime_t</span> <code class="varname">duration</code>;
<span class="type">media_node</span> <code class="varname">timeSourceNode</code>;
<span class="type">media_node</span> <code class="varname">mediaFileNode</code>;
<span class="type">media_output</span> <code class="varname">fileNodeOutput</code>;
<span class="type">int32</span> <code class="varname">fileOutputCount</code>;
<span class="type">media_output</span> <code class="varname">fileAudioOutput</code>;
<span class="type">int32</span> <code class="varname">fileAudioCount</code>;
<span class="type">media_node</span> <code class="varname">codecNode</code>;
<span class="type">media_output</span> <code class="varname">codecOutput</code>;
<span class="type">media_input</span> <code class="varname">codecInput</code>;
<span class="type">media_node</span> <code class="varname">videoNode</code>;
<span class="type">media_input</span> <code class="varname">videoInput</code>;
<span class="type">int32</span> <code class="varname">videoInputCount</code>;
<span class="type">media_node</span> <code class="varname">audioNode</code>;
<span class="type">media_input</span> <code class="varname">audioInput</code>;
<span class="type">int32</span> <code class="varname">audioInputCount</code>;
<span class="type">dormant_node_info</span> <code class="varname">nodeInfo</code>;
<span class="type">status_t</span> <code class="varname">err</code>;
<code class="varname">playingFlag</code> = <code class="constant">false</code>;
<code class="varname">roster</code> = <code class="classname">BMediaRoster</code>::<code class="methodname">Roster</code>();
<code class="varname">initStatus</code> = <code class="varname">roster</code>-&gt;<code class="methodname">SniffRef</code>(*<code class="varname">ref</code>, 0, &amp;<code class="varname">nodeInfo</code>);
if (<code class="varname">initStatus</code>) {
return;
}
<code class="varname">initStatus</code> = <code class="varname">roster</code>-&gt;<code class="methodname">InstantiateDormantNode</code>(<code class="varname">nodeInfo</code>, &amp;<code class="varname">mediaFileNode</code>);
if (<code class="varname">initStatus</code>) {
return;
}
<code class="varname">roster</code>-&gt;<code class="methodname">SetRefFor</code>(<code class="varname">mediaFileNode</code>, *<code class="varname">ref</code>, <code class="constant">false</code>, &amp;<code class="varname">duration</code>);
if ((<code class="varname">err</code> = <code class="methodname">Setup</code>()) != <code class="constant">B_OK</code>) {
<code class="function">printf</code>("Error %08lX in Setup()\n", <code class="varname">err</code>);
}
else {
<code class="methodname">Start</code>();
}</pre><p>This code begins by obtaining a pointer to the media roster. It then
calls <a class="link" href="BMediaRoster.html#BMediaRoster_SniffRef" title="SniffRef(), SniffRefFor()"><code class="methodname">SniffRef()</code></a>
to get a
<a class="link" href="BMediaAddOn.html#dormant_node_info" title="dormant_node_info"><span class="type">dormant_node_info</span></a>
structure describing the
best-suited node for reading the media data from the file specified by
<code class="varname">ref</code>.</p><p>Once a dormant_node_info structure has been filled out, the
<a class="link" href="BMediaRoster.html#BMediaRoster_InstantiateDormantNode" title="InstantiateDormantNode()"><code class="methodname">InstantiateDormantNode()</code></a>
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
<code class="varname">nodeInfo</code> structure
is passed into the function, and on return, the <code class="varname">mediaFileNode</code> has been
set up for the appropriate node.</p><p>Since the
<a class="link" href="TheMediaKit_DefinedTypes.html#media_node" title="media_node"><span class="type">media_node</span></a>
<code class="varname">mediaFileNode</code> is a file handling node, the
<a class="link" href="BMediaRoster.html#BMediaRoster_SetRefFor" title="SetRefFor(), GetRefFor()"><code class="methodname">SetRefFor()</code></a>
function is then called to tell the newly-instantiated file
handler node what file it should handle. The inputs here are:</p><ul class="itemizedlist"><li><p><code class="varname">mediaFileNode</code> is the node whose file reference is to be set.</p></li><li><p><code class="varname">ref</code> is the file that the node should reference.</p></li><li><p><code class="constant">false</code> indicates that the file must already exist. If this flag were
<code class="constant">true</code>, and the file indicated by <code class="varname">ref</code> were nonexistent, the node would
create a new file. Since we're playing a file, we don't want to do that.</p></li><li><p><code class="varname">duration</code> is a <span class="type">bigtime_t</span> variable
that will receive the duration of the media file, in microseconds.</p></li></ul><p>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
<code class="constant">B_OK</code> is returned.</p><p>The <code class="methodname">Setup()</code>
and <code class="methodname">Start()</code>
functions used in the example above are given below.
<code class="methodname">Setup()</code>
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
<code class="methodname">Setup()</code> next:</p><pre class="programlisting example cpp"><span class="type">status_t</span> <code class="classname">MediaPlayer</code>::<code class="methodname">Setup</code>(<span class="type">void</span>) {
<span class="type">status_t</span> <code class="varname">err</code>;
<span class="type">media_format</span> <code class="varname">tryFormat</code>;
<span class="type">dormant_node_info</span> <code class="varname">nodeInfo</code>;
<span class="type">int32</span> <code class="varname">nodeCount</code>;
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetAudioMixer</code>(&amp;<code class="varname">audioNode</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetVideoOutput</code>(&amp;<code class="varname">videoNode</code>);</pre><p>First, <a class="link" href="BMediaRoster.html#BMediaRoster_GetAudioMixer"><code class="methodname">GetAudioMixer()</code></a>
and <a class="link" href="BMediaRoster.html#BMediaRoster_GetVideoOutput"><code class="methodname">GetVideoOutput()</code></a>
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.</p><div class="admonition note"><div class="title">Note</div><div class="graphic"><img class="icon" alt="Note" width="32" src="./images/admonitions/Info_32.png" /><div class="text"><p>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.</p></div></div></div><pre class="programlisting example cpp"> <code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetTimeSource</code>(&amp;<code class="varname">timeSourceNode</code>);
<code class="varname">b_timesource</code> = <code class="varname">roster</code>-&gt;<code class="methodname">MakeTimeSourceFor</code>(<code class="varname">timeSourceNode</code>);</pre><p>This code obtains a
<a class="link" href="TheMediaKit_DefinedTypes.html#media_node" title="media_node"><span class="type">media_node</span></a>
for the preferred time source, and then creates a
<a class="link" href="BTimeSource.html" title="BTimeSource"><code class="classname">BTimeSource</code></a>
object that refers to the same node; we'll need to be able to make some
<a class="link" href="BTimeSource.html" title="BTimeSource"><code class="classname">BTimeSource</code></a>
calls to obtain some specific timing information later.</p><p>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.</p><p>You can think of a media node (represented by the
<a class="link" href="TheMediaKit_DefinedTypes.html#media_node" title="media_node"><span class="type">media_node</span></a> 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.</p><p>The Media Kit works the same way. We need to locate audio outputs from
the <code class="varname">mediaFileNode</code> and find corresponding audio
inputs on the <code class="varname">audioNode</code>.
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
<a class="link" href="BMediaRoster.html#BMediaRoster_GetFreeOutputsFor"><code class="methodname">GetFreeOutputsFor()</code></a>
to find free output ports on the <code class="varname">mediaFileNode</code>, and
<a class="link" href="BMediaRoster.html#BMediaRoster_GetFreeInputsFor"><code class="methodname">GetFreeInputsFor()</code></a>
to locate free input ports on the <code class="varname">audioNode</code>.</p><pre class="programlisting example cpp"> <code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetFreeOutputsFor</code>(<code class="varname">mediaFileNode</code>, &amp;<code class="varname">fileAudioOutput</code>, 1,
&amp;<code class="varname">fileAudioCount</code>, <code class="constant">B_MEDIA_RAW_AUDIO</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetFreeInputsFor</code>(<code class="varname">audioNode</code>, &amp;<code class="varname">audioInput</code>, <code class="varname">fileAudioCount</code>,
&amp;<code class="varname">audioInputCount</code>, <code class="constant">B_MEDIA_RAW_AUDIO</code>);</pre><p>We only want a single audio connection between the two nodes (a
single connection can carry stereo sound), and the connection is of type
<code class="constant">B_MEDIA_RAW_AUDIO</code>. On return,
<code class="varname">fileAudioOutput</code> and <code class="varname">audioInput</code>
describe the output from the <code class="varname">mediaFlieNode</code> and the input
into the <code class="varname">audioNode</code> that will eventually be connected to
play the movie's sound.</p><p>We likewise have to find a video output from the
<code class="varname">mediaFileNode</code> and an input into the
<code class="varname">videoNode</code>. In this case, though, we expect the video
output from the <code class="varname">mediaFileNode</code> to be encoded, and the
<code class="varname">videoNode</code> will want to receive raw, uncompressed video.
We'll work that out in a minute; for now, let's just find the two
ports:</p><pre class="programlisting example cpp"> <code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetFreeOutputsFor</code>(<code class="varname">mediaFileNode</code>, &amp;<code class="varname">fileNodeOutput</code>, 1,
&amp;<code class="varname">fileOutputCount</code>, <code class="constant">B_MEDIA_ENCODED_VIDEO</code>)
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetFreeInputsFor</code>(<code class="varname">videoNode</code>, &amp;<code class="varname">videoInput</code>, <code class="varname">fileOutputCount</code>,
&amp;<code class="varname">videoInputCount</code>, <code class="constant">B_MEDIA_RAW_VIDEO</code>);</pre><p>The problem we have now is that the <code class="varname">mediaFileNode</code> is outputting video
that's encoded somehow (like in Cinepak format, for instance). The
<code class="varname">videoNode</code>, 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 <acronym class="acronym">PAL</acronym> video into <acronym class="acronym">NTSC</acronym>, for example). This node will be
the codec that handles decompressing the video into raw form.</p><p>We need to locate a codec node that can handle the video format being
output by the <code class="varname">mediaFileNode</code>. This is accomplished like this:</p><pre class="programlisting example cpp"> <code class="varname">nodeCount</code> = 1;
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetDormantNodes</code>(&amp;<code class="varname">nodeInfo</code>, &amp;<code class="varname">nodeCount</code>,
&amp;<code class="varname">fileNodeOutput</code>.<code class="varname">format</code>);
if (!<code class="varname">nodeCount</code>) {
return -1;
}</pre><p>This call to
<a class="link" href="BMediaRoster.html#BMediaRoster_GetDormantNodes" title="GetDormantNodes()"><code class="methodname">GetDormantNodes()</code></a>
looks for a dormant node that can handle the media format specified by the
<code class="varname">mediaFileNode</code>'s output
<a class="link" href="TheMediaKit_DefinedTypes.html#media_format" title="media_format"><span class="type">media_format</span></a>
structure. Information about the node is returned in <code class="varname">nodeInfo</code>.
<code class="varname">nodeCount</code> indicates the number of matching nodes that
were found. If it's zero, an error is returned.</p><p>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.</p><p>Then we use
<a class="link" href="BMediaRoster.html#BMediaRoster_InstantiateDormantNode" title="InstantiateDormantNode()"><code class="methodname">InstantiateDormantNode()</code></a>
to instantiate the codec node, and
locate inputs into the node (that accept encoded video) and outputs from
the node (that output raw video):</p><pre class="programlisting example cpp"> <code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">InstantiateDormantNode</code>(<code class="varname">nodeInfo</code>, &amp;<code class="varname">codecNode</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetFreeInputsFor</code>(<code class="varname">codecNode</code>, &amp;<code class="varname">codecInput</code>, 1, &amp;<code class="varname">nodeCount</code>,
<code class="constant">B_MEDIA_ENCODED_VIDEO</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetFreeOutputsFor</code>(<code class="varname">codecNode</code>, &amp;<code class="varname">codecOutput</code>, 1,
&amp;<code class="varname">nodeCount</code>, <code class="constant">B_MEDIA_RAW_VIDEO</code>);</pre><p>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.</p><p>We begin by connecting the file node's video output to the codec's input:</p><pre class="programlisting example cpp"> <code class="varname">tryFormat</code> = <code class="varname">fileNodeOutput</code>.<code class="varname">format</code>;
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">Connect</code>(<code class="varname">fileNodeOutput</code>.<code class="varname">source</code>, <code class="varname">codecInput</code>.<code class="varname">destination</code>,
&amp;<code class="varname">tryFormat</code>, &amp;<code class="varname">fileNodeOutput</code>, &amp;<code class="varname">codecInput</code>);</pre><p><code class="varname">tryFormat</code> indicates the format of the encoded video that will be output
by the <code class="varname">mediaFileNode</code>.
<a class="link" href="BMediaRoster.html#BMediaRoster_Connect" title="Connect(), Disconnect()"><code class="methodname">Connect()</code></a>,
in essense, runs a wire between the
output from the media node's video output (<code class="varname">fileNodeOutput</code>) to the codec
node's input.</p><p>You may wonder what's up with the <code class="varname">fileNodeOutput</code>.<code class="varname">source</code> and
<code class="varname">codecInput</code>.<code class="varname">destination</code> structures. These
<a class="link" href="TheMediaKit_DefinedTypes.html#media_source" title="media_source"><span class="type">media_source</span></a> and
<a class="link" href="TheMediaKit_DefinedTypes.html#media_destination" title="media_destination"><span class="type">media_destination</span></a>
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
<a class="link" href="BMediaRoster.html#BMediaRoster_Connect" title="Connect(), Disconnect()"><code class="methodname">Connect()</code></a>
call (and time is money, especially in the media business).</p><p>Next it's necessary to connect the codec to the video output node. This
begins by setting up <code class="varname">tryFormat</code> to describe raw video of the same width
and height as the encoded video being fed into the codec, then calling
<a class="link" href="BMediaRoster.html#BMediaRoster_Connect" title="Connect(), Disconnect()"><code class="methodname">Connect()</code></a>
to establish the connection:</p><pre class="programlisting example cpp"> <code class="varname">tryFormat</code>.<code class="varname">type</code> = <code class="constant">B_MEDIA_RAW_VIDEO</code>;
<code class="varname">tryFormat</code>.<code class="varname">u</code>.<code class="varname">raw_video</code> = <span class="type">media_raw_video_format</span>::<code class="varname">wildcard</code>;
<code class="varname">tryFormat</code>.<code class="varname">u</code>.<code class="varname">raw_video</code>.<code class="varname">display</code>.<code class="varname">line_width</code> =
<code class="varname">codecInput</code>.<code class="varname">format</code>.<code class="varname">u</code>.<code class="varname">encoded_video</code>.<code class="varname">output</code>.<code class="varname">display</code>.<code class="varname">line_width</code>;
<code class="varname">tryFormat</code>.<code class="varname">u</code>.<code class="varname">raw_video</code>.<code class="varname">display</code>.<code class="varname">line_count</code> =
<code class="varname">codecInput</code>.<code class="varname">format</code>.<code class="varname">u</code>.<code class="varname">encoded_video</code>.<code class="varname">output</code>.<code class="varname">display</code>.<code class="varname">line_count</code>;
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">Connect</code>(<code class="varname">codecOutput</code>.<code class="varname">source</code>, <code class="varname">videoInput</code>.<code class="varname">destination</code>,
&amp;<code class="varname">tryFormat</code>, &amp;<code class="varname">codecOutput</code>, &amp;<code class="varname">videoInput</code>);</pre><p>Now we connect the audio from the media file to the audio mixer node. We
just copy the
<a class="link" href="TheMediaKit_DefinedTypes.html#media_format" title="media_format"><span class="type">media_format</span></a>
from the file's audio output, since both ends of the connection should exactly match.</p><pre class="programlisting example cpp"> <code class="varname">tryFormat</code> = <code class="varname">fileAudioOutput</code>.<code class="varname">format</code>;
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">Connect</code>(<code class="varname">fileAudioOutput</code>.<code class="varname">source</code>, <code class="varname">audioInput</code>.<code class="varname">destination</code>,
&amp;<code class="varname">tryFormat</code>, &amp;<code class="varname">fileAudioOutput</code>, &amp;<code class="varname">audioInput</code>);</pre><p>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):</p><pre class="programlisting example cpp"> <code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">SetTimeSourceFor</code>(<code class="varname">mediaFileNode</code>.<code class="varname">node</code>,
<code class="varname">timeSourceNode</code>.<code class="varname">node</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">SetTimeSourceFor</code>(<code class="varname">videoNode</code>.<code class="varname">node</code>, <code class="varname">timeSourceNode</code>.<code class="varname">node</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">SetTimeSourceFor</code>(<code class="varname">codecOutput</code>.<code class="varname">node</code>.<code class="varname">node</code>,
<code class="varname">timeSourceNode</code>.<code class="varname">node</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">SetTimeSourceFor</code>(<code class="varname">audioNode</code>.<code class="varname">node</code>, <code class="varname">timeSourceNode</code>.<code class="varname">node</code>);
return <code class="constant">B_OK</code>;
}</pre><p>Finally, we return <code class="constant">B_OK</code> to the caller. Note that this code should be
enhanced to check the results of each
<a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a>
call, and to return the result code if it's not <code class="constant">B_OK</code>.
This has been left out of this example for brevity.</p><p>The <code class="methodname">Start()</code>
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 (<code class="varname">audioNode</code>), the
media file's node (<code class="varname">mediaFileNode</code>), the codec, and the video node.</p><pre class="programlisting example cpp"><span class="type">status_t</span> <code class="classname">MediaPlayer</code>::<code class="methodname">Start</code>(<span class="type">void</span>) {
<span class="type">status_t</span> <code class="varname">err</code>;
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">GetStartLatencyFor</code>(<code class="varname">timeSourceNode</code>, &amp;<code class="varname">startTime</code>);
<code class="varname">startTime</code> += <code class="varname">b_timesource</code>-&gt;<code class="methodname">PerformanceTimeFor</code>(<code class="classname">BTimeSource</code>::<code class="methodname">RealTime</code>()
+ 1000000 / 50);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">StartNode</code>(<code class="varname">mediaFileNode</code>, <code class="varname">startTime</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">StartNode</code>(<code class="varname">codecNode</code>, <code class="varname">startTime</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">StartNode</code>(<code class="varname">videoNode</code>, <code class="varname">startTime</code>);
return <code class="constant">B_OK</code>;
}</pre><p>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.</p><p>The
<a class="link" href="BTimeSource.html#BTimeSource_RealTime" title="RealTime()"><code class="methodname">BTimeSource::RealTime()</code></a>
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 <code class="varname">startTime</code>. These are added to the
value returned by
<a class="link" href="BMediaRoster.html#BMediaRoster_GetStartLatencyFor" title="GetStartLatencyFor()"><code class="methodname">GetStartLatencyFor()</code></a>,
which returns the time required
to actually start the time source and all the nodes slaved to it.</p><p>Then we simply call
<a class="link" href="BMediaRoster.html#BMediaRoster_StartNode" title="StartNode(), StopNode()"><code class="methodname">BMediaRoster::StartNode()</code></a>
for each node, specifying
<code class="varname">startTime</code> as the performance time at which playback should begin.</p><p>Again, error handling should be added to actually return the error code
from these functions.</p><p>Stopping playback of the movie is even simpler:</p><pre class="programlisting example cpp"> <code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">StopNode</code>(<code class="varname">mediaFileNode</code>, 0, <code class="constant">true</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">StopNode</code>(<code class="varname">codecNode</code>, 0, <code class="constant">true</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">StopNode</code>(<code class="varname">videoNode</code>, 0, <code class="constant">true</code>);</pre><p>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 <code class="constant">false</code> for the last
argument; when this value is <code class="constant">true</code>,
<a class="link" href="BMediaRoster.html#BMediaRoster_StopNode"><code class="methodname">StopNode()</code></a>
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.</p><p>Note that we don't stop the audio mixer node. You should never stop the
mixer node, because other applications are probably using it.</p><p>Once you're done playing the movie, and have stopped playback, you should
disconnect the nodes from each other:</p><pre class="programlisting example cpp"> <code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">Disconnect</code>(<code class="varname">mediaFileNode</code>.<code class="varname">node</code>, <code class="varname">fileNodeOutput</code>.<code class="varname">source</code>,
<code class="varname">codecNode</code>.<code class="varname">node</code>, <code class="varname">codecInput</code>.<code class="varname">destination</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">Disconnect</code>(<code class="varname">codecNode</code>.<code class="varname">node</code>, <code class="varname">codecOutput</code>.<code class="varname">source</code>,
<code class="varname">videoNode</code>.<code class="varname">node</code>, <code class="varname">videoInput</code>.<code class="varname">destination</code>);
<code class="varname">err</code> = <code class="varname">roster</code>-&gt;<code class="methodname">Disconnect</code>(<code class="varname">mediaFileNode</code>.<code class="varname">node</code>, <code class="varname">fileAudioOutput</code>.<code class="varname">source</code>,
<code class="varname">audioNode</code>.<code class="varname">node</code>, <code class="varname">audioInput</code>.<code class="varname">destination</code>);</pre><p>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.</p><p>Once the connections are severed, you should release any dormant nodes
you instantiated. This includes not only nodes instantiated using
<a class="link" href="BMediaRoster.html#BMediaRoster_InstantiateDormantNode" title="InstantiateDormantNode()"><code class="methodname">InstantiateDormantNode()</code></a>,
but also default nodes (those obtained using functions like
<a class="link" href="BMediaRoster.html#BMediaRoster_GetAudioInput" title="GetAudioInput(), GetVideoInput()"><code class="methodname">GetAudioInput()</code></a> and
<a class="link" href="BMediaRoster.html#BMediaRoster_GetVideoOutput"><code class="methodname">GetVideoOutput)</code></a>,
for example):</p><pre class="programlisting example cpp"> <code class="varname">roster</code>-&gt;<code class="methodname">ReleaseNode</code>(<code class="varname">codecNode</code>);
<code class="varname">roster</code>-&gt;<code class="methodname">ReleaseNode</code>(<code class="varname">mediaFileNode</code>);
<code class="varname">roster</code>-&gt;<code class="methodname">ReleaseNode</code>(<code class="varname">videoNode</code>);
<code class="varname">roster</code>-&gt;<code class="methodname">ReleaseNode</code>(<code class="varname">audioNode</code>);</pre><p>If you want to play audio, you may find it much easier to use the
<span class="deprecated"><code class="classname">BSound</code></span> and
<a class="link" href="BSoundPlayer.html" title="BSoundPlayer"><code class="classname">BSoundPlayer</code></a>
classes to do so. As of R4.5, there are no
Be-provided nodes for producing audio from a disk file.</p><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id589903"></a>Detecting When Playback Is Complete</h4></div></div></div><p>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:</p><pre class="programlisting example cpp"><span class="type">bigtime_t</span> <code class="varname">currentTime</code>;
<span class="type">bool</span> <code class="varname">isPlaying</code> = <code class="constant">true</code>;
<code class="varname">currentTime</code> = <code class="varname">b_timesource</code>-&gt;<code class="methodname">PerformanceTimeFor</code>(<code class="classname">BTimeSource</code>::<code class="methodname">RealTime</code>());
if (<code class="varname">currentTime</code> &gt;= <code class="varname">startTime</code>+<code class="varname">duration</code>) {
<code class="varname">isPlaying</code> = <code class="constant">false</code>;
}</pre><p>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).</p><p>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 <code class="varname">isPlaying</code> to <code class="constant">false</code>;
otherwise, this value remains <code class="constant">true</code>.</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id590007"></a>Using BMediaRoster Functions from Nodes</h4></div></div></div><p>You can issue
<a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a>
function calls from within your own node, however, as a general rule, you
shouldn't call <a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a> functions
from within your control thread, or while the control thread is blocked.
Many <a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a>
functions use synchronous turnarounds, and will
deadlock in this situation. You should assume, for safety's sake, that
all <a class="link" href="BMediaRoster.html" title="BMediaRoster"><code class="classname">BMediaRoster</code></a>
functions will deadlock if used in these cases.</p><p>For example, if you have an application that's playing video into a
window, and you call
<a class="link" href="BMediaRoster.html#BMediaRoster_StopNode"><code class="classname">StopNode()</code></a>
from the window's
<a class="link" href="BWindow.html#BWindow_MessageReceived" title="MessageReceived()"><code class="classname">MessageReceived()</code></a>
function, a deadlock would occur if the video player node blocks waiting
on the window to be unlocked, and the
<a class="link" href="BMediaRoster.html#BMediaRoster_StopNode"><code class="classname">StopNode()</code></a>
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.</p><p>Instead, you should consider creating a seperate
<a class="link" href="BLooper.html" title="BLooper"><code class="classname">BLooper</code></a>
that manages
your nodes. Future versions of the Media Kit will provide convenience
classes to do some of this for you.</p></div></div></div><div id="footer"><hr /><div id="footerT">Prev: <a href="BMediaNode_Overview.html">BMediaNode</a>  Up: <a href="TheMediaKit_Overview.html">The Media Kit</a>  Next: <a href="BMediaTheme_Overview.html">BMediaTheme</a> </div><div id="footerB"><div id="footerBL"><a href="BMediaNode_Overview.html" title="BMediaNode"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a href="TheMediaKit_Overview.html" title="The Media Kit"><img src="./images/navigation/up.png" alt="Up" /></a> <a href="BMediaTheme_Overview.html" title="BMediaTheme"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="footerBR"><div><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div></div><div id="footerBC"><a href="http://www.access-company.com/home.html" title="ACCESS Co."><img alt="Access Company" src="./images/access_logo.png" /></a></div></div></div><div id="licenseFooter"><div id="licenseFooterBL"><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" title="Creative Commons License"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by-nc-nd/3.0/88x31.png" /></a></div><div id="licenseFooterBR"><a href="./LegalNotice.html">Legal Notice</a></div><div id="licenseFooterBC"><span id="licenseText">This work is licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative
Commons Attribution-Non commercial-No Derivative Works 3.0 License</a>.</span></div></div></body></html>