The Be Book The Media Kit The Media Kit Index

BMediaAddOn

Derived from: none
Declared in:  be/media/MediaAddOn.h Library: libmedia.so
Allocation: Constructor only
Summary:  more...


A BMediaAddOn-derived object describes an executable program that lives in a disk file and is loaded by the Media Server when it's needed. A BMediaAddOn tells the Media Server what kinds of nodes it can create and handles the actual creation of those nodes when called upon by the Media Server to do so.

It's important to note that the functions in the BMediaAddOn class will typically only be called by the Media Kit (and from within the add-on itself). These functions aren't called by client applications.

Getting to Node You...

A given node can support as many media kinds and formats as it wants (although if you support too many widely disparate media types, your add-on may get difficult to maintain, but that's another issue entirely). For example, a node that supports video might support inputting AVI, QuickTime, and MPEG-2, but might only be able to output AVI. This is information that the Media Kit needs to know. For this reason, the BMediaAddOn needs to provide information about the media flavors it supports.

This is done using the flavor_info structure:

struct flavor_info {
   char *name;
   char *info;
   uint64 kinds;
   uint32 flavor_flags;
   int32 internal_id;
   int32 possible_count;

   int32 in_format_count;
   uint32 in_format_flags;
   const media_format *in_formats;

   int32 out_format_count;
   uint32 out_format_flags;
   const media_format *out_formats;

   uint32 _reserved_[16];

private:
   flavor_info & operator=(const flavor_info &other);
};

The name and info fields provide a human-readable name, and information about the flavor.

The kinds field should indicate all the relevant kinds that the node matches; this is a bit field, and it's possible that more than one flag may be relevant. See  "node_kind" on page202.

The flavor_flags field contains flags providing additional information about the flavor.

Constant Description
B_FLAVOR_IS_GLOBAL The flavor will be forced into the Media Add-on Server, and only one instance of it will exist.
B_FLAVOR_IS_LOCAL The flavor will be forced into the loading application, and many instances of it may exist.

If neither flag is specified, the Media Kit will decide what to do with the flavor.

The internal_id is an internal ID number that your add-on can use to identify the flavor; the flavor will be requested by the Media Kit using this ID number.

The possible_count field specifies to the Media Kit the maximum number of instances of your node can be in existence at the same time. For example, if your node provides support for a particular sound card, this value should be equal to the number of cards you support that are currently installed in the computer.

in_format_count specifies how many input formats the flavor supports, and in_formats is a list of all the input formats supported by the flavor.

in_format_flags provides informational flags about the flavor's inputs. There aren't any defined values for this field yet; be sure to set it to 0.

out_format_count specifies how many output formats the flavor supports, and out_formats is a list of all the output formats supported by the flavor.

out_format_flags provides informational flags about the flavor's outputs. There aren't any defined values for this field yet; be sure to set it to 0.

If your node is a physical input, such as a sound card, your node's kinds field should include B_PHYSICAL_INPUT among the flags set therein. Likewise, if your node is a physical output, or a system mixer, you should include B_PHYSICAL_OUTPUT or B_SYSTEM_MIXER.

Your node's constructor should also call AddNodeKind() to add these kind flags; the base classes only add B_BUFFER_CONSUMER, B_BUFFER_PRODUCER, and so forth; the flags indicating that the node represents a physical input, physical output, or system mixer aren't added automatically. For example, a sound digitizer node's constructor might have the following form:

MyBufferProducer::MyBufferProducer(const char *name) :
         BMediaNode(name),
         BBufferProducer() {

   AddNodeKind(B_PHYSICAL_INPUT);

   /* constructor stuff goes here */
}


Hook Functions


Constructor and Destructor


BMediaAddOn()

explicit BMediaAddOn(image_id image)

This is the BMediaAddOn constructor; your derived class should perform whatever initialization is necessary in the constructor, and handle any activities necessary in order to properly comply with the media add-on protocol.

The image_id identifies the add-on image from which the add-on was loaded. Your make_media_addon() function should be sure to save the image ID passed to it and pass that value through to the BMediaAddOn constructor, or the Media Kit will be unhappy with you.


~BMediaAddOn

~BMediaAddOn()

You should never delete a BMediaAddOn yourself; the Media Server will do this when the add-on is no longer needed. However, if you're implementing a media add-on, this is a good place to handle disposing of memory you've allocated.


Member Functions


AutoStart()

virtual status_t AutoStart(int32 index, BMediaNode **outNode,
      
int32 *outInternalID, bool *outHasMore) = 0

If WantsAutoStart() returns true, you'll get repeated calls to AutoStart() when your add-on is loaded.

Your AutoStart() function should be implemented to instantiate nodes to your liking, one for each call to AutoStart(). Each time AutoStart() is called, index will be one higher than the previous pass. After creating the new node, store a pointer to it in outNode, and set outInternalID to the internal ID of the flavor represented by that node.

Before returning, set outHasMore to true if there are more nodes to start, and false if there aren't.

Return B_OK if you return a valid node. If there aren't any more nodes to be started, return B_BAD_INDEX. If the specified index fails, but there may be other nodes to start, return B_ADDON_FAILED.


CountFlavors()

virtual int32 CountFlavors(void)

Implement this hook function to return the number of flavors your add-on can deal with.


GetConfigurationFor()

virtual status_t GetConfigurationFor(BMediaNode *node, BMessage *config)

Implement this function to save information about how the given node is configured into the specified message. This lets the node's configuration be saved to disk for future rehydration using InstantiateNodeFor().

Note that it's not reasonable to save information about what connections are routed through the node, since the other nodes probably won't exist when the node is rehydrated. It's up to the application to reconstruct the connections itself, as it wishes.

If the configuration information is stashed into config without errors, return B_OK; otherwise, return an appropriate error code.


GetFileFormatList()

virtual status_t GetFileFormatList(int32 flavorID,
      media_file_format *outWritableFormats,
      int32 inWriteItems,
      int32 *outWriteItems,
      media_file_format *outReadableFormats,
      int32 inReadItems,
      int32 *outReadItems,
      void *reserved)

If your add-on provides nodes that can either read or write media data from files, you should implement this function to describe the media_file_formats you can read and write.

On input, the flavorID argument indicates which flavor you should return information about. You should fill the array outWritableFormats with a list of the file formats the corresponding flavor can write, and the outReadableFormats array with a list of the file formats the flavor can read. The inWriteItems and inReadItems arguments indicate how many items can be stored in each array.

Both outWritableFormats and outReadableFormats can be NULL. Don't write into these arrays if the corresponding pointer is NULL.

On output, you should set outWriteItems to be the number of file formats you can write—even if it's larger than inWriteItems. This lets the caller resize the array and call you back to get the complete list. Likewise, outReadItems should be set to the number of file formats you can read.

The reserved argument isn't currently used, and should always be specified as NULL.

Only implement this function if your node derives from BFileInterface.

If an error occurs, return an appropriate error code; otherwise, return B_OK.


GetFlavorAt()

virtual status_t GetFlavorAt(int32 flavorNum, const flavor_info **outInfo)

Implement GetFlavorAt() to store in outInfo a pointer to a static flavor_info structure describing one flavor supported by your add-on. The data pointed to by outInfo will be copied by the Media Kit after GetFlavorAt() returns. For example, if your add-on only supports one flavor:

flavor_info flavorInfo;

status_t MyMediaAddOn::GetFlavorAt(int32 n, const flavor_info **out_info) {
   if (n != 0) {
      return B_ERROR;
   }

   flavorInfo->internal_id = n;
   flavorInfo->name = strdup("My Media Node");
   flavorInfo->info = strdup("This node receives video from spy cameras at area pizza parlors and determines which one is the least busy.");
   flavorInfo->kinds = B_BUFFER_CONSUMER | B_PHYSICAL_OUTPUT;
   flavorInfo->flavor_flags = 0;
   flavorInfo->possible_count = 0;

   // Set up the list of input formats. We only support
   // raw video input.

   flavorInfo->in_format_count = 1;
   media_format *aFormat = new media_format;
   aFormat->type = B_MEDIA_RAW_VIDEO;
   aFormat->u.raw_video = media_raw_video_format::wildcard;
   flavorInfo->in_formats = aFormat;

   // We don't output.

   flavorInfo->out_format_count = 0;
   flavorInfo->out_formats = 0;

   // And set up the result pointer

   *out_info = flavorInfo;
   return B_OK;
}

If you allocate memory for the flavor_info structure, be sure to discard it before your add-on is unloaded (the destructor is a good place to do this). If you forget to discard the memory, you'll leak, and that can be really embarrassing.

If flavorNum is greater than CountFlavors()-1 (in other words, if the requested number is larger than the number of flavors you support), return B_ERROR. Otherwise, return B_OK or, if an error occurs, an appropriate error code.


ImageID()

image_id ImageID(void)

Returns the add-on's image ID, as specified by the BMediaAddOn constructor.

Your make_media_addon() function should be sure to save the image ID passed to it and pass that value through to the BMediaAddOn constructor, or the Media Kit will be unhappy with you.


InitCheck()

virtual status_t InitCheck(const char **outFailureText)

Implement this hook function to set outFailureText to point to a static text buffer that contains a message explaining why your add-on failed the most recent operation requested by the Media Server. This doesn't include errors reported by nodes instantiated by your add-on, but only to errors caused directly by your BMediaAddOn-derived object.

The buffer pointed to by outFailureText shouldn't go away until the add-on is reloaded or a new call to InitCheck() is made.

Also returned is the actual result code from that operation; if all is well, B_OK should be returned.


InstantiateNodeFor()

virtual BMediaNode *InstantiateNodeFor(const flavor_info *info,
      BMessage *config, status_t *outError)

Given the information in info (which might be a copy of information you previously returned from a GetFlavorAt() call), you should instantiate a new object of the node class referenced by info's internal_id field and return a pointer to that node.

The config message might contain information saved by a previous instance of the same flavor node, and should be used to configure the new node if possible. config will never be NULL, although it may not have any fields of interest in it.

The simplest implementation of this function, in which there's no configuration possible, might look like this:

BMediaNode *BMyConsumerAddOn::InstantiateNodeFor(const flavor_info *info,
            BMessage *config, status_t *outError) {
   return new MyConsumerNode((const char *) "My Consumer Node");
}

If a new instance can't be instantiated, set outError to an appropriate error code and return NULL. Otherwise, set outError to B_OK.


SniffRef() , SniffType() , SniffTypeKind()

virtual status_t SniffRef(const entry_ref &file, BMimeType *outMimeType,
      float *outQuality, int32 *outInternalID)
virtual status_t SniffType(BMimeType &mimeType,
      float *outQuality, int32 *outInternalID)
virtual status_t SniffTypeKind(BMimeType &mimeType, uint64 inKinds,
      float *outQuality, int32 *outInternalID,
      void *reserved)

If your add-on supports BFileInterface nodes, you may implement SniffRef(). Given the specified file, examine the file and set outMimeType to describe the MIME type of the file.

Additionally, you can implement SniffType() to report how well your add-on can handle a file containing data of the MIME type specified by mimeType.

If your node deals with both producers and consumers, you shouldn't implement SniffType(). Implement SniffTypeKind() instead. If SniffTypeKind() is implemented, SniffType() won't be called.

SniffTypeKind() limits the search to the kinds indicated by inKinds. This lets the caller indicate whether it's looking for a consumer or a producer, for example.

In any case, you should also store, in outQuality, a value representing the quality level at which your add-on can interpret the data in the file (where 0.0 means you can't handle it well at all and 1.0 means you can handle it perfectly), and in outInternalID, the internal ID of the flavor that handles the data.

Don't implement these functions if your add-on doesn't support BFileInterface nodes.

Return B_OK if you've successfully identified the node; otherwise, return an appropriate error code.


WantsAutoStart()

virtual bool WantsAutoStart(void)

Implement this hook function to return true if there are one or more node flavors supported by your add-on that want to be instantiated automatically when the add-on is loaded, instead of waiting until they're explicitly instantiated by an application's request later. Return false otherwise.


Global C Functions


make_media_addon()

BMediaAddOn *make_media_addon(image_id addonID)

make_media_addon() is the global C function your add-on needs to implement in order to make itself available to the world. It will be called when the Media Server loads your add-on, and you should return an instance of your BMediaAddOn-derived class, with the appropriate overrides to the hook functions.

The addonID argument is your add-on's image ID. Your make_media_addon() function should be sure to save the image ID passed to it and pass that value through to the BMediaAddOn constructor, or the Media Kit will be unhappy with you.

This function can be quite simple:

BMediaAddOn *make_media_addon(image_id myImage) {
   return new MyConsumerAddOn(myImage);
}

It simply creates an instance of the add-on object (in this case, MyConsumerAddOn), and returns it.


Structures


dormant_flavor_info

Declared in:  be/media/MediaAddOn.h

struct dormant_flavor_info : public flavor_info, public BFlattenable {
   dormant_node_info();
   virtual ~dormant_node_info();
   dormant_flavor_info(const dormant_flavor_info &);
   dormant_flavor_info& operator=(const dormant_flavor_info &);
   dormant_flavor_info& operator=(const flavor_info &);

   dormant_node_info node_info;

   void set_name(const char *in_name);
   void set_info(const char *in_info);
   void add_in_format(const media_format &in_format);
   void add_out_format(const media_format &out_format);

   virtual bool IsFixedSize() const;
   virtual type_code TypeCode() const;
   virtual ssize_t FlattenedSize() const;
   virtual status_t Flatten(void *buffer, ssize_t size) const;
   virtual status_t Unflatten(type_code c, const void *buf, ssize_t size);

private:
   void assign_atoms(const flavor_info &that);
   media_addon_id addon;
   int32 flavor_id;
   char name[B_MEDIA_NAME_LENGTH];
private:
   char reserved[128];
};

The dormant_flavor_info structure describes a flavor in a dormant node.


dormant_node_info

Declared in:  be/media/MediaAddOn.h

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 dormant_node_info structure describes a node that resides in an add-on and that may not be in memory. You might use it when issuing the BMediaRoster::InstantiateDormantNode() to instantiate a node, for example.

The addon field indicates the ID number of the media add-on in which the node resides, and the flavor_id is the flavor ID internal to that add-on indicating which flavor the node should represent. The name field is the node's name.


flavor_info

Declared in:  be/media/MediaAddOn.h

struct flavor_info {
   char *name;
   char *info;
   uint64 kinds;
   uint32 flavor_flags;
   int32 internal_id;
   int32 possible_count;

   int32 in_format_count;
   uint32 in_format_flags;
   const media_format *in_formats;

   int32 out_format_count;
   uint32 out_format_flags;
   const media_format *out_formats;

   uint32 _reserved_[16];

private:
   flavor_info & operator=(const flavor_info &other);
};

The name and info fields provide a human-readable name, and information about the flavor.

The kinds field should be set to the node kind. See  "node_kind" on page202.

The flavor_flags field contain flags providing additional information about the flavor.

Constant Description
B_FLAVOR_IS_GLOBAL The flavor will be forced into the Media Add-on Server, and only one instance of it will exist.
B_FLAVOR_IS_LOCAL The flavor will be forced into the loading application, and many instances of it may exist.

If neither flag is specified, the Media Kit will decide what to do with the flavor.

The internal_id is an internal ID number that your add-on can use to identify the flavor; the flavor will be requested by the Media Kit using this ID number.

The possible_count field specifies to the Media Kit the maximum number of instances of your node can be in existence at the same time. For example, if your node provides support for a particular sound card, this value should be equal to the number of cards you support that are currently installed in the computer.

in_format_count specifies how many input formats the flavor supports, and in_formats is a list of all the input formats supported by the flavor.

in_format_flags provides informational flags about the flavor's inputs. There currently aren't any defined flags, so set this field to 0.

out_format_count specifies how many output formats the flavor supports, and out_formats is a list of all the output formats supported by the flavor.

out_format_flags provides informational flags about the flavor's outputs. There currently aren't any defined flags, so set this field to 0.


The Be Book The Media Kit The Media Kit Index

Stephen van Egmond
Add a comment