1 /* 2 * multiaudio replacement media addon for BeOS 3 * 4 * Copyright (c) 2002, Jerome Duval (jerome.duval@free.fr) 5 * 6 * All rights reserved. 7 * Redistribution and use in source and binary forms, with or without modification, 8 * are permitted provided that the following conditions are met: 9 * 10 * - Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 #ifndef _MULTIAUDIONODE_H 29 #define _MULTIAUDIONODE_H 30 31 #include <MediaDefs.h> 32 #include <MediaNode.h> 33 #include <FileInterface.h> 34 #include <BufferConsumer.h> 35 #include <BufferProducer.h> 36 #include <Controllable.h> 37 #include <MediaEventLooper.h> 38 #include <TimeSource.h> 39 #include <Controllable.h> 40 #include <File.h> 41 #include <Entry.h> 42 #include "multi_audio.h" 43 #include "MultiAudioDevice.h" 44 45 /*bool format_is_acceptible( 46 const media_format & producer_format, 47 const media_format & consumer_format);*/ 48 49 50 class node_input 51 { 52 public: 53 node_input(media_input &input, media_format format); 54 ~node_input(); 55 56 int32 fChannelId; 57 media_input fInput; 58 media_format fPreferredFormat; 59 media_format fFormat; 60 uint32 fBufferCycle; 61 multi_buffer_info fOldMBI; 62 BBuffer *fBuffer; 63 }; 64 65 class node_output 66 { 67 public: 68 node_output(media_output &output, media_format format); 69 ~node_output(); 70 71 int32 fChannelId; 72 media_output fOutput; 73 media_format fPreferredFormat; 74 media_format fFormat; 75 76 BBufferGroup *fBufferGroup; 77 bool fOutputEnabled; 78 uint64 fSamplesSent; 79 volatile uint32 fBufferCycle; 80 multi_buffer_info fOldMBI; 81 }; 82 83 class MultiAudioNode : 84 public BBufferConsumer, 85 public BBufferProducer, 86 public BTimeSource, 87 public BMediaEventLooper, 88 public BControllable 89 { 90 protected: 91 virtual ~MultiAudioNode(void); 92 93 public: 94 95 explicit MultiAudioNode(BMediaAddOn *addon, char* name, MultiAudioDevice *device, 96 int32 internal_id, BMessage * config); 97 98 virtual status_t InitCheck(void) const; 99 100 /*************************/ 101 /* begin from BMediaNode */ 102 public: 103 virtual BMediaAddOn* AddOn( 104 int32 * internal_id) const; /* Who instantiated you -- or NULL for app class */ 105 106 protected: 107 /* These don't return errors; instead, they use the global error condition reporter. */ 108 /* A node is required to have a queue of at least one pending command (plus TimeWarp) */ 109 /* and is recommended to allow for at least one pending command of each type. */ 110 /* Allowing an arbitrary number of outstanding commands might be nice, but apps */ 111 /* cannot depend on that happening. */ 112 virtual void Preroll(void); 113 114 public: 115 virtual status_t HandleMessage( 116 int32 message, 117 const void * data, 118 size_t size); 119 120 protected: 121 virtual void NodeRegistered(void); /* reserved 2 */ 122 virtual status_t RequestCompleted(const media_request_info &info); 123 virtual void SetTimeSource(BTimeSource *timeSource); 124 125 /* end from BMediaNode */ 126 /***********************/ 127 128 /******************************/ 129 /* begin from BBufferConsumer */ 130 131 //included from BMediaAddOn 132 //virtual status_t HandleMessage( 133 // int32 message, 134 // const void * data, 135 // size_t size); 136 137 /* Someone, probably the producer, is asking you about this format. Give */ 138 /* your honest opinion, possibly modifying *format. Do not ask upstream */ 139 /* producer about the format, since he's synchronously waiting for your */ 140 /* reply. */ 141 virtual status_t AcceptFormat( 142 const media_destination & dest, 143 media_format * format); 144 virtual status_t GetNextInput( 145 int32 * cookie, 146 media_input * out_input); 147 virtual void DisposeInputCookie( 148 int32 cookie); 149 virtual void BufferReceived( 150 BBuffer * buffer); 151 virtual void ProducerDataStatus( 152 const media_destination & for_whom, 153 int32 status, 154 bigtime_t at_performance_time); 155 virtual status_t GetLatencyFor( 156 const media_destination & for_whom, 157 bigtime_t * out_latency, 158 media_node_id * out_timesource); 159 virtual status_t Connected( 160 const media_source & producer, /* here's a good place to request buffer group usage */ 161 const media_destination & where, 162 const media_format & with_format, 163 media_input * out_input); 164 virtual void Disconnected( 165 const media_source & producer, 166 const media_destination & where); 167 /* The notification comes from the upstream producer, so he's already cool with */ 168 /* the format; you should not ask him about it in here. */ 169 virtual status_t FormatChanged( 170 const media_source & producer, 171 const media_destination & consumer, 172 int32 change_tag, 173 const media_format & format); 174 175 /* Given a performance time of some previous buffer, retrieve the remembered tag */ 176 /* of the closest (previous or exact) performance time. Set *out_flags to 0; the */ 177 /* idea being that flags can be added later, and the understood flags returned in */ 178 /* *out_flags. */ 179 virtual status_t SeekTagRequested( 180 const media_destination & destination, 181 bigtime_t in_target_time, 182 uint32 in_flags, 183 media_seek_tag * out_seek_tag, 184 bigtime_t * out_tagged_time, 185 uint32 * out_flags); 186 187 /* end from BBufferConsumer */ 188 /****************************/ 189 190 /******************************/ 191 /* begin from BBufferProducer */ 192 193 virtual status_t FormatSuggestionRequested( media_type type, 194 int32 quality, 195 media_format* format); 196 197 virtual status_t FormatProposal( const media_source& output, 198 media_format* format); 199 200 virtual status_t FormatChangeRequested( const media_source& source, 201 const media_destination& destination, 202 media_format* io_format, 203 int32* _deprecated_); 204 virtual status_t GetNextOutput( int32* cookie, 205 media_output* out_output); 206 virtual status_t DisposeOutputCookie( int32 cookie); 207 208 virtual status_t SetBufferGroup( const media_source& for_source, 209 BBufferGroup* group); 210 211 virtual status_t PrepareToConnect( const media_source& what, 212 const media_destination& where, 213 media_format* format, 214 media_source* out_source, 215 char* out_name); 216 217 virtual void Connect( status_t error, 218 const media_source& source, 219 const media_destination& destination, 220 const media_format& format, 221 char* io_name); 222 223 virtual void Disconnect( const media_source& what, 224 const media_destination& where); 225 226 virtual void LateNoticeReceived( const media_source& what, 227 bigtime_t how_much, 228 bigtime_t performance_time); 229 230 virtual void EnableOutput( const media_source & what, 231 bool enabled, 232 int32* _deprecated_); 233 virtual void AdditionalBufferRequested( const media_source& source, 234 media_buffer_id prev_buffer, 235 bigtime_t prev_time, 236 const media_seek_tag* prev_tag); 237 238 /* end from BBufferProducer */ 239 /****************************/ 240 241 /*****************/ 242 /* BControllable */ 243 /*****************/ 244 245 /********************************/ 246 /* start from BMediaEventLooper */ 247 248 protected: 249 /* you must override to handle your events! */ 250 /* you should not call HandleEvent directly */ 251 virtual void HandleEvent( const media_timed_event *event, 252 bigtime_t lateness, 253 bool realTimeEvent = false); 254 255 /* end from BMediaEventLooper */ 256 /******************************/ 257 258 /********************************/ 259 /* start from BTimeSource */ 260 protected: 261 virtual void SetRunMode( run_mode mode); 262 virtual status_t TimeSourceOp( const time_source_op_info &op, 263 void *_reserved); 264 265 /* end from BTimeSource */ 266 /******************************/ 267 268 /********************************/ 269 /* start from BControllable */ 270 protected: 271 virtual status_t GetParameterValue( int32 id, 272 bigtime_t* last_change, 273 void* value, 274 size_t* ioSize); 275 virtual void SetParameterValue( int32 id, 276 bigtime_t when, 277 const void* value, 278 size_t size); 279 virtual BParameterWeb* MakeParameterWeb(); 280 281 /* end from BControllable */ 282 /******************************/ 283 284 protected: 285 286 virtual status_t HandleStart( 287 const media_timed_event *event, 288 bigtime_t lateness, 289 bool realTimeEvent = false); 290 virtual status_t HandleSeek( 291 const media_timed_event *event, 292 bigtime_t lateness, 293 bool realTimeEvent = false); 294 virtual status_t HandleWarp( 295 const media_timed_event *event, 296 bigtime_t lateness, 297 bool realTimeEvent = false); 298 virtual status_t HandleStop( 299 const media_timed_event *event, 300 bigtime_t lateness, 301 bool realTimeEvent = false); 302 virtual status_t HandleBuffer( 303 const media_timed_event *event, 304 bigtime_t lateness, 305 bool realTimeEvent = false); 306 virtual status_t HandleDataStatus( 307 const media_timed_event *event, 308 bigtime_t lateness, 309 bool realTimeEvent = false); 310 virtual status_t HandleParameter( 311 const media_timed_event *event, 312 bigtime_t lateness, 313 bool realTimeEvent = false); 314 315 public: 316 317 static void GetFlavor(flavor_info * outInfo, int32 id); 318 static void GetFormat(media_format * outFormat); 319 320 status_t GetConfigurationFor(BMessage * into_message); 321 322 323 private: 324 325 MultiAudioNode( /* private unimplemented */ 326 const MultiAudioNode & clone); 327 MultiAudioNode & operator=( 328 const MultiAudioNode & clone); 329 330 //void WriteBuffer( BBuffer *buffer, node_input &input ); 331 void WriteZeros(node_input &input, uint32 bufferCycle); 332 void FillWithZeros(node_input &input); 333 void FillNextBuffer(node_input &channel, BBuffer* buffer); 334 335 static int32 _run_thread_( void *data ); 336 int32 RunThread(); 337 status_t StartThread(); 338 status_t StopThread(); 339 340 341 void AllocateBuffers(node_output &channel); 342 BBuffer* FillNextBuffer( multi_buffer_info &MBI, 343 node_output &channel); 344 void UpdateTimeSource(multi_buffer_info &MBI, 345 multi_buffer_info &oldMBI, 346 node_input &input); 347 348 node_output* FindOutput(media_source source); 349 node_input* FindInput(media_destination dest); 350 node_input* FindInput(int32 destinationId); 351 352 void ProcessGroup(BParameterGroup *group, int32 index, int32 &nbParameters); 353 void ProcessMux(BDiscreteParameter *parameter, int32 index); 354 355 status_t fInitCheckStatus; 356 357 BMediaAddOn *fAddOn; 358 int32 fId; 359 360 BList fInputs; 361 362 bigtime_t fLatency; 363 BList fOutputs; 364 media_format fPreferredFormat; 365 366 bigtime_t fInternalLatency; 367 // this is computed from the real (negotiated) chunk size and bit rate, 368 // not the defaults that are in the parameters 369 bigtime_t fBufferPeriod; 370 371 372 //volatile uint32 fBufferCycle; 373 sem_id fBuffer_free; 374 375 376 thread_id fThread; 377 378 MultiAudioDevice *fDevice; 379 380 //multi_description MD; 381 //multi_format_info MFI; 382 //multi_buffer_list MBL; 383 384 //multi_mix_control_info MMCI; 385 //multi_mix_control MMC[MAX_CONTROLS]; 386 387 bool fTimeSourceStarted; 388 389 BParameterWeb *fWeb; 390 391 BMessage fConfig; 392 }; 393 394 #endif /* _MULTIAUDIONODE_H */ 395