From 242094db6d5f3885b8cf944882c852029e1055a7 Mon Sep 17 00:00:00 2001 From: shatty Date: Mon, 16 Sep 2002 03:29:54 +0000 Subject: [PATCH] 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 --- .../AbstractFileInterfaceAddOn.h | 118 +++ .../AbstractFileInterfaceNode.cpp | 957 ++++++++++++++++++ .../media-add-ons/AbstractFileInterfaceNode.h | 313 ++++++ 3 files changed, 1388 insertions(+) create mode 100644 src/add-ons/media/media-add-ons/AbstractFileInterfaceAddOn.h create mode 100644 src/add-ons/media/media-add-ons/AbstractFileInterfaceNode.cpp create mode 100644 src/add-ons/media/media-add-ons/AbstractFileInterfaceNode.h diff --git a/src/add-ons/media/media-add-ons/AbstractFileInterfaceAddOn.h b/src/add-ons/media/media-add-ons/AbstractFileInterfaceAddOn.h new file mode 100644 index 0000000000..839e9268e3 --- /dev/null +++ b/src/add-ons/media/media-add-ons/AbstractFileInterfaceAddOn.h @@ -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 +#include + +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 */ diff --git a/src/add-ons/media/media-add-ons/AbstractFileInterfaceNode.cpp b/src/add-ons/media/media-add-ons/AbstractFileInterfaceNode.cpp new file mode 100644 index 0000000000..7bf6006e7d --- /dev/null +++ b/src/add-ons/media/media-add-ons/AbstractFileInterfaceNode.cpp @@ -0,0 +1,957 @@ +// AbstractFileInterfaceNode.cpp +// +// Andrew Bachmann, 2002 +// +// The AbstractFileInterfaceNode class implements +// the common functionality between MediaReader +// and MediaWriter. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AbstractFileInterfaceNode.h" + +#include +#include + +// -------------------------------------------------------- // +// 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 *) {} diff --git a/src/add-ons/media/media-add-ons/AbstractFileInterfaceNode.h b/src/add-ons/media/media-add-ons/AbstractFileInterfaceNode.h new file mode 100644 index 0000000000..b0a0d01272 --- /dev/null +++ b/src/add-ons/media/media-add-ons/AbstractFileInterfaceNode.h @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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 */