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

Revision 829, 27.6 kB (checked in by ppalmers, 16 years ago)

some caching and bugfixes

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