1 #include <TimeSource.h> 2 #include <Buffer.h> 3 #include <stdlib.h> 4 #include "ConsumerNode.h" 5 #include "misc.h" 6 7 ConsumerNode::ConsumerNode() : 8 BBufferConsumer(B_MEDIA_RAW_AUDIO), 9 BMediaEventLooper(), 10 BMediaNode("ConsumerNode") 11 { 12 out("ConsumerNode::ConsumerNode\n"); 13 } 14 15 ConsumerNode::~ConsumerNode() 16 { 17 out("ConsumerNode::~ConsumerNode\n"); 18 Quit(); 19 } 20 21 void 22 ConsumerNode::NodeRegistered() 23 { 24 out("ConsumerNode::NodeRegistered\n"); 25 InitializeInput(); 26 SetPriority(108); 27 Run(); 28 } 29 30 status_t 31 ConsumerNode::AcceptFormat( 32 const media_destination & dest, 33 media_format * format) 34 { 35 out("ConsumerNode::AcceptFormat\n"); 36 37 if (dest != mInput.destination) 38 return B_MEDIA_BAD_DESTINATION; 39 40 if (format == NULL) 41 return B_BAD_VALUE; 42 43 if (format->type != B_MEDIA_RAW_AUDIO) 44 return B_MEDIA_BAD_FORMAT; 45 46 return B_OK; 47 } 48 49 status_t 50 ConsumerNode::GetNextInput( 51 int32 * cookie, 52 media_input * out_input) 53 { 54 out("ConsumerNode::GetNextInput\n"); 55 56 if (out_input == NULL) 57 return B_BAD_VALUE; 58 59 if (++(*cookie) > 1) 60 return B_BAD_INDEX; 61 62 *out_input = mInput; 63 return B_OK; 64 } 65 66 void 67 ConsumerNode::DisposeInputCookie( 68 int32 cookie) 69 { 70 out("ConsumerNode::DisposeInputCookie\n"); 71 return; 72 } 73 74 void 75 ConsumerNode::BufferReceived( 76 BBuffer * buffer) 77 { 78 out("ConsumerNode::BufferReceived, sheduled time = %5.4f\n",buffer->Header()->start_time / 1E6); 79 media_timed_event event(buffer->Header()->start_time,BTimedEventQueue::B_HANDLE_BUFFER, 80 buffer, BTimedEventQueue::B_RECYCLE_BUFFER); 81 EventQueue()->AddEvent(event); 82 return; 83 } 84 85 void 86 ConsumerNode::ProducerDataStatus( 87 const media_destination & for_whom, 88 int32 status, 89 bigtime_t at_performance_time) 90 { 91 out("ConsumerNode::ProducerDataStatus\n"); 92 if (for_whom == mInput.destination) { 93 media_timed_event event(at_performance_time,BTimedEventQueue::B_DATA_STATUS, 94 &mInput, BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL); 95 EventQueue()->AddEvent(event); 96 } 97 } 98 99 status_t 100 ConsumerNode::GetLatencyFor( 101 const media_destination & for_whom, 102 bigtime_t * out_latency, 103 media_node_id * out_timesource) 104 { 105 out("ConsumerNode::GetLatencyFor\n"); 106 // make sure this is one of my valid inputs 107 if (for_whom != mInput.destination) 108 return B_MEDIA_BAD_DESTINATION; 109 110 *out_latency = 23000; 111 *out_timesource = TimeSource()->ID(); 112 return B_OK; 113 } 114 115 status_t 116 ConsumerNode::Connected( 117 const media_source & producer, 118 const media_destination & where, 119 const media_format & with_format, 120 media_input * out_input) 121 { 122 out("ConsumerNode::Connected\n"); 123 if (where != mInput.destination) 124 return B_MEDIA_BAD_DESTINATION; 125 126 // calculate my latency here, because it may depend on buffer sizes/durations, then 127 // tell the BMediaEventLooper how early we need to get the buffers 128 SetEventLatency(10 * 1000); //fixme 129 130 /* reserve the connection */ 131 mInput.source = producer; 132 mInput.format = with_format; 133 134 /* and publish it's name and connection info */ 135 *out_input = mInput; 136 137 #if 0 138 /* create the buffer group */ 139 if (mBufferGroup == NULL) { 140 create_own_buffer_group(); 141 mBufferGroup = mOwnBufferGroup; 142 } 143 144 /* set the duration of the node's buffers */ 145 int32 numBuffers; 146 mBufferGroup->CountBuffers(&numBuffers); 147 SetBufferDuration((1000000LL * numBuffers) / mOutput.format.u.raw_video.field_rate); 148 #endif 149 150 return B_OK; 151 } 152 153 void 154 ConsumerNode::Disconnected( 155 const media_source & producer, 156 const media_destination & where) 157 { 158 out("ConsumerNode::Disconnected\n"); 159 160 /* unreserve the connection */ 161 InitializeInput(); 162 163 #if 0 164 /* release buffer group */ 165 mBufferGroup = NULL; 166 if (mOwnBufferGroup != NULL) { 167 delete_own_buffer_group(); 168 } 169 #endif 170 171 return; 172 } 173 174 status_t 175 ConsumerNode::FormatChanged( 176 const media_source & producer, 177 const media_destination & consumer, 178 int32 change_tag, 179 const media_format & format) 180 { 181 out("ConsumerNode::FormatChanged\n"); 182 return B_OK; 183 } 184 185 status_t 186 ConsumerNode::SeekTagRequested( 187 const media_destination& destination, 188 bigtime_t in_target_time, 189 uint32 in_flags, 190 media_seek_tag* out_seek_tag, 191 bigtime_t* out_tagged_time, 192 uint32* out_flags) 193 { 194 out("ConsumerNode::SeekTagRequested\n"); 195 return B_OK; 196 } 197 198 BMediaAddOn* 199 ConsumerNode::AddOn(int32 * internal_id) const 200 { 201 out("ConsumerNode::AddOn\n"); 202 return NULL; 203 } 204 205 void 206 ConsumerNode::HandleEvent(const media_timed_event *event, 207 bigtime_t lateness, 208 bool realTimeEvent) 209 { 210 switch (event->type) 211 { 212 case BTimedEventQueue::B_HANDLE_BUFFER: 213 { 214 out("ConsumerNode::HandleEvent B_HANDLE_BUFFER\n"); 215 BBuffer* buffer = const_cast<BBuffer*>((BBuffer*) event->pointer); 216 217 out("### sheduled time = %5.4f, current time = %5.4f, lateness = %5.4f\n",buffer->Header()->start_time / 1E6,TimeSource()->Now() / 1E6,lateness / 1E6); 218 219 snooze((rand()*100) % 200000); 220 221 if (buffer) 222 buffer->Recycle(); 223 } 224 break; 225 226 case BTimedEventQueue::B_PARAMETER: 227 { 228 out("ConsumerNode::HandleEvent B_PARAMETER\n"); 229 } 230 break; 231 232 case BTimedEventQueue::B_START: 233 { 234 out("ConsumerNode::HandleEvent B_START\n"); 235 } 236 break; 237 238 case BTimedEventQueue::B_STOP: 239 { 240 out("ConsumerNode::HandleEvent B_STOP\n"); 241 } 242 // stopping implies not handling any more buffers. So, we flush all pending 243 // buffers out of the event queue before returning to the event loop. 244 EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER); 245 break; 246 247 case BTimedEventQueue::B_SEEK: 248 { 249 out("ConsumerNode::HandleEvent B_SEEK\n"); 250 } 251 break; 252 253 case BTimedEventQueue::B_WARP: 254 { 255 out("ConsumerNode::HandleEvent B_WARP\n"); 256 } 257 // similarly, time warps aren't meaningful to the logger, so just record it and return 258 //mLogger->Log(LOG_WARP_HANDLED, logMsg); 259 break; 260 261 case BTimedEventQueue::B_DATA_STATUS: 262 { 263 out("ConsumerNode::HandleEvent B_DATA_STATUS\n"); 264 } 265 break; 266 267 default: 268 { 269 out("ConsumerNode::HandleEvent default\n"); 270 } 271 break; 272 } 273 } 274 275 status_t 276 ConsumerNode::HandleMessage(int32 message,const void *data, size_t size) 277 { 278 out("ConsumerNode::HandleMessage %lx\n",message); 279 if (B_OK == BBufferConsumer::HandleMessage(message,data,size)) 280 return B_OK; 281 if (B_OK == BMediaEventLooper::HandleMessage(message,data,size)) 282 return B_OK; 283 return BMediaNode::HandleMessage(message,data,size); 284 } 285 286 void 287 ConsumerNode::InitializeInput() 288 { 289 out("ConsumerNode::InitializeInput()\n"); 290 mInput.source = media_source::null; 291 mInput.destination.port = ControlPort(); 292 mInput.destination.id = 0; 293 mInput.node = Node(); 294 mInput.format.type = B_MEDIA_RAW_AUDIO; 295 mInput.format.u.raw_audio = media_raw_audio_format::wildcard; 296 mInput.format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; 297 mInput.format.u.raw_audio.channel_count = 1; 298 mInput.format.u.raw_audio.frame_rate = 44100; 299 mInput.format.u.raw_audio.byte_order = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN; 300 strcpy(mInput.name, "this way in"); 301 } 302