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