abstract file interface node used for reader and writer
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1049 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,118 @@
|
|||||||
|
// AbstractFileInterfaceAddOn.h
|
||||||
|
//
|
||||||
|
// Andrew Bachmann, 2002
|
||||||
|
//
|
||||||
|
// AbstractFileInterfaceAddOn is an add-on
|
||||||
|
// that can make instances of AbstractFileInterfaceNode
|
||||||
|
//
|
||||||
|
// AbstractFileInterfaceNode handles a file and a multistream
|
||||||
|
|
||||||
|
#if !defined(_ABSTRACT_FILE_INTERFACE_ADD_ON_H)
|
||||||
|
#define _ABSTRACT_FILE_INTERFACE_ADD_ON_H
|
||||||
|
|
||||||
|
#include <MediaDefs.h>
|
||||||
|
#include <MediaAddOn.h>
|
||||||
|
|
||||||
|
class AbstractFileInterfaceAddOn :
|
||||||
|
public BMediaAddOn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~AbstractFileInterfaceAddOn(void);
|
||||||
|
explicit AbstractFileInterfaceAddOn(image_id image);
|
||||||
|
|
||||||
|
/**************************/
|
||||||
|
/* begin from BMediaAddOn */
|
||||||
|
public:
|
||||||
|
virtual status_t InitCheck(
|
||||||
|
const char ** out_failure_text);
|
||||||
|
virtual int32 CountFlavors(void);
|
||||||
|
virtual status_t GetFlavorAt(
|
||||||
|
int32 n,
|
||||||
|
const flavor_info ** out_info);
|
||||||
|
virtual BMediaNode * InstantiateNodeFor(
|
||||||
|
const flavor_info * info,
|
||||||
|
BMessage * config,
|
||||||
|
status_t * out_error) = 0;
|
||||||
|
virtual status_t GetConfigurationFor(
|
||||||
|
BMediaNode * your_node,
|
||||||
|
BMessage * into_message);
|
||||||
|
virtual bool WantsAutoStart(void);
|
||||||
|
virtual status_t AutoStart(
|
||||||
|
int in_count,
|
||||||
|
BMediaNode ** out_node,
|
||||||
|
int32 * out_internal_id,
|
||||||
|
bool * out_has_more);
|
||||||
|
|
||||||
|
/* only implement if you have a B_FILE_INTERFACE node */
|
||||||
|
virtual status_t SniffRef(
|
||||||
|
const entry_ref & file,
|
||||||
|
BMimeType * io_mime_type,
|
||||||
|
float * out_quality,
|
||||||
|
int32 * out_internal_id);
|
||||||
|
virtual status_t SniffType( // This is broken if you deal with producers
|
||||||
|
const BMimeType & type, // and consumers both. Use SniffTypeKind instead.
|
||||||
|
float * out_quality, // If you implement SniffTypeKind, this doesn't
|
||||||
|
int32 * out_internal_id); // get called.
|
||||||
|
virtual status_t GetFileFormatList(
|
||||||
|
int32 flavor_id, // for this node flavor (if it matters)
|
||||||
|
media_file_format * out_writable_formats, // don't write here if NULL
|
||||||
|
int32 in_write_items, // this many slots in out_writable_formats
|
||||||
|
int32 * out_write_items, // set this to actual # available, even if bigger than in count
|
||||||
|
media_file_format * out_readable_formats, // don't write here if NULL
|
||||||
|
int32 in_read_items, // this many slots in out_readable_formats
|
||||||
|
int32 * out_read_items, // set this to actual # available, even if bigger than in count
|
||||||
|
void * _reserved); // ignore until further notice
|
||||||
|
virtual status_t SniffTypeKind( // Like SniffType, but for the specific kind(s)
|
||||||
|
const BMimeType & type,
|
||||||
|
uint64 in_kinds,
|
||||||
|
float * out_quality,
|
||||||
|
int32 * out_internal_id,
|
||||||
|
void * _reserved) = 0;
|
||||||
|
virtual status_t SniffTypeKind( // Like SniffType, but for the specific kind(s)
|
||||||
|
const BMimeType & type,
|
||||||
|
uint64 in_kinds,
|
||||||
|
uint64 io_kind,
|
||||||
|
float * out_quality,
|
||||||
|
int32 * out_internal_id,
|
||||||
|
void * _reserved);
|
||||||
|
|
||||||
|
|
||||||
|
/* end from BMediaAddOn */
|
||||||
|
/************************/
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
AbstractFileInterfaceAddOn( /* private unimplemented */
|
||||||
|
const AbstractFileInterfaceAddOn & clone);
|
||||||
|
AbstractFileInterfaceAddOn & operator=(
|
||||||
|
const AbstractFileInterfaceAddOn & clone);
|
||||||
|
|
||||||
|
int32 refCount;
|
||||||
|
|
||||||
|
/* Mmmh, stuffing! */
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_0(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_1(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_2(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_3(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_4(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_5(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_6(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_7(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_8(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_9(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_10(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_11(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_12(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_13(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_14(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceAddOn_15(void *);
|
||||||
|
|
||||||
|
uint32 _reserved_media_reader_add_on_[16];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#if BUILDING_ABSTRACT_FILE_INTERFACE__ADD_ON
|
||||||
|
extern "C" _EXPORT BMediaAddOn * make_abstract_file_interface_add_on(image_id you);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ABSTRACT_FILE_INTERFACE_ADD_ON_H */
|
||||||
@@ -0,0 +1,957 @@
|
|||||||
|
// AbstractFileInterfaceNode.cpp
|
||||||
|
//
|
||||||
|
// Andrew Bachmann, 2002
|
||||||
|
//
|
||||||
|
// The AbstractFileInterfaceNode class implements
|
||||||
|
// the common functionality between MediaReader
|
||||||
|
// and MediaWriter.
|
||||||
|
|
||||||
|
#include <MediaDefs.h>
|
||||||
|
#include <MediaNode.h>
|
||||||
|
#include <MediaAddOn.h>
|
||||||
|
#include <FileInterface.h>
|
||||||
|
#include <Controllable.h>
|
||||||
|
#include <MediaEventLooper.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <Errors.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <BufferGroup.h>
|
||||||
|
#include <TimeSource.h>
|
||||||
|
#include <Buffer.h>
|
||||||
|
#include <ParameterWeb.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "AbstractFileInterfaceNode.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
// ctor/dtor
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
|
||||||
|
AbstractFileInterfaceNode::~AbstractFileInterfaceNode(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::~AbstractFileInterfaceNode\n");
|
||||||
|
// Stop the BMediaEventLooper thread
|
||||||
|
Quit();
|
||||||
|
if (fCurrentFile != 0) {
|
||||||
|
delete fCurrentFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFileInterfaceNode::AbstractFileInterfaceNode(
|
||||||
|
size_t defaultChunkSize = 8192,
|
||||||
|
float defaultBitRate = 800000,
|
||||||
|
const flavor_info * info = 0,
|
||||||
|
BMessage * config = 0,
|
||||||
|
BMediaAddOn * addOn = 0)
|
||||||
|
: BMediaNode("AbstractFileInterfaceNode"),
|
||||||
|
BFileInterface(),
|
||||||
|
BControllable(),
|
||||||
|
BMediaEventLooper()
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::AbstractFileInterfaceNode\n");
|
||||||
|
// keep our creator around for AddOn calls later
|
||||||
|
fAddOn = addOn;
|
||||||
|
// null some fields
|
||||||
|
fCurrentFile = 0;
|
||||||
|
f_current_mime_type[0] = '\0';
|
||||||
|
// initialize the parameters
|
||||||
|
if (defaultChunkSize <= 0) {
|
||||||
|
fInitCheckStatus = B_BAD_VALUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fDefaultChunkSizeParam = defaultChunkSize;
|
||||||
|
fDefaultChunkSizeParamChangeTime = 0;
|
||||||
|
if (defaultBitRate <= 0) {
|
||||||
|
fInitCheckStatus = B_BAD_VALUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fDefaultBitRateParam = defaultBitRate;
|
||||||
|
fDefaultBitRateParamChangeTime = 0;
|
||||||
|
// initialize parameter compute fields
|
||||||
|
fLeastRecentlyUpdatedParameter = DEFAULT_BIT_RATE_PARAM;
|
||||||
|
fLastUpdatedParameter = DEFAULT_BUFFER_PERIOD_PARAM;
|
||||||
|
// From the chunk size and bit rate we compute the buffer period.
|
||||||
|
int64 value = int64(8000000/1024*fDefaultChunkSizeParam/fDefaultBitRateParam);
|
||||||
|
if ((value <= 0) || (value > INT_MAX)) {
|
||||||
|
fInitCheckStatus = B_BAD_VALUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fDefaultBufferPeriodParam = int32(value);
|
||||||
|
fDefaultBufferPeriodParamChangeTime = 0;
|
||||||
|
|
||||||
|
fInitCheckStatus = B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::InitCheck(void) const
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::InitCheck\n");
|
||||||
|
return fInitCheckStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::GetConfigurationFor(
|
||||||
|
BMessage * into_message)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetConfigurationFor\n");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
// implementation of BMediaNode
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
|
||||||
|
BMediaAddOn * AbstractFileInterfaceNode::AddOn(
|
||||||
|
int32 * internal_id) const
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::AddOn\n");
|
||||||
|
// BeBook says this only gets called if we were in an add-on.
|
||||||
|
if (fAddOn != 0) {
|
||||||
|
// If we get a null pointer then we just won't write.
|
||||||
|
if (internal_id != 0) {
|
||||||
|
internal_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fAddOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::Start(
|
||||||
|
bigtime_t performance_time)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::Start(pt=%i)\n",performance_time);
|
||||||
|
BMediaEventLooper::Start(performance_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::Stop(
|
||||||
|
bigtime_t performance_time,
|
||||||
|
bool immediate)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::Stop(pt=%i,%s)\n",performance_time,(immediate?"now":"then"));
|
||||||
|
BMediaEventLooper::Stop(performance_time,immediate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::Seek(
|
||||||
|
bigtime_t media_time,
|
||||||
|
bigtime_t performance_time)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::Seek(mt=%i,pt=%i)\n",media_time,performance_time);
|
||||||
|
BMediaEventLooper::Seek(media_time,performance_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::SetRunMode(
|
||||||
|
run_mode mode)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::SetRunMode(%i)\n",mode);
|
||||||
|
BMediaEventLooper::SetRunMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::TimeWarp(
|
||||||
|
bigtime_t at_real_time,
|
||||||
|
bigtime_t to_performance_time)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::TimeWarp(rt=%i,pt=%i)\n",at_real_time,to_performance_time);
|
||||||
|
BMediaEventLooper::TimeWarp(at_real_time,to_performance_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::Preroll(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::Preroll\n");
|
||||||
|
// XXX:Performance opportunity
|
||||||
|
BMediaNode::Preroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::SetTimeSource(
|
||||||
|
BTimeSource * time_source)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::SetTimeSource\n");
|
||||||
|
BMediaNode::SetTimeSource(time_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::HandleMessage(
|
||||||
|
int32 message,
|
||||||
|
const void * data,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::HandleMessage\n");
|
||||||
|
status_t status = B_OK;
|
||||||
|
switch (message) {
|
||||||
|
// no special messages for now
|
||||||
|
default:
|
||||||
|
status = BFileInterface::HandleMessage(message,data,size);
|
||||||
|
if (status == B_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
status = BMediaNode::HandleMessage(message,data,size);
|
||||||
|
if (status == B_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BMediaNode::HandleBadMessage(message,data,size);
|
||||||
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::RequestCompleted(
|
||||||
|
const media_request_info & info)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::RequestCompleted\n");
|
||||||
|
return BMediaNode::RequestCompleted(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::DeleteHook(
|
||||||
|
BMediaNode * node)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::DeleteHook\n");
|
||||||
|
return BMediaEventLooper::DeleteHook(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::NodeRegistered(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::NodeRegistered\n");
|
||||||
|
|
||||||
|
// set up our parameter web
|
||||||
|
SetParameterWeb(MakeParameterWeb());
|
||||||
|
|
||||||
|
// start the BMediaEventLooper thread
|
||||||
|
SetPriority(B_REAL_TIME_PRIORITY);
|
||||||
|
Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::GetNodeAttributes(
|
||||||
|
media_node_attribute * outAttributes,
|
||||||
|
size_t inMaxCount)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetNodeAttributes\n");
|
||||||
|
return BMediaNode::GetNodeAttributes(outAttributes,inMaxCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::AddTimer(
|
||||||
|
bigtime_t at_performance_time,
|
||||||
|
int32 cookie)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::AddTimer\n");
|
||||||
|
return BMediaEventLooper::AddTimer(at_performance_time,cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
|
||||||
|
BParameterWeb * AbstractFileInterfaceNode::MakeParameterWeb(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::MakeParameterWeb\n");
|
||||||
|
|
||||||
|
BParameterWeb * web = new BParameterWeb();
|
||||||
|
BParameterGroup * mainGroup = web->MakeGroup("AbstractFileInterfaceNode Parameters");
|
||||||
|
|
||||||
|
// these three are related:
|
||||||
|
// DEFAULT_CHUNK_SIZE_PARAM = DEFAULT_BIT_RATE_PARAM / 1024 * DEFAULT_BUFFER_PERIOD_PARAM * 1000
|
||||||
|
BParameterGroup * chunkSizeGroup = mainGroup->MakeGroup("Chunk Size Group");
|
||||||
|
BContinuousParameter * chunkSizeParameter
|
||||||
|
= chunkSizeGroup->MakeContinuousParameter(
|
||||||
|
DEFAULT_CHUNK_SIZE_PARAM, B_MEDIA_MULTISTREAM,
|
||||||
|
"Chunk Size", B_GAIN, "bytes", 1024, 32*1024, 512);
|
||||||
|
chunkSizeParameter->SetResponse(BContinuousParameter::B_LINEAR,1,0);
|
||||||
|
chunkSizeParameter->SetValue(&fDefaultChunkSizeParam,sizeof(fDefaultChunkSizeParam),0);
|
||||||
|
|
||||||
|
BParameterGroup * bitRateGroup = mainGroup->MakeGroup("Bit Rate Group");
|
||||||
|
BContinuousParameter * bitRateParameter
|
||||||
|
= bitRateGroup->MakeContinuousParameter(
|
||||||
|
DEFAULT_BIT_RATE_PARAM, B_MEDIA_MULTISTREAM,
|
||||||
|
"Bit Rate", B_GAIN, "kbits/sec", 1, 320000, 1);
|
||||||
|
bitRateParameter->SetResponse(BContinuousParameter::B_LINEAR,.001,0);
|
||||||
|
bitRateParameter->SetValue(&fDefaultBitRateParam,sizeof(fDefaultBitRateParam),0);
|
||||||
|
|
||||||
|
BParameterGroup * bufferPeriodGroup = mainGroup->MakeGroup("Buffer Period Group");
|
||||||
|
BContinuousParameter * bufferPeriodParameter
|
||||||
|
= bufferPeriodGroup->MakeContinuousParameter(
|
||||||
|
DEFAULT_BUFFER_PERIOD_PARAM, B_MEDIA_MULTISTREAM,
|
||||||
|
"Buffer Period", B_GAIN, "ms", 1, 10000, 1);
|
||||||
|
bufferPeriodParameter->SetResponse(BContinuousParameter::B_LINEAR,1,0);
|
||||||
|
bufferPeriodParameter->SetValue(&fDefaultBufferPeriodParam,sizeof(fDefaultBufferPeriodParam),0);
|
||||||
|
|
||||||
|
return web;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
// implementation of BFileInterface
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::GetNextFileFormat(
|
||||||
|
int32 * cookie,
|
||||||
|
media_file_format * out_format)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetNextFileFormat\n");
|
||||||
|
// let's not crash even if they are stupid
|
||||||
|
if (out_format == 0) {
|
||||||
|
// no place to write!
|
||||||
|
fprintf(stderr,"<- B_BAD_VALUE\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
if (cookie != 0) {
|
||||||
|
// it's valid but they already got our 1 file format
|
||||||
|
if (*cookie != 0) {
|
||||||
|
fprintf(stderr,"<- B_ERROR\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
// so next time they won't get the same format again
|
||||||
|
*cookie = 1;
|
||||||
|
}
|
||||||
|
*out_format = *GetFileFormat();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::DisposeFileFormatCookie(
|
||||||
|
int32 cookie)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::DisposeFileFormatCookie\n");
|
||||||
|
// nothing to do since our cookies are just integers
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::GetDuration(
|
||||||
|
bigtime_t * out_time)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetDuration\n");
|
||||||
|
if (out_time == 0) {
|
||||||
|
fprintf(stderr,"<- B_BAD_VALUE\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
if (fCurrentFile == 0) {
|
||||||
|
fprintf(stderr,"<- B_NO_INIT\n");
|
||||||
|
return B_NO_INIT;
|
||||||
|
}
|
||||||
|
return fCurrentFile->GetSize(out_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::SniffRef(
|
||||||
|
const entry_ref & file,
|
||||||
|
char * out_mime_type, /* 256 bytes */
|
||||||
|
float * out_quality)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::SniffRef\n");
|
||||||
|
return StaticSniffRef(file,out_mime_type,out_quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::SetRef(
|
||||||
|
const entry_ref & file,
|
||||||
|
uint32 openMode,
|
||||||
|
bool create,
|
||||||
|
bigtime_t * out_time)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::SetRef\n");
|
||||||
|
if (out_time == 0) {
|
||||||
|
fprintf(stderr,"<- B_BAD_VALUE\n");
|
||||||
|
return B_BAD_VALUE; // no crashes today thanks
|
||||||
|
}
|
||||||
|
status_t status;
|
||||||
|
f_current_ref = file;
|
||||||
|
if (fCurrentFile == 0) {
|
||||||
|
fCurrentFile = new BFile(&f_current_ref,(openMode|(create?B_CREATE_FILE:0)));
|
||||||
|
status = fCurrentFile->InitCheck();
|
||||||
|
} else {
|
||||||
|
status = fCurrentFile->SetTo(&f_current_ref,(openMode|(create?B_CREATE_FILE:0)));
|
||||||
|
}
|
||||||
|
if (status != B_OK) {
|
||||||
|
fprintf(stderr,"<- failed BFile initialization\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
// cache the mime type for later
|
||||||
|
fCurrentFile->ReadAttr("BEOS:TYPE",0,0,f_current_mime_type,B_MIME_TYPE_LENGTH);
|
||||||
|
// compute the duration and return any error
|
||||||
|
return GetDuration(out_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::GetRef(
|
||||||
|
entry_ref * out_ref,
|
||||||
|
char * out_mime_type)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetRef\n");
|
||||||
|
if ((out_ref == 0) || (out_mime_type == 0)) {
|
||||||
|
fprintf(stderr,"<- B_BAD_VALUE\n");
|
||||||
|
return B_BAD_VALUE; // no crashes today thanks
|
||||||
|
}
|
||||||
|
if (fCurrentFile == 0) {
|
||||||
|
fprintf(stderr,"<- B_NO_INIT\n");
|
||||||
|
return B_NO_INIT; // the input_ref isn't valid yet either
|
||||||
|
}
|
||||||
|
*out_ref = f_current_ref;
|
||||||
|
// they hopefully allocated enough space (no way to check :-/ )
|
||||||
|
strcpy(out_mime_type,f_current_mime_type);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// provided for BAbstractFileInterfaceNodeAddOn
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::StaticSniffRef(
|
||||||
|
const entry_ref & file,
|
||||||
|
char * out_mime_type, /* 256 bytes */
|
||||||
|
float * out_quality)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::StaticSniffRef\n");
|
||||||
|
if ((out_mime_type == 0) || (out_quality == 0)) {
|
||||||
|
fprintf(stderr,"<- B_BAD_VALUE\n");
|
||||||
|
return B_BAD_VALUE; // we refuse to crash because you were stupid
|
||||||
|
}
|
||||||
|
BNode node(&file);
|
||||||
|
status_t initCheck = node.InitCheck();
|
||||||
|
if (initCheck != B_OK) {
|
||||||
|
fprintf(stderr,"<- failed BNode::InitCheck()\n");
|
||||||
|
return initCheck;
|
||||||
|
}
|
||||||
|
// they hopefully allocated enough room
|
||||||
|
node.ReadAttr("BEOS:TYPE",0,0,out_mime_type,B_MIME_TYPE_LENGTH);
|
||||||
|
*out_quality = 1.0; // we handle all files perfectly! we are so amazing!
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
// implementation for BControllable
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
|
||||||
|
const int32 AbstractFileInterfaceNode::DEFAULT_CHUNK_SIZE_PARAM = 1;
|
||||||
|
const int32 AbstractFileInterfaceNode::DEFAULT_BIT_RATE_PARAM = 2;
|
||||||
|
const int32 AbstractFileInterfaceNode::DEFAULT_BUFFER_PERIOD_PARAM = 3;
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::GetParameterValue(
|
||||||
|
int32 id,
|
||||||
|
bigtime_t * last_change,
|
||||||
|
void * value,
|
||||||
|
size_t * ioSize)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetParameterValue\n");
|
||||||
|
if ((last_change == 0) || (value == 0) || (ioSize == 0)) {
|
||||||
|
return B_BAD_VALUE; // no crashing
|
||||||
|
}
|
||||||
|
switch (id) {
|
||||||
|
case DEFAULT_CHUNK_SIZE_PARAM:
|
||||||
|
if (*ioSize < sizeof(size_t)) {
|
||||||
|
return B_ERROR; // not enough room
|
||||||
|
}
|
||||||
|
*last_change = fDefaultChunkSizeParamChangeTime;
|
||||||
|
*((size_t*)value) = fDefaultChunkSizeParam;
|
||||||
|
*ioSize = sizeof(size_t);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEFAULT_BIT_RATE_PARAM:
|
||||||
|
if (*ioSize < sizeof(float)) {
|
||||||
|
return B_ERROR; // not enough room
|
||||||
|
}
|
||||||
|
*last_change = fDefaultBitRateParamChangeTime;
|
||||||
|
*((float*)value) = fDefaultBitRateParam;
|
||||||
|
*ioSize = sizeof(float);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEFAULT_BUFFER_PERIOD_PARAM:
|
||||||
|
if (*ioSize < sizeof(int32)) {
|
||||||
|
return B_ERROR; // not enough room
|
||||||
|
}
|
||||||
|
*last_change = fDefaultBufferPeriodParamChangeTime;
|
||||||
|
*((int32*)value) = fDefaultBufferPeriodParam;
|
||||||
|
*ioSize = sizeof(int32);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetParameterValue unknown id (%i)\n",id);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::SetParameterValue(
|
||||||
|
int32 id,
|
||||||
|
bigtime_t when,
|
||||||
|
const void * value,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::SetParameterValue(id=%i,when=%ld,size=%i)\n",id,int32(when),int32(size));
|
||||||
|
switch (id) {
|
||||||
|
case DEFAULT_CHUNK_SIZE_PARAM:
|
||||||
|
case DEFAULT_BIT_RATE_PARAM:
|
||||||
|
case DEFAULT_BUFFER_PERIOD_PARAM:
|
||||||
|
{
|
||||||
|
media_timed_event event(when, BTimedEventQueue::B_PARAMETER,
|
||||||
|
NULL, BTimedEventQueue::B_NO_CLEANUP,
|
||||||
|
size, id, (char*) value, size);
|
||||||
|
EventQueue()->AddEvent(event);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::SetParameterValue unknown id (%i)\n",id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the default implementation should call the add-on main()
|
||||||
|
status_t AbstractFileInterfaceNode::StartControlPanel(
|
||||||
|
BMessenger * out_messenger)
|
||||||
|
{
|
||||||
|
BControllable::StartControlPanel(out_messenger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
// implementation for BMediaEventLooper
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
|
||||||
|
void AbstractFileInterfaceNode::HandleEvent(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::HandleEvent\n");
|
||||||
|
switch (event->type) {
|
||||||
|
case BTimedEventQueue::B_START:
|
||||||
|
HandleStart(event,lateness,realTimeEvent);
|
||||||
|
break;
|
||||||
|
case BTimedEventQueue::B_SEEK:
|
||||||
|
HandleSeek(event,lateness,realTimeEvent);
|
||||||
|
break;
|
||||||
|
case BTimedEventQueue::B_WARP:
|
||||||
|
HandleWarp(event,lateness,realTimeEvent);
|
||||||
|
break;
|
||||||
|
case BTimedEventQueue::B_STOP:
|
||||||
|
HandleStop(event,lateness,realTimeEvent);
|
||||||
|
break;
|
||||||
|
case BTimedEventQueue::B_HANDLE_BUFFER:
|
||||||
|
if (RunState() == BMediaEventLooper::B_STARTED) {
|
||||||
|
HandleBuffer(event,lateness,realTimeEvent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BTimedEventQueue::B_DATA_STATUS:
|
||||||
|
HandleDataStatus(event,lateness,realTimeEvent);
|
||||||
|
break;
|
||||||
|
case BTimedEventQueue::B_PARAMETER:
|
||||||
|
HandleParameter(event,lateness,realTimeEvent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr," unknown event type: %i\n",event->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* override to clean up custom events you have added to your queue */
|
||||||
|
void AbstractFileInterfaceNode::CleanUpEvent(
|
||||||
|
const media_timed_event *event)
|
||||||
|
{
|
||||||
|
BMediaEventLooper::CleanUpEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* called from Offline mode to determine the current time of the node */
|
||||||
|
/* update your internal information whenever it changes */
|
||||||
|
bigtime_t AbstractFileInterfaceNode::OfflineTime()
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::OfflineTime\n");
|
||||||
|
return BMediaEventLooper::OfflineTime();
|
||||||
|
// if (inputFile == 0) {
|
||||||
|
// return 0;
|
||||||
|
// } else {
|
||||||
|
// return inputFile->Position();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* override only if you know what you are doing! */
|
||||||
|
/* otherwise much badness could occur */
|
||||||
|
/* the actual control loop function: */
|
||||||
|
/* waits for messages, Pops events off the queue and calls DispatchEvent */
|
||||||
|
void AbstractFileInterfaceNode::ControlLoop() {
|
||||||
|
BMediaEventLooper::ControlLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::HandleStart(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"MediaReader::HandleStart()\n");
|
||||||
|
if (RunState() != B_STARTED) {
|
||||||
|
HandleBuffer(event,lateness,realTimeEvent);
|
||||||
|
// media_timed_event firstBufferEvent(event->event_time, BTimedEventQueue::B_HANDLE_BUFFER);
|
||||||
|
// //this->HandleEvent(&firstBufferEvent, 0, false);
|
||||||
|
// EventQueue()->AddEvent(firstBufferEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::HandleSeek(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false)
|
||||||
|
{
|
||||||
|
// XXX: argghh.. seek events seem broken when received from
|
||||||
|
// the usual BMediaEventLooper::Seek() dispatcher :-(
|
||||||
|
// They lost where we are supposed to seek to!?!
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::HandleSeek(t=%i,d=%i,bd=%ld)\n",event->event_time,event->data,event->bigdata);
|
||||||
|
if (fCurrentFile != 0) {
|
||||||
|
fCurrentFile->Seek(event->bigdata,SEEK_SET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::HandleWarp(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::HandleWarp\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::HandleStop(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::HandleStop\n");
|
||||||
|
// flush the queue so downstreamers don't get any more
|
||||||
|
EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::HandleParameter(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::HandleParameter");
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
bool chunkSizeUpdated = false, bitRateUpdated = false, bufferPeriodUpdated = false;
|
||||||
|
|
||||||
|
size_t dataSize = size_t(event->data);
|
||||||
|
int32 param = int32(event->bigdata);
|
||||||
|
|
||||||
|
switch (param) {
|
||||||
|
case DEFAULT_CHUNK_SIZE_PARAM:
|
||||||
|
fprintf(stderr,"(DEFAULT_CHUNK_SIZE_PARAM,size=%i",dataSize);
|
||||||
|
if (dataSize < sizeof(size_t)) {
|
||||||
|
fprintf(stderr,")\n");
|
||||||
|
fprintf(stderr,"<- B_BAD_VALUE\n",param);
|
||||||
|
status = B_BAD_VALUE;
|
||||||
|
} else {
|
||||||
|
size_t newDefaultChunkSize = *((size_t*)event->user_data);
|
||||||
|
fprintf(stderr,",%i)\n",newDefaultChunkSize);
|
||||||
|
// ignore non positive chunk sizes
|
||||||
|
// XXX: we may decide later that a 0 chunk size means ship the whole file in one chunk (!)
|
||||||
|
if ((newDefaultChunkSize > 0) && (newDefaultChunkSize != fDefaultChunkSizeParam)) {
|
||||||
|
fprintf(stderr," got a new chunk size, old chunk size was %i\n",fDefaultChunkSizeParam);
|
||||||
|
fDefaultChunkSizeParam = newDefaultChunkSize;
|
||||||
|
fDefaultChunkSizeParamChangeTime = TimeSource()->Now();
|
||||||
|
chunkSizeUpdated = true;
|
||||||
|
if (fLeastRecentlyUpdatedParameter == DEFAULT_CHUNK_SIZE_PARAM) {
|
||||||
|
// Okay we were the least recently updated parameter,
|
||||||
|
// but we just got an update so we are no longer that.
|
||||||
|
// Let's figure out who the new least recently updated
|
||||||
|
// parameter is. We are going to prefer to compute the
|
||||||
|
// bit rate since you usually don't want to muck with
|
||||||
|
// the buffer period. However, if you just set the bitrate
|
||||||
|
// then we are stuck with making the buffer period the new
|
||||||
|
// parameter to be computed.
|
||||||
|
if (fLastUpdatedParameter == DEFAULT_BIT_RATE_PARAM) {
|
||||||
|
fLeastRecentlyUpdatedParameter = DEFAULT_BUFFER_PERIOD_PARAM;
|
||||||
|
} else {
|
||||||
|
fLeastRecentlyUpdatedParameter = DEFAULT_BIT_RATE_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we just got an update, so we are the new lastUpdatedParameter
|
||||||
|
fLastUpdatedParameter = DEFAULT_CHUNK_SIZE_PARAM;
|
||||||
|
// now we have to compute the new value for the leastRecentlyUpdatedParameter
|
||||||
|
// we use the chunk size change time to preserve "simultaneity" information
|
||||||
|
if (fLeastRecentlyUpdatedParameter == DEFAULT_BUFFER_PERIOD_PARAM) {
|
||||||
|
int64 value = int64(8000000/1024*fDefaultChunkSizeParam/fDefaultBitRateParam);
|
||||||
|
if (value > INT_MAX) {
|
||||||
|
// clamp to INT_MAX
|
||||||
|
fDefaultBufferPeriodParam = INT_MAX;
|
||||||
|
// recompute chunk size
|
||||||
|
fDefaultChunkSizeParam = size_t(1024/8000000*fDefaultBitRateParam*fDefaultBufferPeriodParam);
|
||||||
|
} else {
|
||||||
|
fDefaultBufferPeriodParam = MAX(1,value);
|
||||||
|
}
|
||||||
|
fDefaultBufferPeriodParamChangeTime = fDefaultChunkSizeParamChangeTime;
|
||||||
|
bufferPeriodUpdated = true;
|
||||||
|
} else { // must have been bit rate
|
||||||
|
fDefaultBitRateParam = MAX(0.001,8000000/1024*fDefaultChunkSizeParam/fDefaultBufferPeriodParam);
|
||||||
|
fDefaultBitRateParamChangeTime = fDefaultChunkSizeParamChangeTime;
|
||||||
|
bitRateUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DEFAULT_BIT_RATE_PARAM:
|
||||||
|
fprintf(stderr,"(DEFAULT_BIT_RATE_PARAM,size=%i",dataSize);
|
||||||
|
if (dataSize < sizeof(float)) {
|
||||||
|
fprintf(stderr,")\n");
|
||||||
|
fprintf(stderr,"<- B_BAD_VALUE\n",param);
|
||||||
|
status = B_BAD_VALUE;
|
||||||
|
} else {
|
||||||
|
float newDefaultBitRate = *((float*)event->user_data);
|
||||||
|
fprintf(stderr,",%f)\n",newDefaultBitRate);
|
||||||
|
// ignore non positive bitrates
|
||||||
|
if ((newDefaultBitRate > 0) && (newDefaultBitRate != fDefaultBitRateParam)) {
|
||||||
|
fprintf(stderr," got a new bit rate, old bit rate was %i\n",fDefaultBitRateParam);
|
||||||
|
fDefaultBitRateParam = newDefaultBitRate;
|
||||||
|
fDefaultBitRateParamChangeTime = TimeSource()->Now();
|
||||||
|
bitRateUpdated = true;
|
||||||
|
if (fLeastRecentlyUpdatedParameter == DEFAULT_BIT_RATE_PARAM) {
|
||||||
|
// Okay we were the least recently updated parameter,
|
||||||
|
// but we just got an update so we are no longer that.
|
||||||
|
// Let's figure out who the new least recently updated
|
||||||
|
// parameter is. We are going to prefer to compute the
|
||||||
|
// chunk size since you usually don't want to muck with
|
||||||
|
// the buffer period. However, if you just set the chunk size
|
||||||
|
// then we are stuck with making the buffer period the new
|
||||||
|
// parameter to be computed.
|
||||||
|
if (fLastUpdatedParameter == DEFAULT_CHUNK_SIZE_PARAM) {
|
||||||
|
fLeastRecentlyUpdatedParameter = DEFAULT_BUFFER_PERIOD_PARAM;
|
||||||
|
} else {
|
||||||
|
fLeastRecentlyUpdatedParameter = DEFAULT_CHUNK_SIZE_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we just got an update, so we are the new lastUpdatedParameter
|
||||||
|
fLastUpdatedParameter = DEFAULT_BIT_RATE_PARAM;
|
||||||
|
// now we have to compute the new value for the leastRecentlyUpdatedParameter
|
||||||
|
// we use the bit rate change time to preserve "simultaneity" information
|
||||||
|
if (fLeastRecentlyUpdatedParameter == DEFAULT_BUFFER_PERIOD_PARAM) {
|
||||||
|
int64 value = int64(8000000/1024*fDefaultChunkSizeParam/fDefaultBitRateParam);
|
||||||
|
if (value > INT_MAX) {
|
||||||
|
// clamp to INT_MAX
|
||||||
|
fDefaultBufferPeriodParam = INT_MAX;
|
||||||
|
// recompute bit rate
|
||||||
|
fDefaultBitRateParam = MAX(0.001,8000000/1024*fDefaultChunkSizeParam/fDefaultBufferPeriodParam);
|
||||||
|
} else {
|
||||||
|
fDefaultBufferPeriodParam = MAX(1,int32(value));
|
||||||
|
}
|
||||||
|
fDefaultBufferPeriodParamChangeTime = fDefaultBitRateParamChangeTime;
|
||||||
|
bufferPeriodUpdated = true;
|
||||||
|
} else { // must have been chunk size
|
||||||
|
int64 value = int64(1024/8000000*fDefaultBitRateParam*fDefaultBufferPeriodParam);
|
||||||
|
if (value > INT_MAX) {
|
||||||
|
// clamp to INT_MAX
|
||||||
|
fDefaultChunkSizeParam = INT_MAX;
|
||||||
|
// recompute bit rate
|
||||||
|
fDefaultBitRateParam = MAX(0.001,8000000/1024*fDefaultChunkSizeParam/fDefaultBufferPeriodParam);
|
||||||
|
} else {
|
||||||
|
fDefaultChunkSizeParam = MAX(1,int32(value));
|
||||||
|
}
|
||||||
|
fDefaultChunkSizeParamChangeTime = fDefaultBitRateParamChangeTime;
|
||||||
|
chunkSizeUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DEFAULT_BUFFER_PERIOD_PARAM:
|
||||||
|
fprintf(stderr,"(DEFAULT_BUFFER_PERIOD_PARAM,size=%i",dataSize);
|
||||||
|
if (dataSize < sizeof(int32)) {
|
||||||
|
fprintf(stderr,")\n");
|
||||||
|
fprintf(stderr,"<- B_BAD_VALUE\n",param);
|
||||||
|
status = B_BAD_VALUE;
|
||||||
|
} else {
|
||||||
|
int32 newBufferPeriod = *((int32*)event->user_data);
|
||||||
|
fprintf(stderr,",%i)\n",newBufferPeriod);
|
||||||
|
// ignore non positive buffer period
|
||||||
|
if ((newBufferPeriod > 0) && (newBufferPeriod != fDefaultBufferPeriodParam)) {
|
||||||
|
fprintf(stderr," got a new buffer period, old buffer period was %i\n",fDefaultBufferPeriodParam);
|
||||||
|
fDefaultBufferPeriodParam = newBufferPeriod;
|
||||||
|
fDefaultBufferPeriodParamChangeTime = TimeSource()->Now();
|
||||||
|
bufferPeriodUpdated = true;
|
||||||
|
if (fLastUpdatedParameter == DEFAULT_BUFFER_PERIOD_PARAM) {
|
||||||
|
// prefer to update bit rate, unless you just set it
|
||||||
|
if (fLastUpdatedParameter == DEFAULT_BIT_RATE_PARAM) {
|
||||||
|
fLeastRecentlyUpdatedParameter = DEFAULT_CHUNK_SIZE_PARAM;
|
||||||
|
} else {
|
||||||
|
fLeastRecentlyUpdatedParameter = DEFAULT_BIT_RATE_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we just got an update, so we are the new lastUpdatedParameter
|
||||||
|
fLastUpdatedParameter = DEFAULT_BUFFER_PERIOD_PARAM;
|
||||||
|
// now we have to compute the new value for the leastRecentlyUpdatedParameter
|
||||||
|
// we use the buffer period change time to preserve "simultaneity" information
|
||||||
|
if (fLeastRecentlyUpdatedParameter == DEFAULT_BIT_RATE_PARAM) {
|
||||||
|
fDefaultBitRateParam = MAX(0.001,8000000/1024*fDefaultChunkSizeParam/fDefaultBufferPeriodParam);
|
||||||
|
fDefaultBitRateParamChangeTime = fDefaultBufferPeriodParamChangeTime;
|
||||||
|
bitRateUpdated = true;
|
||||||
|
} else { // must have been chunk size
|
||||||
|
int64 value = int64(1024/8000000*fDefaultBitRateParam*fDefaultBufferPeriodParam);
|
||||||
|
if (value > INT_MAX) {
|
||||||
|
// clamp to INT_MAX
|
||||||
|
fDefaultChunkSizeParam = INT_MAX;
|
||||||
|
// recompute buffer period
|
||||||
|
fDefaultBufferPeriodParam = size_t(8000000/1024*fDefaultChunkSizeParam/fDefaultBitRateParam);
|
||||||
|
} else {
|
||||||
|
fDefaultChunkSizeParam = MAX(1,int32(value));
|
||||||
|
}
|
||||||
|
fDefaultChunkSizeParamChangeTime = fDefaultBufferPeriodParamChangeTime;
|
||||||
|
chunkSizeUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::HandleParameter called with unknown param id (%i)\n",param);
|
||||||
|
status = B_ERROR;
|
||||||
|
}
|
||||||
|
// send updates out for all the parameters that changed
|
||||||
|
// in every case this should be two updates. (if I have not made an error :-) )
|
||||||
|
if (chunkSizeUpdated) {
|
||||||
|
fprintf(stderr," chunk size parameter updated\n");
|
||||||
|
BroadcastNewParameterValue(fDefaultChunkSizeParamChangeTime,
|
||||||
|
DEFAULT_CHUNK_SIZE_PARAM,
|
||||||
|
&fDefaultChunkSizeParam,
|
||||||
|
sizeof(fDefaultChunkSizeParam));
|
||||||
|
}
|
||||||
|
if (bitRateUpdated) {
|
||||||
|
fprintf(stderr," bit rate parameter updated\n");
|
||||||
|
BroadcastNewParameterValue(fDefaultBitRateParamChangeTime,
|
||||||
|
DEFAULT_BIT_RATE_PARAM,
|
||||||
|
&fDefaultBitRateParam,
|
||||||
|
sizeof(fDefaultBitRateParam));
|
||||||
|
}
|
||||||
|
if (bufferPeriodUpdated) {
|
||||||
|
fprintf(stderr," buffer period parameter updated\n");
|
||||||
|
BroadcastNewParameterValue(fDefaultBufferPeriodParamChangeTime,
|
||||||
|
DEFAULT_BUFFER_PERIOD_PARAM,
|
||||||
|
&fDefaultBufferPeriodParam,
|
||||||
|
sizeof(fDefaultBufferPeriodParam));
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
// AbstractFileInterfaceNode specific functions
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
|
||||||
|
// public:
|
||||||
|
|
||||||
|
flavor_info * AbstractFileInterfaceNode::GetFlavor(int32 id)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetFlavor\n");
|
||||||
|
static bool initialized = false;
|
||||||
|
static flavor_info info;
|
||||||
|
if (initialized == false) {
|
||||||
|
info.name = "AbstractFileInterfaceNode";
|
||||||
|
info.info = "A AbstractFileInterfaceNode node handles a file.";
|
||||||
|
info.kinds = B_FILE_INTERFACE | B_CONTROLLABLE;
|
||||||
|
info.flavor_flags = B_FLAVOR_IS_LOCAL;
|
||||||
|
info.possible_count = INT_MAX;
|
||||||
|
info.in_format_count = 0; // no inputs
|
||||||
|
info.in_formats = 0;
|
||||||
|
info.out_format_count = 0; // no outputs
|
||||||
|
info.out_formats = 0;
|
||||||
|
info.internal_id = id;
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
media_format * AbstractFileInterfaceNode::GetFormat()
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetFormat\n");
|
||||||
|
static bool initialized = false;
|
||||||
|
static media_format format;
|
||||||
|
if (initialized == false) {
|
||||||
|
format.type = B_MEDIA_MULTISTREAM;
|
||||||
|
format.require_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
||||||
|
format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
|
||||||
|
format.u.multistream = media_multistream_format::wildcard;
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
return &format;
|
||||||
|
}
|
||||||
|
|
||||||
|
media_file_format * AbstractFileInterfaceNode::GetFileFormat()
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::GetFileFormat\n");
|
||||||
|
static bool initialized = false;
|
||||||
|
static media_file_format file_format;
|
||||||
|
if (initialized == false) {
|
||||||
|
file_format.capabilities =
|
||||||
|
media_file_format::B_PERFECTLY_SEEKABLE
|
||||||
|
| media_file_format::B_IMPERFECTLY_SEEKABLE
|
||||||
|
| media_file_format::B_KNOWS_ANYTHING;
|
||||||
|
/* I don't know what to initialize this to. (or if I should) */
|
||||||
|
// format.id =
|
||||||
|
file_format.family = B_ANY_FORMAT_FAMILY;
|
||||||
|
file_format.version = 100;
|
||||||
|
strcpy(file_format.mime_type,"");
|
||||||
|
strcpy(file_format.pretty_name,"any media file format");
|
||||||
|
strcpy(file_format.short_name,"any");
|
||||||
|
strcpy(file_format.file_extension,"");
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
return &file_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
|
||||||
|
// Here we make some guesses based on the file's mime type.
|
||||||
|
// We don't have enough information to add any other requirements.
|
||||||
|
// This function doesn't complain if you have already decided you want
|
||||||
|
// the stream to be considered a different one. (so you can say that you
|
||||||
|
// want to read that mpeg file as avi if you are so nutty.)
|
||||||
|
//
|
||||||
|
status_t AbstractFileInterfaceNode::AddRequirements(media_format * format)
|
||||||
|
{
|
||||||
|
if (strcmp("video/x-msvideo",f_current_mime_type) == 0) {
|
||||||
|
if (format->u.multistream.format == media_multistream_format::wildcard.format) {
|
||||||
|
format->u.multistream.format = media_multistream_format::B_AVI;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (strcmp("video/mpeg",f_current_mime_type) == 0) {
|
||||||
|
if (format->u.multistream.format == media_multistream_format::wildcard.format) {
|
||||||
|
format->u.multistream.format = media_multistream_format::B_MPEG1;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (strcmp("video/quicktime",f_current_mime_type) == 0) {
|
||||||
|
if (format->u.multistream.format == media_multistream_format::wildcard.format) {
|
||||||
|
format->u.multistream.format = media_multistream_format::B_QUICKTIME;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (strcmp("audio/x-mpeg",f_current_mime_type) == 0) {
|
||||||
|
if (format->u.multistream.format == media_multistream_format::wildcard.format) {
|
||||||
|
format->u.multistream.format = media_multistream_format::B_MPEG1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need some sort of bit rate and chunk size, so if the other guy
|
||||||
|
// didn't care, we'll use our own defaults.
|
||||||
|
status_t AbstractFileInterfaceNode::ResolveWildcards(media_format * format)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AbstractFileInterfaceNode::ResolveWildcards\n");
|
||||||
|
// There isn't an unknown format. hmph.
|
||||||
|
// if (format->u.multistream.format == media_multistream_format::wildcard.format) {
|
||||||
|
// format->u.multistream.format = media_multistream_format::B_UNKNOWN;
|
||||||
|
// }
|
||||||
|
if (format->u.multistream.max_bit_rate == media_multistream_format::wildcard.max_bit_rate) {
|
||||||
|
format->u.multistream.max_bit_rate = fDefaultBitRateParam;
|
||||||
|
}
|
||||||
|
if (format->u.multistream.max_chunk_size == media_multistream_format::wildcard.max_chunk_size) {
|
||||||
|
format->u.multistream.max_chunk_size = fDefaultChunkSizeParam;
|
||||||
|
}
|
||||||
|
if (format->u.multistream.avg_bit_rate == media_multistream_format::wildcard.avg_bit_rate) {
|
||||||
|
format->u.multistream.avg_bit_rate = fDefaultBitRateParam;
|
||||||
|
}
|
||||||
|
if (format->u.multistream.avg_chunk_size == media_multistream_format::wildcard.avg_chunk_size) {
|
||||||
|
format->u.multistream.avg_chunk_size = fDefaultChunkSizeParam;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
// stuffing
|
||||||
|
// -------------------------------------------------------- //
|
||||||
|
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_0(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_1(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_2(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_3(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_4(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_5(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_6(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_7(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_8(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_9(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_10(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_11(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_12(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_13(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_14(void *) {}
|
||||||
|
status_t AbstractFileInterfaceNode::_Reserved_AbstractFileInterfaceNode_15(void *) {}
|
||||||
@@ -0,0 +1,313 @@
|
|||||||
|
// AbstractFileInterfaceNode.h
|
||||||
|
//
|
||||||
|
// Andrew Bachmann, 2002
|
||||||
|
//
|
||||||
|
// The AbstractFileInterfaceNode class implements
|
||||||
|
// the common functionality between MediaReader
|
||||||
|
// and MediaWriter.
|
||||||
|
|
||||||
|
#if !defined(_ABSTRACT_FILE_INTERFACE_NODE_H)
|
||||||
|
#define _ABSTRACT_FILE_INTERFACE_NODE_H
|
||||||
|
|
||||||
|
#include <MediaDefs.h>
|
||||||
|
#include <MediaNode.h>
|
||||||
|
#include <FileInterface.h>
|
||||||
|
#include <Controllable.h>
|
||||||
|
#include <MediaEventLooper.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <BufferGroup.h>
|
||||||
|
|
||||||
|
class AbstractFileInterfaceNode :
|
||||||
|
public BFileInterface,
|
||||||
|
public BControllable,
|
||||||
|
public BMediaEventLooper
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
virtual ~AbstractFileInterfaceNode(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit AbstractFileInterfaceNode(
|
||||||
|
size_t defaultChunkSize = 8192, // chunk size = 8 KB
|
||||||
|
float defaultBitRate = 800000, // bit rate = 100.000 KB/sec = 5.85 MB/minute
|
||||||
|
const flavor_info * info = 0, // buffer period = 80 milliseconds
|
||||||
|
BMessage * config = 0,
|
||||||
|
BMediaAddOn * addOn = 0);
|
||||||
|
|
||||||
|
virtual status_t InitCheck(void) const;
|
||||||
|
|
||||||
|
// see BMediaAddOn::GetConfigurationFor
|
||||||
|
virtual status_t GetConfigurationFor(
|
||||||
|
BMessage * into_message);
|
||||||
|
|
||||||
|
/*************************/
|
||||||
|
/* begin from BMediaNode */
|
||||||
|
public:
|
||||||
|
// /* this port is what a media node listens to for commands */
|
||||||
|
// virtual port_id ControlPort(void) const;
|
||||||
|
|
||||||
|
virtual BMediaAddOn* AddOn(
|
||||||
|
int32 * internal_id) const; /* Who instantiated you -- or NULL for app class */
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* These don't return errors; instead, they use the global error condition reporter. */
|
||||||
|
/* A node is required to have a queue of at least one pending command (plus TimeWarp) */
|
||||||
|
/* and is recommended to allow for at least one pending command of each type. */
|
||||||
|
/* Allowing an arbitrary number of outstanding commands might be nice, but apps */
|
||||||
|
/* cannot depend on that happening. */
|
||||||
|
virtual void Start(
|
||||||
|
bigtime_t performance_time);
|
||||||
|
virtual void Stop(
|
||||||
|
bigtime_t performance_time,
|
||||||
|
bool immediate);
|
||||||
|
virtual void Seek(
|
||||||
|
bigtime_t media_time,
|
||||||
|
bigtime_t performance_time);
|
||||||
|
virtual void SetRunMode(
|
||||||
|
run_mode mode);
|
||||||
|
virtual void TimeWarp(
|
||||||
|
bigtime_t at_real_time,
|
||||||
|
bigtime_t to_performance_time);
|
||||||
|
virtual void Preroll(void);
|
||||||
|
virtual void SetTimeSource(
|
||||||
|
BTimeSource * time_source);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual status_t HandleMessage(
|
||||||
|
int32 message,
|
||||||
|
const void * data,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Called when requests have completed, or failed. */
|
||||||
|
virtual status_t RequestCompleted( /* reserved 0 */
|
||||||
|
const media_request_info & info);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual status_t DeleteHook(BMediaNode * node); /* reserved 1 */
|
||||||
|
|
||||||
|
virtual void NodeRegistered(void); /* reserved 2 */
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/* fill out your attributes in the provided array, returning however many you have. */
|
||||||
|
virtual status_t GetNodeAttributes( /* reserved 3 */
|
||||||
|
media_node_attribute * outAttributes,
|
||||||
|
size_t inMaxCount);
|
||||||
|
|
||||||
|
virtual status_t AddTimer(
|
||||||
|
bigtime_t at_performance_time,
|
||||||
|
int32 cookie);
|
||||||
|
|
||||||
|
/* end from BMediaNode */
|
||||||
|
/***********************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual BParameterWeb * MakeParameterWeb(void);
|
||||||
|
|
||||||
|
/*****************************/
|
||||||
|
/* begin from BFileInterface */
|
||||||
|
protected:
|
||||||
|
//included from BMediaNode
|
||||||
|
//virtual status_t HandleMessage(
|
||||||
|
// int32 message,
|
||||||
|
// const void * data,
|
||||||
|
// size_t size);
|
||||||
|
|
||||||
|
virtual status_t GetNextFileFormat(
|
||||||
|
int32 * cookie,
|
||||||
|
media_file_format * out_format);
|
||||||
|
virtual void DisposeFileFormatCookie(
|
||||||
|
int32 cookie);
|
||||||
|
|
||||||
|
virtual status_t GetDuration(
|
||||||
|
bigtime_t * out_time);
|
||||||
|
|
||||||
|
virtual status_t SniffRef(
|
||||||
|
const entry_ref & file,
|
||||||
|
char * out_mime_type, /* 256 bytes */
|
||||||
|
float * out_quality);
|
||||||
|
|
||||||
|
virtual status_t SetRef(
|
||||||
|
const entry_ref & file,
|
||||||
|
bool create,
|
||||||
|
bigtime_t * out_time) = 0;
|
||||||
|
|
||||||
|
virtual status_t SetRef(
|
||||||
|
const entry_ref & file,
|
||||||
|
uint32 openMode,
|
||||||
|
bool create,
|
||||||
|
bigtime_t * out_time);
|
||||||
|
|
||||||
|
virtual status_t GetRef(
|
||||||
|
entry_ref * out_ref,
|
||||||
|
char * out_mime_type);
|
||||||
|
|
||||||
|
/* end from BFileInterface */
|
||||||
|
/***************************/
|
||||||
|
|
||||||
|
// provided for BAbstractFileInterfaceNodeAddOn
|
||||||
|
public:
|
||||||
|
static status_t StaticSniffRef(
|
||||||
|
const entry_ref & file,
|
||||||
|
char * out_mime_type, /* 256 bytes */
|
||||||
|
float * out_quality);
|
||||||
|
|
||||||
|
/****************************/
|
||||||
|
/* begin from BControllable */
|
||||||
|
|
||||||
|
//included from BMediaNode
|
||||||
|
//virtual status_t HandleMessage(
|
||||||
|
// int32 message,
|
||||||
|
// const void * data,
|
||||||
|
// size_t size);
|
||||||
|
public:
|
||||||
|
/* These are alternate methods of accomplishing the same thing as */
|
||||||
|
/* connecting to control information source/destinations would. */
|
||||||
|
virtual status_t GetParameterValue(
|
||||||
|
int32 id,
|
||||||
|
bigtime_t * last_change,
|
||||||
|
void * value,
|
||||||
|
size_t * ioSize);
|
||||||
|
virtual void SetParameterValue(
|
||||||
|
int32 id,
|
||||||
|
bigtime_t when,
|
||||||
|
const void * value,
|
||||||
|
size_t size);
|
||||||
|
virtual status_t StartControlPanel(
|
||||||
|
BMessenger * out_messenger);
|
||||||
|
|
||||||
|
/* end from BControllable */
|
||||||
|
/**************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
// these three are related:
|
||||||
|
// DEFAULT_CHUNK_SIZE = (DEFAULT_BIT_RATE * 1024) * (DEFAULT_BUFFER_PERIOD / 8000000)
|
||||||
|
static const int32 DEFAULT_CHUNK_SIZE_PARAM; // in bytes
|
||||||
|
static const int32 DEFAULT_BIT_RATE_PARAM; // in 1000*kilobits/sec
|
||||||
|
static const int32 DEFAULT_BUFFER_PERIOD_PARAM; // milliseconds
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t fDefaultChunkSizeParam;
|
||||||
|
bigtime_t fDefaultChunkSizeParamChangeTime;
|
||||||
|
float fDefaultBitRateParam;
|
||||||
|
bigtime_t fDefaultBitRateParamChangeTime;
|
||||||
|
int32 fDefaultBufferPeriodParam;
|
||||||
|
bigtime_t fDefaultBufferPeriodParamChangeTime;
|
||||||
|
|
||||||
|
// This is used to figure out which parameter to compute
|
||||||
|
// when enforcing the above constraint relating the three params
|
||||||
|
int32 fLastUpdatedParameter;
|
||||||
|
int32 fLeastRecentlyUpdatedParameter;
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
/* start from BMediaEventLooper */
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* you must override to handle your events! */
|
||||||
|
/* you should not call HandleEvent directly */
|
||||||
|
virtual void HandleEvent( const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false);
|
||||||
|
|
||||||
|
/* override to clean up custom events you have added to your queue */
|
||||||
|
virtual void CleanUpEvent(const media_timed_event *event);
|
||||||
|
|
||||||
|
/* called from Offline mode to determine the current time of the node */
|
||||||
|
/* update your internal information whenever it changes */
|
||||||
|
virtual bigtime_t OfflineTime();
|
||||||
|
|
||||||
|
/* override only if you know what you are doing! */
|
||||||
|
/* otherwise much badness could occur */
|
||||||
|
/* the actual control loop function: */
|
||||||
|
/* waits for messages, Pops events off the queue and calls DispatchEvent */
|
||||||
|
virtual void ControlLoop();
|
||||||
|
|
||||||
|
/* end from BMediaEventLooper */
|
||||||
|
/******************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual status_t HandleStart(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false);
|
||||||
|
virtual status_t HandleSeek(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false);
|
||||||
|
virtual status_t HandleWarp(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false);
|
||||||
|
virtual status_t HandleStop(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false);
|
||||||
|
virtual status_t HandleBuffer(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false) = 0;
|
||||||
|
virtual status_t HandleDataStatus(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false) = 0;
|
||||||
|
virtual status_t HandleParameter(
|
||||||
|
const media_timed_event *event,
|
||||||
|
bigtime_t lateness,
|
||||||
|
bool realTimeEvent = false);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static flavor_info * GetFlavor(int32 id);
|
||||||
|
static media_format * GetFormat();
|
||||||
|
static media_file_format * GetFileFormat();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual status_t AddRequirements(media_format * format);
|
||||||
|
virtual status_t ResolveWildcards(media_format * format);
|
||||||
|
|
||||||
|
// accessors
|
||||||
|
|
||||||
|
inline BFile * GetCurrentFile() { return fCurrentFile; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
AbstractFileInterfaceNode( /* private unimplemented */
|
||||||
|
const AbstractFileInterfaceNode & clone);
|
||||||
|
AbstractFileInterfaceNode & operator=(
|
||||||
|
const AbstractFileInterfaceNode & clone);
|
||||||
|
|
||||||
|
status_t fInitCheckStatus;
|
||||||
|
|
||||||
|
BMediaAddOn * fAddOn;
|
||||||
|
|
||||||
|
BFile * fCurrentFile;
|
||||||
|
entry_ref f_current_ref;
|
||||||
|
char f_current_mime_type[B_MIME_TYPE_LENGTH+1];
|
||||||
|
|
||||||
|
/* Mmmh, stuffing! */
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_0(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_1(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_2(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_3(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_4(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_5(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_6(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_7(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_8(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_9(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_10(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_11(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_12(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_13(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_14(void *);
|
||||||
|
virtual status_t _Reserved_AbstractFileInterfaceNode_15(void *);
|
||||||
|
|
||||||
|
uint32 _reserved_abstract_file_interface_node_[16];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _ABSTRACT_FILE_INTERFACE_NODE_H */
|
||||||
Reference in New Issue
Block a user