Google Custom Search

BMidiLocalProducer Class Reference
[MIDI 2 Kit(libmidi2.so)]

A producer endpoint that is created by your own application. More...

Inheritance diagram for BMidiLocalProducer:

BMidiProducer BMidiEndpoint List of all members.

Public Member Functions

status_t Acquire ()
 Increments the endpoint's reference count.
 BMidiLocalProducer (const char *name=NULL)
 Creates a new local producer endpoint.
status_t Connect (BMidiConsumer *cons)
 Connects a consumer to this producer.
virtual void Connected (BMidiConsumer *cons)
 Invoked when a new consumer is connected to this producer.
BListConnections () const
 Returns a list with all connected consumers.
status_t Disconnect (BMidiConsumer *cons)
 Disconnects a consumer from this producer.
virtual void Disconnected (BMidiConsumer *cons)
 Invoked when a consumer is disconnected from this producer.
status_t GetProperties (BMessage *properties) const
 Reads the properties of the endpoint.
int32 ID () const
 Returns the ID of the endpoint.
bool IsConnected (BMidiConsumer *cons) const
 Determines whether a consumer is connected to this producer.
bool IsConsumer () const
 Determines whether this endpoint is a BMidiConsumer.
bool IsLocal () const
 Determines whether this endpoint represents a local object.
bool IsPersistent () const
 Not used.
bool IsProducer () const
 Determines whether this endpoint is a BMidiProducer.
bool IsRemote () const
 Determines whether this endpoint is a proxy for a remote object.
bool IsValid () const
 Determines whether the endpoint still exists.
const char * Name () const
 Returns the name of the endpoint.
status_t Register ()
 Publishes the endpoint on the roster.
status_t Release ()
 Decrements the endpoint's reference count.
void SetName (const char *name)
 Changes the name of the endpoint.
status_t SetProperties (const BMessage *properties)
 Changes the properties of the endpoint.
void SprayChannelPressure (uchar channel, uchar pressure, bigtime_t time=0) const
 Sends a Channel Pressure event to all connected consumers.
void SprayControlChange (uchar channel, uchar controlNumber, uchar controlValue, bigtime_t time=0) const
 Sends a Controller Change event to all connected consumers.
void SprayData (void *data, size_t length, bool atomic=false, bigtime_t time=0) const
 Sends raw MIDI data downstream to all connected consumers.
void SprayKeyPressure (uchar channel, uchar note, uchar pressure, bigtime_t time=0) const
 Sends a Polyphonic Pressure (Aftertouch) event to all connected consumers.
void SprayNoteOff (uchar channel, uchar note, uchar velocity, bigtime_t time=0) const
 Sends a Note Off event to all connected consumers.
void SprayNoteOn (uchar channel, uchar note, uchar velocity, bigtime_t time=0) const
 Sends a Note On event to all connected consumers.
void SprayPitchBend (uchar channel, uchar lsb, uchar msb, bigtime_t time=0) const
 Sends a Pitch Bend event to all connected consumers.
void SprayProgramChange (uchar channel, uchar programNumber, bigtime_t time=0) const
 Sends a Program Change event to all connected consumers.
void SpraySystemCommon (uchar status, uchar data1, uchar data2, bigtime_t time=0) const
 Sends a System Common event to the connected consumers.
void SpraySystemExclusive (void *data, size_t length, bigtime_t time=0) const
 Sends a System Exclusive event to all connected consumers.
void SpraySystemRealTime (uchar status, bigtime_t time=0) const
 Sends a Real Time event to the connected consumers.
void SprayTempoChange (int32 beatsPerMinute, bigtime_t time=0) const
 Sends a Tempo Change event to the connected consumers.
status_t Unregister ()
 Hides the endpoint from the roster.

Detailed Description

A producer endpoint that is created by your own application.

You create a BMidiLocalProducer if you want your application to send MIDI events. You use the various spray functions to send events to all connected consumers. If no consumers are connected to the producer, any calls to the spray functions are ignored.

Most spray functions accept a channel argument. Even though MIDI channels are really numbered 1 through 16, the spray functions work with channels 0 through 15. You can also specify the performance time for the event using the time argument. Specify 0 (or any time in the past) to perform the event "now", i.e. as soon as possible. You can also schedule events to be performed in the future, by passing a time such as system_time() + 5000000, which means 5 seconds from now.

Unlike BMidiLocalConsumer, which should be subclassed almost always, you hardly ever need to derive a class from BMidiLocalProducer. The only reason for subclassing is when you need to know when the producer gets connected or disconnected.

Also unlike consumers, local producers have no thread of control directly associated with them. If you want to send out the MIDI events from a different thread, you will have to create one yourself.


Constructor & Destructor Documentation

BMidiLocalProducer::BMidiLocalProducer ( const char *  name = NULL  ) 

Creates a new local producer endpoint.

The new endpoint is not visible to other applications until you Register() it.

You can tell the constructor what the name of the new producer will be. If you pass NULL (or use the default argument), then the producer's name will be an empty string. It won't be NULL, since endpoint names cannot be NULL.

There is no guarantee that the endpoint will be successfully created. For example, the Midi Server may not be running. Therefore, you should always call IsValid() after creating a new endpoint to make sure that everything went okay. If not, Release() the object to reclaim memory and abort gracefully.

BMidiLocalProducer* prod = new BMidiLocalProducer(...);
if (!prod->IsValid())
{
    prod->Release();
    ...exit gracefully...
}


Member Function Documentation

status_t BMidiEndpoint::Acquire (  )  [inherited]

Increments the endpoint's reference count.

Each BMidiEndpoint has a reference count associated with it, so that BMidiRoster can do proper bookkeeping. Acquire() increments this reference count, and Release() decrements it. Once the count reaches zero, the endpoint is deleted.

When you are done with the endpoint, whether local or remote, you should always Release() it!

Upon construction, local endpoints start with a reference count of 1. Any objects you obtain from BMidiRoster using the NextXXX() or FindXXX() functions have their reference counts incremented in the process. If you forget to call Release(), the objects won't be properly cleaned up and you'll make a fool out of yourself.

After you Release() an object, you are advised not to use it any further. If you do, your app will probably crash. That also happens if you Release() an object too many times.

Typically, you don't need to call Acquire(), unless you have two disparate parts of your application working with the same endpoint, and you don't want to have to keep track of who needs to Release() the endpoint. Now you simply have both of them release it.

Returns:
Always returns B_OK
See also:
Release()

status_t BMidiProducer::Connect ( BMidiConsumer cons  )  [inherited]

Connects a consumer to this producer.

Establishes a connection between this producer and the specified consumer endpoint. From now on, any events that this producer sprays will be sent to that consumer. You may connect multiple consumers to a producer.

Returns:
B_OK on success, or an error code when the connection could not be established. If the consumer is a proxy for a remote object and that object no longer exists, Connect() returns B_ERROR. It also returns B_ERROR if you try to connect the same producer and consumer more than once.
See also:
Disconnect()

void BMidiLocalProducer::Connected ( BMidiConsumer cons  )  [virtual]

Invoked when a new consumer is connected to this producer.

Although typical notifications (i.e. from BMidiRoster's "watching" facility) are only sent if it is some other app that is performing the operation, Connected() is also called if you are making the connection yourself.

If you override this hook, you don't have to call the default implementation, because that does nothing.

Parameters:
cons The newly connected consumer. The reference count of the consumer object is not increased, so you should not Release() it. However, if you want to keep track of the consumer beyond this function, you should first Acquire() it, and Release() it when you are done.
See also:
Disconnected()

BList * BMidiProducer::Connections (  )  const [inherited]

Returns a list with all connected consumers.

Returns a BList with pointers to BMidiEndpoint objects for all consumers that are connected to this producer. You can examine the contents of the list as follows:

BList* list = prod->Connections();
for (int32 t = 0; t < list->CountItems(); ++t)
{
    BMidiEndpoint* endp = (BMidiEndpoint*) list->ItemAt(t);
    ...do stuff...
    endp->Release();  // yes, here too!
}
delete list;

Every time you call this function, a new BList is allocated. The caller (that is you) is responsible for freeing this list. The BMidiEndpoint objects in the list have their reference counts bumped, so you need to Release() them before you delete the list or they will go all leaky on you.

status_t BMidiProducer::Disconnect ( BMidiConsumer cons  )  [inherited]

Disconnects a consumer from this producer.

Terminates the connection between this producer and the specified consumer endpoint. From now on, any events that this producer sprays no longer go to that consumer.

Returns:
B_OK on success, or an error code if there was no connection to break
See also:
Connect()

void BMidiLocalProducer::Disconnected ( BMidiConsumer cons  )  [virtual]

Invoked when a consumer is disconnected from this producer.

See also:
Connected()

status_t BMidiEndpoint::GetProperties ( BMessage props  )  const [inherited]

Reads the properties of the endpoint.

Usage example:

BMessage props;
if (endpoint->GetProperties(&props) == B_OK) 
{
    ...examine the contents of the message...
}

Note that GetProperties() overwrites the contents of your BMessage.

See also:
SetProperties()

int32 BMidiEndpoint::ID (  )  const [inherited]

Returns the ID of the endpoint.

An ID uniquely identifies an endpoint in the system. The ID is a signed 32-bit number that is assigned by the Midi Server when the endpoint is created. (So even if a local endpoint is not published, it still has a unique ID.) Valid IDs range from 1 to 0x7FFFFFFF, the largest value an int32 can have. 0 and negative values are not valid IDs.

bool BMidiProducer::IsConnected ( BMidiConsumer cons  )  const [inherited]

Determines whether a consumer is connected to this producer.

See also:
Connect()

Disconnect()

bool BMidiEndpoint::IsConsumer (  )  const [inherited]

Determines whether this endpoint is a BMidiConsumer.

If it is, you can use a dynamic_cast to convert this object into a consumer:

if (endp->IsConsumer())
{
    BMidiConsumer* cons = dynamic_cast<BMidiConsumer*>(endp);
    ....
}

bool BMidiEndpoint::IsLocal (  )  const [inherited]

Determines whether this endpoint represents a local object.

An endpoint is "local" when it is created by this application; in other words, a BMidiLocalConsumer or BMidiLocalProducer.

bool BMidiEndpoint::IsPersistent (  )  const [inherited]

Not used.

The purpose of this function is unclear, and as a result it doesn't do anything in the OpenBeOS implementation of the Midi Kit.

Returns:
Always returns false.

bool BMidiEndpoint::IsProducer (  )  const [inherited]

Determines whether this endpoint is a BMidiProducer.

If it is, you can use a dynamic_cast to convert this object into a producer:

if (endp->IsProducer())
{
    BMidiProducer* prod = dynamic_cast<BMidiProducer*>(endp);
    ....
}

bool BMidiEndpoint::IsRemote (  )  const [inherited]

Determines whether this endpoint is a proxy for a remote object.

An endpoint is "remote" when it is created by another application. Obviously, the remote object is Register()'ed as well, otherwise you would not be able to see it.

bool BMidiEndpoint::IsValid (  )  const [inherited]

Determines whether the endpoint still exists.

Suppose you obtained a proxy object for a remote endpoint by querying the BMidiRoster. What if the application that published this endpoint quits, or less drastically, Unregister()'s that endpoint? Even though you still have a BMidiEndpoint proxy object, the real endpoint no longer exists. You can use IsValid() to check for this.

Don't worry, operations on invalid objects, such as GetProperties(), will return an error code (typically B_ERROR), but not cause a crash. Local objects are always are considered to be valid, even if you did not Register() them. (The only time a local endpoint is not valid is when there was a problem constructing it.)

If the application that created the remote endpoint crashes, then there is no guarantee that the Midi Server immediately recognizes this. In that case, IsValid() may still return true. Eventually, the stale endpoint will be removed from the roster, though. From then on, IsValid() correctly returns false.

const char * BMidiEndpoint::Name (  )  const [inherited]

Returns the name of the endpoint.

The function never returns NULL. If you created a local endpoint by passing a NULL name into its constructor (or passing no name, which is the same thing), then Name() will return an empty string, not NULL.

See also:
SetName()

status_t BMidiEndpoint::Register (  )  [inherited]

Publishes the endpoint on the roster.

MIDI objects created by an application are invisible to other applications until they are published. To publish an object use the Register() method. The corresponding Unregister() method will cause an object to once again become invisible to remote applications.

BMidiRoster also has Register() and Unregister() methods. You may also use those methods to publish or hide your endpoints; both do the same thing.

Although it is considered bad style, calling Register() on local endpoints that are already registered won't mess things up. The Midi Server will simply ignore your request. Likewise for Unregister()'ing more than once. Attempts to Register() or Unregister() remote endpoints will fail, of course.

If you are watching , you will not receive notifications for any local endpoints you register or unregister. Of course, other applications will be notified about your endpoints.

Existing connections will not be broken when an object is unregistered, but future remote connections will be denied. When objects are destroyed, they automatically become unregistered.

Returns:
B_OK on success, or a negative error code (typically B_ERROR) if something went wrong.
See also:
Unregister()

status_t BMidiEndpoint::Release (  )  [inherited]

Decrements the endpoint's reference count.

Returns:
Always returns B_OK
See also:
Acquire()

void BMidiEndpoint::SetName ( const char *  name  )  [inherited]

Changes the name of the endpoint.

Names don't have to be unique, but it is recommended that you give any endpoints you publish meaningful and unique names, so users can easily recognize what each endpoint does. There is no limit to the size of endpoint names.

Even though you can call this function on both remote and local objects, you are only allowed to change the names of local endpoints; SetName() calls on remote endpoints are ignored.

Parameters:
name The new name. If you pass NULL, the name simply won't be changed.
See also:
Name()

status_t BMidiEndpoint::SetProperties ( const BMessage props  )  [inherited]

Changes the properties of the endpoint.

Endpoints can have properties, which is any kind of information that might be useful to associate with a MIDI object. The properties are stored in a BMessage.

Usage example:

BMessage props;
if (endpoint->GetProperties(&props) == B_OK)
{
    ...add data to the message...
    endpoint->SetProperties(&props);
} 

You are only allowed to call SetProperties() on a local object.

Properties should follow a protocol, so different applications will know how to read each other's properties. The current protocol is very limited -- it only allows you to associate icons with your endpoints. Be planned to publish a more complete protocol that included additional information, such as vendor/model names, copyright/version info, category, etc., but they never got around to it.

propertyLarge (32x32) icon
field name"be:large_icon"
field type'ICON'

propertySmall (16x16) icon
field name"be:mini_icon"
field type'MICN'

The MidiUtil package (downloadable from the OpenBeOS website) contains a number of convenient functions to associate icons with endpoints, so you don't have to write that code all over again.

See also:
GetProperties()

void BMidiLocalProducer::SprayChannelPressure ( uchar  channel,
uchar  pressure,
bigtime_t  time = 0 
) const

Sends a Channel Pressure event to all connected consumers.

See also:
BMidiLocalConsumer::ChannelPressure()

void BMidiLocalProducer::SprayControlChange ( uchar  channel,
uchar  controlNumber,
uchar  controlValue,
bigtime_t  time = 0 
) const

Sends a Controller Change event to all connected consumers.

See also:
Midi2Defs.h

BMidiLocalConsumer::ControlChange()

void BMidiLocalProducer::SprayData ( void *  data,
size_t  length,
bool  atomic = false,
bigtime_t  time = 0 
) const

Sends raw MIDI data downstream to all connected consumers.

Typically you won't have to call SprayData(); the other spray functions will do just fine. If you do call it, remember that you retain ownership of the data and that you are responsible for freeing it at some point. (Even though data is not declared const, the function does not change it.)

With atomic set to false, you can send a MIDI message in segments (perhaps for a large sysex dump). However, when you do this, you are on your own. The Midi Kit only tags the data as being non-atomic, but offers no additional support. The default implementation of BMidiLocalConsumer completely ignores such events. To handle non-atomic MIDI data, you should override the BMidiLocalConsumer::Data() hook and process the MIDI event yourself. All of BMidiLocalProducer's other spray functions always send atomic data.

Parameters:
data the MIDI event data
length byte size of the data buffer
atomic whether the data buffer contains a single complete MIDI event
time the required performance time of the event
See also:
BMidiLocalConsumer::Data()

void BMidiLocalProducer::SprayKeyPressure ( uchar  channel,
uchar  note,
uchar  pressure,
bigtime_t  time = 0 
) const

Sends a Polyphonic Pressure (Aftertouch) event to all connected consumers.

See also:
BMidiLocalConsumer::KeyPressure()

void BMidiLocalProducer::SprayNoteOff ( uchar  channel,
uchar  note,
uchar  velocity,
bigtime_t  time = 0 
) const

Sends a Note Off event to all connected consumers.

See also:
BMidiLocalConsumer::NoteOff()

void BMidiLocalProducer::SprayNoteOn ( uchar  channel,
uchar  note,
uchar  velocity,
bigtime_t  time = 0 
) const

Sends a Note On event to all connected consumers.

See also:
BMidiLocalConsumer::NoteOn()

void BMidiLocalProducer::SprayPitchBend ( uchar  channel,
uchar  lsb,
uchar  msb,
bigtime_t  time = 0 
) const

Sends a Pitch Bend event to all connected consumers.

See also:
BMidiLocalConsumer::PitchBend()

void BMidiLocalProducer::SprayProgramChange ( uchar  channel,
uchar  programNumber,
bigtime_t  time = 0 
) const

Sends a Program Change event to all connected consumers.

See also:
BMidiLocalConsumer::ProgramChange()

void BMidiLocalProducer::SpraySystemCommon ( uchar  status,
uchar  data1,
uchar  data2,
bigtime_t  time = 0 
) const

Sends a System Common event to the connected consumers.

The status byte must be one of the following:

0xF1B_MIDI_TIME_CODEdata1 only
0xF2B_SONG_POSITIONdata1 and data2
0xF3B_SONG_SELECTdata1 only
0xF5B_CABLE_MESSAGEdata1 only
0xF6B_TUNE_REQUESTno data
0xF7B_SYS_EX_ENDno data

See also:
BMidiLocalConsumer::SystemCommon()

void BMidiLocalProducer::SpraySystemExclusive ( void *  data,
size_t  length,
bigtime_t  time = 0 
) const

Sends a System Exclusive event to all connected consumers.

You retain ownership of the data and are responsible for freeing it. Even though data is not declared const, the function does not change it. Even though the amount of data may be quite large, this function always sends sysex messages as an atomic block of data.

See also:
BMidiLocalConsumer::SystemExclusive()

void BMidiLocalProducer::SpraySystemRealTime ( uchar  status,
bigtime_t  time = 0 
) const

Sends a Real Time event to the connected consumers.

The status byte must be one of the following:

0xF8B_TIMING_CLOCK
0xFAB_START
0xFBB_CONTINUE
0xFCB_STOP
0xFEB_ACTIVE_SENSING
0xFFB_SYSTEM_RESET

Because of their high priority, the MIDI specification allows real time messages to "interleave" with other MIDI messages. A large sysex dump, for example, may be interrupted by a real time event. The Midi Kit, however, doesn't care. If you (or another producer) have just sent a big system exclusive to a consumer, any following real time message will simply have to wait until the consumer has dealt with the sysex.

See also:
BMidiLocalConsumer::SystemRealTime()

void BMidiLocalProducer::SprayTempoChange ( int32  bpm,
bigtime_t  time = 0 
) const

Sends a Tempo Change event to the connected consumers.

This kind of Tempo Change event is not really part of the MIDI spec, rather it is an extension from the SMF (Standard MIDI File) format.

See also:
BMidiLocalConsumer::TempoChange()

status_t BMidiEndpoint::Unregister (  )  [inherited]

Hides the endpoint from the roster.

See also:
Register()


The Haiku Book pre-R1 - BMidiLocalProducer Class Reference
Generated on 14 Feb 2008