root/branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

Revision 818, 26.2 kB (checked in by ppalmers, 16 years ago)

add prefetch commands, can't harm

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25 #include "AmdtpTransmitStreamProcessor.h"
26 #include "AmdtpPort.h"
27 #include "../StreamProcessorManager.h"
28 #include "devicemanager.h"
29
30 #include "libutil/Time.h"
31
32 #include "libieee1394/ieee1394service.h"
33 #include "libieee1394/IsoHandlerManager.h"
34 #include "libieee1394/cycletimer.h"
35
36 #include <netinet/in.h>
37 #include <assert.h>
38
39 #define AMDTP_FLOAT_MULTIPLIER 2147483392.0
40
41 namespace Streaming
42 {
43
44 /* transmit */
45 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(FFADODevice &parent, int dimension)
46         : StreamProcessor(parent, ePT_Transmit)
47         , m_dimension( dimension )
48         , m_dbc( 0 )
49         , m_nb_audio_ports( 0 )
50         , m_nb_midi_ports( 0 )
51 {}
52
53 enum StreamProcessor::eChildReturnValue
54 AmdtpTransmitStreamProcessor::generatePacketHeader (
55     unsigned char *data, unsigned int *length,
56     unsigned char *tag, unsigned char *sy,
57     int cycle, unsigned int dropped, unsigned int max_length )
58 {
59     struct iec61883_packet *packet = ( struct iec61883_packet * ) data;
60     /* Our node ID can change after a bus reset, so it is best to fetch
61     * our node ID for each packet. */
62     packet->sid = m_1394service.getLocalNodeId() & 0x3f;
63
64     packet->dbs = m_dimension;
65     packet->fn = 0;
66     packet->qpc = 0;
67     packet->sph = 0;
68     packet->reserved = 0;
69     packet->dbc = m_dbc;
70     packet->eoh1 = 2;
71     packet->fmt = IEC61883_FMT_AMDTP;
72
73     *tag = IEC61883_TAG_WITH_CIP;
74     *sy = 0;
75
76     signed int fc;
77     uint64_t presentation_time;
78     unsigned int presentation_cycle;
79     int cycles_until_presentation;
80
81     uint64_t transmit_at_time;
82     unsigned int transmit_at_cycle;
83     int cycles_until_transmit;
84
85     debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "Try for cycle %d\n", cycle );
86     // check whether the packet buffer has packets for us to send.
87     // the base timestamp is the one of the next sample in the buffer
88     ffado_timestamp_t ts_head_tmp;
89     m_data_buffer->getBufferHeadTimestamp ( &ts_head_tmp, &fc ); // thread safe
90
91     // the timestamp gives us the time at which we want the sample block
92     // to be output by the device
93     presentation_time = ( uint64_t ) ts_head_tmp;
94     m_last_timestamp = presentation_time;
95
96     // now we calculate the time when we have to transmit the sample block
97     transmit_at_time = substractTicks ( presentation_time, AMDTP_TRANSMIT_TRANSFER_DELAY );
98
99     // calculate the cycle this block should be presented in
100     // (this is just a virtual calculation since at that time it should
101     //  already be in the device's buffer)
102     presentation_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( presentation_time ) );
103
104     // calculate the cycle this block should be transmitted in
105     transmit_at_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( transmit_at_time ) );
106
107     // we can check whether this cycle is within the 'window' we have
108     // to send this packet.
109     // first calculate the number of cycles left before presentation time
110     cycles_until_presentation = diffCycles ( presentation_cycle, cycle );
111
112     // we can check whether this cycle is within the 'window' we have
113     // to send this packet.
114     // first calculate the number of cycles left before presentation time
115     cycles_until_transmit = diffCycles ( transmit_at_cycle, cycle );
116
117     if (dropped) {
118         debugOutput ( DEBUG_LEVEL_VERBOSE,
119                     "Gen HDR: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
120                     cycle,
121                     transmit_at_cycle, cycles_until_transmit,
122                     transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
123                     presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
124     }
125     // two different options:
126     // 1) there are not enough frames for one packet
127     //      => determine wether this is a problem, since we might still
128     //         have some time to send it
129     // 2) there are enough packets
130     //      => determine whether we have to send them in this packet
131     if ( fc < ( signed int ) m_syt_interval )
132     {
133         // not enough frames in the buffer,
134
135         // we can still postpone the queueing of the packets
136         // if we are far enough ahead of the presentation time
137         if ( cycles_until_presentation <= AMDTP_MIN_CYCLES_BEFORE_PRESENTATION )
138         {
139             debugOutput ( DEBUG_LEVEL_VERBOSE,
140                         "Insufficient frames (P): N=%02d, CY=%04u, TC=%04u, CUT=%04d\n",
141                         fc, cycle, transmit_at_cycle, cycles_until_transmit );
142             // we are too late
143             return eCRV_XRun;
144         }
145         else
146         {
147             unsigned int now_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( m_1394service.getCycleTimerTicks() ) );
148
149             debugOutput ( DEBUG_LEVEL_VERBOSE,
150                         "Insufficient frames (NP): N=%02d, CY=%04u, TC=%04u, CUT=%04d, NOW=%04d\n",
151                         fc, cycle, transmit_at_cycle, cycles_until_transmit, now_cycle );
152             debugWarning("Insufficient frames (NP): N=%02d, CY=%04u, TC=%04u, CUT=%04d, NOW=%04d\n",
153                          fc, cycle, transmit_at_cycle, cycles_until_transmit, now_cycle );
154
155             // there is still time left to send the packet
156             // we want the system to give this packet another go at a later time instant
157             return eCRV_Again; // note that the raw1394 again system doesn't work as expected
158
159             // we could wait here for a certain time before trying again. However, this
160             // is not going to work since we then block the iterator thread, hence also
161             // the receiving code, meaning that we are not processing received packets,
162             // and hence there is no progression in the number of frames available.
163
164             // for example:
165             // SleepRelativeUsec(125); // one cycle
166             // goto try_block_of_frames;
167
168             // or more advanced, calculate how many cycles we are ahead of 'now' and
169             // base the sleep on that.
170
171             // note that this requires that there is one thread for each IsoHandler,
172             // otherwise we're in the deadlock described above.
173         }
174     }
175     else
176     {
177         // there are enough frames, so check the time they are intended for
178         // all frames have a certain 'time window' in which they can be sent
179         // this corresponds to the range of the timestamp mechanism:
180         // we can send a packet 15 cycles in advance of the 'presentation time'
181         // in theory we can send the packet up till one cycle before the presentation time,
182         // however this is not very smart.
183
184         // There are 3 options:
185         // 1) the frame block is too early
186         //      => send an empty packet
187         // 2) the frame block is within the window
188         //      => send it
189         // 3) the frame block is too late
190         //      => discard (and raise xrun?)
191         //         get next block of frames and repeat
192
193         if(cycles_until_transmit < 0)
194         {
195             // we are too late
196             debugOutput(DEBUG_LEVEL_VERBOSE,
197                         "Too late: CY=%04u, TC=%04u, CUT=%04d, TSP=%011llu (%04u)\n",
198                         cycle,
199                         transmit_at_cycle, cycles_until_transmit,
200                         presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time) );
201             //debugShowBackLogLines(200);
202 //             // however, if we can send this sufficiently before the presentation
203 //             // time, it could be harmless.
204 //             // NOTE: dangerous since the device has no way of reporting that it didn't get
205 //             //       this packet on time.
206 //             if(cycles_until_presentation >= AMDTP_MIN_CYCLES_BEFORE_PRESENTATION)
207 //             {
208 //                 // we are not that late and can still try to transmit the packet
209 //                 m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp);
210 //                 return (fc < (signed)(2*m_syt_interval) ? eCRV_Defer : eCRV_Packet);
211 //             }
212 //             else   // definitely too late
213 //             {
214                 return eCRV_XRun;
215 //             }
216         }
217         else if(cycles_until_transmit <= AMDTP_MAX_CYCLES_TO_TRANSMIT_EARLY)
218         {
219             // it's time send the packet
220             m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp);
221             return (fc < (signed)(2*m_syt_interval) ? eCRV_Defer : eCRV_Packet);
222         }
223         else
224         {
225             debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
226                         "Too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
227                         cycle,
228                         transmit_at_cycle, cycles_until_transmit,
229                         transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
230                         presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
231 #ifdef DEBUG
232             if ( cycles_until_transmit > AMDTP_MAX_CYCLES_TO_TRANSMIT_EARLY + 1 )
233             {
234                 debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
235                             "Way too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
236                             cycle,
237                             transmit_at_cycle, cycles_until_transmit,
238                             transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
239                             presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
240             }
241 #endif
242             // we are too early, send only an empty packet
243             return eCRV_EmptyPacket;
244         }
245     }
246     return eCRV_Invalid;
247 }
248
249 enum StreamProcessor::eChildReturnValue
250 AmdtpTransmitStreamProcessor::generatePacketData (
251     unsigned char *data, unsigned int *length,
252     unsigned char *tag, unsigned char *sy,
253     int cycle, unsigned int dropped, unsigned int max_length )
254 {
255     if ( m_data_buffer->readFrames ( m_syt_interval, ( char * ) ( data + 8 ) ) )
256     {
257         debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT DATA (cy %04d): TSP=%011llu (%04u)\n",
258                     cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) );
259         return eCRV_OK;
260     }
261     else return eCRV_XRun;
262
263 }
264
265 enum StreamProcessor::eChildReturnValue
266 AmdtpTransmitStreamProcessor::generateSilentPacketHeader (
267     unsigned char *data, unsigned int *length,
268     unsigned char *tag, unsigned char *sy,
269     int cycle, unsigned int dropped, unsigned int max_length )
270 {
271     struct iec61883_packet *packet = ( struct iec61883_packet * ) data;
272     debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT NONE (cy %04d): CY=%04u, TSP=%011llu (%04u)\n",
273                 cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) );
274
275     /* Our node ID can change after a bus reset, so it is best to fetch
276     * our node ID for each packet. */
277     packet->sid = m_1394service.getLocalNodeId() & 0x3f;
278
279     packet->dbs = m_dimension;
280     packet->fn = 0;
281     packet->qpc = 0;
282     packet->sph = 0;
283     packet->reserved = 0;
284     packet->dbc = m_dbc;
285     packet->eoh1 = 2;
286     packet->fmt = IEC61883_FMT_AMDTP;
287
288     *tag = IEC61883_TAG_WITH_CIP;
289     *sy = 0;
290
291     m_dbc += fillNoDataPacketHeader ( packet, length );
292     return eCRV_OK;
293 }
294
295 enum StreamProcessor::eChildReturnValue
296 AmdtpTransmitStreamProcessor::generateSilentPacketData (
297     unsigned char *data, unsigned int *length,
298     unsigned char *tag, unsigned char *sy,
299     int cycle, unsigned int dropped, unsigned int max_length )
300 {
301     return eCRV_OK; // no need to do anything
302 }
303
304 unsigned int AmdtpTransmitStreamProcessor::fillDataPacketHeader (
305     struct iec61883_packet *packet, unsigned int* length,
306     uint32_t ts )
307 {
308
309     packet->fdf = m_fdf;
310
311     // convert the timestamp to SYT format
312     uint16_t timestamp_SYT = TICKS_TO_SYT ( ts );
313     packet->syt = ntohs ( timestamp_SYT );
314
315     *length = m_syt_interval*sizeof ( quadlet_t ) *m_dimension + 8;
316
317     return m_syt_interval;
318 }
319
320 unsigned int AmdtpTransmitStreamProcessor::fillNoDataPacketHeader (
321     struct iec61883_packet *packet, unsigned int* length )
322 {
323
324     // no-data packets have syt=0xFFFF
325     // and have the usual amount of events as dummy data (?)
326     packet->fdf = IEC61883_FDF_NODATA;
327     packet->syt = 0xffff;
328
329     // FIXME: either make this a setting or choose
330     bool send_payload=true;
331     if ( send_payload )
332     {
333         // this means no-data packets with payload (DICE doesn't like that)
334         *length = 2*sizeof ( quadlet_t ) + m_syt_interval * m_dimension * sizeof ( quadlet_t );
335         return m_syt_interval;
336     }
337     else
338     {
339         // dbc is not incremented
340         // this means no-data packets without payload
341         *length = 2*sizeof ( quadlet_t );
342         return 0;
343     }
344 }
345
346 unsigned int
347 AmdtpTransmitStreamProcessor::getSytInterval() {
348     switch (m_StreamProcessorManager.getNominalRate()) {
349         case 32000:
350         case 44100:
351         case 48000:
352             return 8;
353         case 88200:
354         case 96000:
355             return 16;
356         case 176400:
357         case 192000:
358             return 32;
359         default:
360             debugError("Unsupported rate: %d\n", m_StreamProcessorManager.getNominalRate());
361             return 0;
362     }
363 }
364 unsigned int
365 AmdtpTransmitStreamProcessor::getFDF() {
366     switch (m_StreamProcessorManager.getNominalRate()) {
367         case 32000: return IEC61883_FDF_SFC_32KHZ;
368         case 44100: return IEC61883_FDF_SFC_44K1HZ;
369         case 48000: return IEC61883_FDF_SFC_48KHZ;
370         case 88200: return IEC61883_FDF_SFC_88K2HZ;
371         case 96000: return IEC61883_FDF_SFC_96KHZ;
372         case 176400: return IEC61883_FDF_SFC_176K4HZ;
373         case 192000: return IEC61883_FDF_SFC_192KHZ;
374         default:
375             debugError("Unsupported rate: %d\n", m_StreamProcessorManager.getNominalRate());
376             return 0;
377     }
378 }
379
380 bool AmdtpTransmitStreamProcessor::prepareChild()
381 {
382     debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this );
383     m_syt_interval = getSytInterval();
384     m_fdf = getFDF();
385
386     iec61883_cip_init (
387         &m_cip_status,
388         IEC61883_FMT_AMDTP,
389         m_fdf,
390         m_StreamProcessorManager.getNominalRate(),
391         m_dimension,
392         m_syt_interval );
393
394     if (!initPortCache()) {
395         debugError("Could not init port cache\n");
396         return false;
397     }
398
399     return true;
400 }
401
402 /*
403 * compose the event streams for the packets from the port buffers
404 */
405 bool AmdtpTransmitStreamProcessor::processWriteBlock ( char *data,
406         unsigned int nevents, unsigned int offset )
407 {
408     updatePortCache();
409     switch(m_StreamProcessorManager.getAudioDataType()) {
410         case StreamProcessorManager::eADT_Int24:
411             encodeAudioPortsInt24((quadlet_t *)data, offset, nevents);
412             break;
413         case StreamProcessorManager::eADT_Float:
414             encodeAudioPortsFloat((quadlet_t *)data, offset, nevents);
415             break;
416     }
417     encodeMidiPorts((quadlet_t *)data, offset, nevents);
418     return true;
419 }
420
421 bool
422 AmdtpTransmitStreamProcessor::transmitSilenceBlock(
423     char *data, unsigned int nevents, unsigned int offset)
424 {
425     // no need to update the port cache when transmitting silence since
426     // no dynamic values are used to do so.
427
428     encodeAudioPortsSilence((quadlet_t *)data, offset, nevents);
429     encodeMidiPortsSilence((quadlet_t *)data, offset, nevents);
430     return true;
431 }
432
433 /**
434  * @brief encodes all audio ports in the cache to events (silent data)
435  * @param data
436  * @param offset
437  * @param nevents
438  */
439 void
440 AmdtpTransmitStreamProcessor::encodeAudioPortsSilence(quadlet_t *data,
441                                                       unsigned int offset,
442                                                       unsigned int nevents)
443 {
444     unsigned int j;
445     quadlet_t *target_event;
446     unsigned int i;
447
448     for (i = 0; i < m_nb_audio_ports; i++) {
449         target_event = (quadlet_t *)(data + i);
450         __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
451
452         for (j = 0;j < nevents; j += 1)
453         {
454             *target_event = htonl( 0x40000000 );
455             target_event += m_dimension;
456             __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
457         }
458     }
459 }
460
461 /**
462  * @brief encodes all audio ports in the cache to events (float data)
463  * @param data
464  * @param offset
465  * @param nevents
466  */
467 void
468 AmdtpTransmitStreamProcessor::encodeAudioPortsFloat(quadlet_t *data,
469                                                     unsigned int offset,
470                                                     unsigned int nevents)
471 {
472     unsigned int j;
473     quadlet_t *target_event;
474     unsigned int i;
475
476     for (i = 0; i < m_nb_audio_ports; i++) {
477         struct _MBLA_port_cache &p = m_audio_ports.at(i);
478         target_event = (quadlet_t *)(data + i);
479         __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
480         assert(nevents + offset <= p.buffer_size );
481
482         float *buffer = (float *)(p.buffer);
483         buffer += offset;
484         __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
485
486         for (j = 0;j < nevents; j += 1)
487         {
488             // don't care for overflow
489             float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER;
490             unsigned int tmp = ((int) v);
491             *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 );
492             buffer++;
493             __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
494             target_event += m_dimension;
495             __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
496         }
497     }
498 }
499
500 /**
501  * @brief encodes all audio ports in the cache to events (int24 data)
502  * @param data
503  * @param offset
504  * @param nevents
505  */
506 void
507 AmdtpTransmitStreamProcessor::encodeAudioPortsInt24(quadlet_t *data,
508                                                     unsigned int offset,
509                                                     unsigned int nevents)
510 {
511     unsigned int j;
512     quadlet_t *target_event;
513     unsigned int i;
514
515     for (i = 0; i < m_nb_audio_ports; i++) {
516         struct _MBLA_port_cache &p = m_audio_ports.at(i);
517         target_event = (quadlet_t *)(data + i);
518         __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
519         assert(nevents + offset <= p.buffer_size );
520
521         uint32_t *buffer = (uint32_t *)(p.buffer);
522         buffer += offset;
523         __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
524
525         for (j = 0; j < nevents; j += 1)
526         {
527             *target_event = htonl(((*buffer) & 0x00FFFFFF) | 0x40000000);
528             buffer++;
529             __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
530
531             target_event += m_dimension;
532             __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
533         }
534     }
535 }
536
537 /**
538  * @brief encodes all midi ports in the cache to events (silence)
539  * @param data
540  * @param offset
541  * @param nevents
542  */
543 void
544 AmdtpTransmitStreamProcessor::encodeMidiPortsSilence(quadlet_t *data,
545                                                      unsigned int offset,
546                                                      unsigned int nevents)
547 {
548     quadlet_t *target_event;
549     unsigned int i,j;
550
551     for (i = 0; i < m_nb_midi_ports; i++) {
552         struct _MIDI_port_cache &p = m_midi_ports.at(i);
553
554         for (j = p.location;j < nevents; j += 8) {
555             target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position));
556             __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
557             *target_event = htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA));
558         }
559     }
560 }
561
562 /**
563  * @brief encodes all midi ports in the cache to events
564  * @param data
565  * @param offset
566  * @param nevents
567  */
568 void
569 AmdtpTransmitStreamProcessor::encodeMidiPorts(quadlet_t *data,
570                                               unsigned int offset,
571                                               unsigned int nevents)
572 {
573     quadlet_t *target_event;
574     unsigned int i,j;
575
576     for (i = 0; i < m_nb_midi_ports; i++) {
577         struct _MIDI_port_cache &p = m_midi_ports.at(i);
578         uint32_t *buffer = (quadlet_t *)(p.buffer);
579         buffer += offset;
580         __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality
581
582         for (j = p.location;j < nevents; j += 8) {
583             target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position));
584             __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality
585
586             if ( *buffer & 0xFF000000 )   // we can send a byte
587             {
588                 quadlet_t tmpval;
589                 tmpval = ((*buffer)<<16) & 0x00FF0000;
590                 tmpval = IEC61883_AM824_SET_LABEL(tmpval, IEC61883_AM824_LABEL_MIDI_1X);
591                 *target_event = htonl(tmpval);
592    
593                 // debugOutput ( DEBUG_LEVEL_VERBOSE, "MIDI port %s, pos=%u, loc=%u, nevents=%u, dim=%d\n",
594                 //            p->getName().c_str(), position, location, nevents, m_dimension );
595                 // debugOutput ( DEBUG_LEVEL_VERBOSE, "base=%p, target=%p, value=%08X\n",
596                 //            data, target_event, tmpval );
597             } else {
598                 // can't send a byte, either because there is no byte,
599                 // or because this would exceed the maximum rate
600                 // FIXME: this can be ifdef optimized since it's a constant
601                 *target_event = htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA));
602             }
603             buffer+=8;
604         }
605     }
606 }
607
608 bool
609 AmdtpTransmitStreamProcessor::initPortCache() {
610     // make use of the fact that audio ports are the first ports in
611     // the cluster as per AMDTP. so we can sort the ports by position
612     // and have very efficient lookups:
613     // m_float_ports.at(i).buffer -> audio stream i buffer
614     // for midi ports we simply cache all port info since they are (usually) not
615     // that numerous
616     m_nb_audio_ports = 0;
617     m_audio_ports.clear();
618    
619     m_nb_midi_ports = 0;
620     m_midi_ports.clear();
621    
622     for(PortVectorIterator it = m_Ports.begin();
623         it != m_Ports.end();
624         ++it )
625     {
626         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
627         assert(pinfo); // this should not fail!!
628
629         switch( pinfo->getFormat() )
630         {
631             case AmdtpPortInfo::E_MBLA:
632                 m_nb_audio_ports++;
633                 break;
634             case AmdtpPortInfo::E_SPDIF: // still unimplemented
635                 break;
636             case AmdtpPortInfo::E_Midi:
637                 m_nb_midi_ports++;
638                 break;
639             default: // ignore
640                 break;
641         }
642     }
643
644     unsigned int idx;
645     for (idx = 0; idx < m_nb_audio_ports; idx++) {
646         for(PortVectorIterator it = m_Ports.begin();
647             it != m_Ports.end();
648             ++it )
649         {
650             AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
651             debugOutput(DEBUG_LEVEL_VERBOSE, "idx %u: looking at port %s at position %u\n",
652                                               idx, (*it)->getName().c_str(), pinfo->getPosition());
653             if(pinfo->getPosition() == idx) {
654                 struct _MBLA_port_cache p;
655                 p.port = dynamic_cast<AmdtpAudioPort *>(*it);
656                 if(p.port == NULL) {
657                     debugError("Port is not an AmdtpAudioPort!\n");
658                     return false;
659                 }
660                 p.buffer = NULL; // to be filled by updatePortCache
661                 #ifdef DEBUG
662                 p.buffer_size = (*it)->getBufferSize();
663                 #endif
664
665                 m_audio_ports.push_back(p);
666                 debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u\n",
667                                                  p.port->getName().c_str(), idx);
668                 goto next_index;
669             }
670         }
671         debugError("No MBLA port found for position %d\n", idx);
672         return false;
673 next_index:
674         continue;
675     }
676
677     for(PortVectorIterator it = m_Ports.begin();
678         it != m_Ports.end();
679         ++it )
680     {
681         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
682         debugOutput(DEBUG_LEVEL_VERBOSE, "idx %u: looking at port %s at position %u, location %u\n",
683                                         idx, (*it)->getName().c_str(), pinfo->getPosition(), pinfo->getLocation());
684         if ((*it)->getPortType() == Port::E_Midi) {
685             struct _MIDI_port_cache p;
686             p.port = dynamic_cast<AmdtpMidiPort *>(*it);
687             if(p.port == NULL) {
688                 debugError("Port is not an AmdtpMidiPort!\n");
689                 return false;
690             }
691             p.position = pinfo->getPosition();
692             p.location = pinfo->getLocation();
693             p.buffer = NULL; // to be filled by updatePortCache
694             #ifdef DEBUG
695             p.buffer_size = (*it)->getBufferSize();
696             #endif
697
698             m_midi_ports.push_back(p);
699             debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u, location %u\n",
700                                             p.port->getName().c_str(), p.position, p.location);
701         }
702     }
703
704     return true;
705 }
706
707 void
708 AmdtpTransmitStreamProcessor::updatePortCache() {
709     unsigned int idx;
710     for (idx = 0; idx < m_nb_audio_ports; idx++) {
711         struct _MBLA_port_cache& p = m_audio_ports.at(idx);
712         AmdtpAudioPort *port = p.port;
713         p.buffer = port->getBufferAddress();
714     }
715     for (idx = 0; idx < m_nb_midi_ports; idx++) {
716         struct _MIDI_port_cache& p = m_midi_ports.at(idx);
717         AmdtpMidiPort *port = p.port;
718         p.buffer = port->getBufferAddress();
719     }
720 }
721
722 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.