/[rdesktop]/jpeg/rdesktop/trunk/rdpsnd.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /jpeg/rdesktop/trunk/rdpsnd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 435 by astrand, Wed Jul 9 09:18:20 2003 UTC revision 1302 by ossman_, Thu Oct 26 09:47:17 2006 UTC
# Line 1  Line 1 
1    /* -*- c-basic-offset: 8 -*-
2       rdesktop: A Remote Desktop Protocol client.
3       Sound Channel Process Functions
4       Copyright (C) Matthew Chapman 2003
5       Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6    
7       This program is free software; you can redistribute it and/or modify
8       it under the terms of the GNU General Public License as published by
9       the Free Software Foundation; either version 2 of the License, or
10       (at your option) any later version.
11    
12       This program is distributed in the hope that it will be useful,
13       but WITHOUT ANY WARRANTY; without even the implied warranty of
14       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15       GNU General Public License for more details.
16    
17       You should have received a copy of the GNU General Public License
18       along with this program; if not, write to the Free Software
19       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    */
21    
22    #include <assert.h>
23    
24  #include "rdesktop.h"  #include "rdesktop.h"
25    #include "rdpsnd.h"
26    #include "rdpsnd_dsp.h"
27    
28    #define RDPSND_CLOSE            1
29    #define RDPSND_WRITE            2
30    #define RDPSND_SET_VOLUME       3
31    #define RDPSND_UNKNOWN4         4
32    #define RDPSND_COMPLETION       5
33    #define RDPSND_SERVERTICK       6
34    #define RDPSND_NEGOTIATE        7
35    
36    #define MAX_FORMATS             10
37    #define MAX_QUEUE               10
38    
39    BOOL g_dsp_busy = False;
40    int g_dsp_fd;
41    
42  static VCHANNEL *rdpsnd_channel;  static VCHANNEL *rdpsnd_channel;
43    static struct audio_driver *drivers = NULL;
44    struct audio_driver *current_driver = NULL;
45    
46    static BOOL device_open;
47    static WAVEFORMATEX formats[MAX_FORMATS];
48    static unsigned int format_count;
49    static unsigned int current_format;
50    unsigned int queue_hi, queue_lo, queue_pending;
51    struct audio_packet packet_queue[MAX_QUEUE];
52    
53    void (*wave_out_play) (void);
54    
55    static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
56    static void rdpsnd_queue_init(void);
57    static void rdpsnd_queue_complete_pending(void);
58    static long rdpsnd_queue_next_completion(void);
59    
60    static STREAM
61    rdpsnd_init_packet(uint16 type, uint16 size)
62    {
63            STREAM s;
64    
65            s = channel_init(rdpsnd_channel, size + 4);
66            out_uint16_le(s, type);
67            out_uint16_le(s, size);
68            return s;
69    }
70    
71    static void
72    rdpsnd_send(STREAM s)
73    {
74    #ifdef RDPSND_DEBUG
75            printf("RDPSND send:\n");
76            hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
77    #endif
78    
79            channel_send(s, rdpsnd_channel);
80    }
81    
82    static void
83    rdpsnd_send_completion(uint16 tick, uint8 packet_index)
84    {
85            STREAM s;
86    
87            s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
88            out_uint16_le(s, tick);
89            out_uint8(s, packet_index);
90            out_uint8(s, 0);
91            s_mark_end(s);
92            rdpsnd_send(s);
93    }
94    
95    static void
96    rdpsnd_process_negotiate(STREAM in)
97    {
98            unsigned int in_format_count, i;
99            WAVEFORMATEX *format;
100            STREAM out;
101            BOOL device_available = False;
102            int readcnt;
103            int discardcnt;
104    
105            in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */
106            in_uint16_le(in, in_format_count);
107            in_uint8s(in, 4);       /* pad, status, pad */
108    
109            if (current_driver->wave_out_open())
110            {
111                    current_driver->wave_out_close();
112                    device_available = True;
113            }
114    
115            format_count = 0;
116            if (s_check_rem(in, 18 * in_format_count))
117            {
118                    for (i = 0; i < in_format_count; i++)
119                    {
120                            format = &formats[format_count];
121                            in_uint16_le(in, format->wFormatTag);
122                            in_uint16_le(in, format->nChannels);
123                            in_uint32_le(in, format->nSamplesPerSec);
124                            in_uint32_le(in, format->nAvgBytesPerSec);
125                            in_uint16_le(in, format->nBlockAlign);
126                            in_uint16_le(in, format->wBitsPerSample);
127                            in_uint16_le(in, format->cbSize);
128    
129                            /* read in the buffer of unknown use */
130                            readcnt = format->cbSize;
131                            discardcnt = 0;
132                            if (format->cbSize > MAX_CBSIZE)
133                            {
134                                    fprintf(stderr, "cbSize too large for buffer: %d\n",
135                                            format->cbSize);
136                                    readcnt = MAX_CBSIZE;
137                                    discardcnt = format->cbSize - MAX_CBSIZE;
138                            }
139                            in_uint8a(in, format->cb, readcnt);
140                            in_uint8s(in, discardcnt);
141    
142                            if (device_available && current_driver->wave_out_format_supported(format))
143                            {
144                                    format_count++;
145                                    if (format_count == MAX_FORMATS)
146                                            break;
147                            }
148                    }
149            }
150    
151            out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
152            out_uint32_le(out, 3);  /* flags */
153            out_uint32(out, 0xffffffff);    /* volume */
154            out_uint32(out, 0);     /* pitch */
155            out_uint16(out, 0);     /* UDP port */
156    
157            out_uint16_le(out, format_count);
158            out_uint8(out, 0x95);   /* pad? */
159            out_uint16_le(out, 2);  /* status */
160            out_uint8(out, 0x77);   /* pad? */
161    
162            for (i = 0; i < format_count; i++)
163            {
164                    format = &formats[i];
165                    out_uint16_le(out, format->wFormatTag);
166                    out_uint16_le(out, format->nChannels);
167                    out_uint32_le(out, format->nSamplesPerSec);
168                    out_uint32_le(out, format->nAvgBytesPerSec);
169                    out_uint16_le(out, format->nBlockAlign);
170                    out_uint16_le(out, format->wBitsPerSample);
171                    out_uint16(out, 0);     /* cbSize */
172            }
173    
174            s_mark_end(out);
175            rdpsnd_send(out);
176    }
177    
178    static void
179    rdpsnd_process_servertick(STREAM in)
180    {
181            uint16 tick1, tick2;
182            STREAM out;
183    
184            /* in_uint8s(in, 4); unknown */
185            in_uint16_le(in, tick1);
186            in_uint16_le(in, tick2);
187    
188            out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
189            out_uint16_le(out, tick1);
190            out_uint16_le(out, tick2);
191            s_mark_end(out);
192            rdpsnd_send(out);
193    }
194    
195  static void  static void
196  rdpsnd_process(STREAM s)  rdpsnd_process(STREAM s)
197  {  {
198          printf("rdpsnd_process\n");          uint8 type;
199            uint16 datalen;
200            uint32 volume;
201            static uint16 tick, format;
202            static uint8 packet_index;
203            static BOOL awaiting_data_packet;
204            static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
205    
206    #ifdef RDPSND_DEBUG
207            printf("RDPSND recv:\n");
208          hexdump(s->p, s->end - s->p);          hexdump(s->p, s->end - s->p);
209    #endif
210    
211            if (awaiting_data_packet)
212            {
213                    if (format >= MAX_FORMATS)
214                    {
215                            error("RDPSND: Invalid format index\n");
216                            return;
217                    }
218    
219                    if (!device_open || (format != current_format))
220                    {
221                            if (!device_open && !current_driver->wave_out_open())
222                            {
223                                    rdpsnd_send_completion(tick, packet_index);
224                                    return;
225                            }
226                            if (!current_driver->wave_out_set_format(&formats[format]))
227                            {
228                                    rdpsnd_send_completion(tick, packet_index);
229                                    current_driver->wave_out_close();
230                                    device_open = False;
231                                    return;
232                            }
233                            device_open = True;
234                            current_format = format;
235                    }
236    
237                    /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
238                    memcpy(s->data, missing_bytes, 4);
239    
240                    rdpsnd_queue_write(rdpsnd_dsp_process
241                                       (s, current_driver, &formats[current_format]), tick,
242                                       packet_index);
243                    awaiting_data_packet = False;
244                    return;
245            }
246    
247            in_uint8(s, type);
248            in_uint8s(s, 1);        /* unknown? */
249            in_uint16_le(s, datalen);
250    
251            switch (type)
252            {
253                    case RDPSND_WRITE:
254                            in_uint16_le(s, tick);
255                            in_uint16_le(s, format);
256                            in_uint8(s, packet_index);
257                            /* Here are our lost bytes, but why? */
258                            memcpy(missing_bytes, s->end - 4, 4);
259                            awaiting_data_packet = True;
260                            break;
261                    case RDPSND_CLOSE:
262                            current_driver->wave_out_close();
263                            device_open = False;
264                            break;
265                    case RDPSND_NEGOTIATE:
266                            rdpsnd_process_negotiate(s);
267                            break;
268                    case RDPSND_SERVERTICK:
269                            rdpsnd_process_servertick(s);
270                            break;
271                    case RDPSND_SET_VOLUME:
272                            in_uint32(s, volume);
273                            if (device_open)
274                            {
275                                    current_driver->wave_out_volume((volume & 0xffff),
276                                                                    (volume & 0xffff0000) >> 16);
277                            }
278                            break;
279                    default:
280                            unimpl("RDPSND packet type %d\n", type);
281                            break;
282            }
283    }
284    
285    static BOOL
286    rdpsnd_auto_open(void)
287    {
288            static BOOL failed = False;
289    
290            if (!failed)
291            {
292                    struct audio_driver *auto_driver = current_driver;
293    
294                    current_driver = drivers;
295                    while (current_driver != NULL)
296                    {
297                            DEBUG(("trying %s...\n", current_driver->name));
298                            if (current_driver->wave_out_open())
299                            {
300                                    DEBUG(("selected %s\n", current_driver->name));
301                                    return True;
302                            }
303                            g_dsp_fd = 0;
304                            current_driver = current_driver->next;
305                    }
306    
307                    warning("no working audio-driver found\n");
308                    failed = True;
309                    current_driver = auto_driver;
310            }
311    
312            return False;
313    }
314    
315    static void
316    rdpsnd_register_drivers(char *options)
317    {
318            struct audio_driver **reg;
319    
320            /* The order of registrations define the probe-order
321               when opening the device for the first time */
322            reg = &drivers;
323    #if defined(RDPSND_ALSA)
324            *reg = alsa_register(options);
325            assert(*reg);
326            reg = &((*reg)->next);
327    #endif
328    #if defined(RDPSND_SUN)
329            *reg = sun_register(options);
330            assert(*reg);
331            reg = &((*reg)->next);
332    #endif
333    #if defined(RDPSND_OSS)
334            *reg = oss_register(options);
335            assert(*reg);
336            reg = &((*reg)->next);
337    #endif
338    #if defined(RDPSND_SGI)
339            *reg = sgi_register(options);
340            assert(*reg);
341            reg = &((*reg)->next);
342    #endif
343    #if defined(RDPSND_LIBAO)
344            *reg = libao_register(options);
345            assert(*reg);
346            reg = &((*reg)->next);
347    #endif
348  }  }
349    
350  BOOL  BOOL
351  rdpsnd_init(void)  rdpsnd_init(char *optarg)
352  {  {
353            static struct audio_driver auto_driver;
354            struct audio_driver *pos;
355            char *driver = NULL, *options = NULL;
356    
357            drivers = NULL;
358    
359          rdpsnd_channel =          rdpsnd_channel =
360                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
361                                   rdpsnd_process);                                   rdpsnd_process);
362          return (rdpsnd_channel != NULL);  
363            if (rdpsnd_channel == NULL)
364            {
365                    error("channel_register\n");
366                    return False;
367            }
368    
369            rdpsnd_queue_init();
370    
371            if (optarg != NULL && strlen(optarg) > 0)
372            {
373                    driver = options = optarg;
374    
375                    while (*options != '\0' && *options != ':')
376                            options++;
377    
378                    if (*options == ':')
379                    {
380                            *options = '\0';
381                            options++;
382                    }
383    
384                    if (*options == '\0')
385                            options = NULL;
386            }
387    
388            rdpsnd_register_drivers(options);
389    
390            if (!driver)
391            {
392                    auto_driver.wave_out_open = &rdpsnd_auto_open;
393                    current_driver = &auto_driver;
394                    return True;
395            }
396    
397            pos = drivers;
398            while (pos != NULL)
399            {
400                    if (!strcmp(pos->name, driver))
401                    {
402                            DEBUG(("selected %s\n", pos->name));
403                            current_driver = pos;
404                            return True;
405                    }
406                    pos = pos->next;
407            }
408            return False;
409    }
410    
411    void
412    rdpsnd_show_help(void)
413    {
414            struct audio_driver *pos;
415    
416            rdpsnd_register_drivers(NULL);
417    
418            pos = drivers;
419            while (pos != NULL)
420            {
421                    fprintf(stderr, "                     %s:\t%s\n", pos->name, pos->description);
422                    pos = pos->next;
423            }
424    }
425    
426    void
427    rdpsnd_play(void)
428    {
429            current_driver->wave_out_play();
430    }
431    
432    void
433    rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
434    {
435            long next_pending;
436    
437            if (g_dsp_busy)
438            {
439                    FD_SET(g_dsp_fd, wfds);
440                    *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
441            }
442    
443            next_pending = rdpsnd_queue_next_completion();
444            if (next_pending >= 0)
445            {
446                    long cur_timeout;
447    
448                    cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
449                    if (cur_timeout > next_pending)
450                    {
451                            tv->tv_sec = next_pending / 1000000;
452                            tv->tv_usec = next_pending % 1000000;
453                    }
454            }
455    }
456    
457    void
458    rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
459    {
460            rdpsnd_queue_complete_pending();
461    
462            if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
463                    rdpsnd_play();
464    }
465    
466    static void
467    rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
468    {
469            struct audio_packet *packet = &packet_queue[queue_hi];
470            unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
471    
472            if (next_hi == queue_pending)
473            {
474                    error("No space to queue audio packet\n");
475                    return;
476            }
477    
478            queue_hi = next_hi;
479    
480            packet->s = *s;
481            packet->tick = tick;
482            packet->index = index;
483    
484            gettimeofday(&packet->arrive_tv, NULL);
485    
486            if (!g_dsp_busy)
487                    current_driver->wave_out_play();
488    }
489    
490    struct audio_packet *
491    rdpsnd_queue_current_packet(void)
492    {
493            return &packet_queue[queue_lo];
494    }
495    
496    BOOL
497    rdpsnd_queue_empty(void)
498    {
499            return (queue_lo == queue_hi);
500    }
501    
502    static void
503    rdpsnd_queue_init(void)
504    {
505            queue_pending = queue_lo = queue_hi = 0;
506    }
507    
508    void
509    rdpsnd_queue_next(unsigned long completed_in_us)
510    {
511            struct audio_packet *packet;
512    
513            assert(!rdpsnd_queue_empty());
514    
515            packet = &packet_queue[queue_lo];
516    
517            gettimeofday(&packet->completion_tv, NULL);
518    
519            packet->completion_tv.tv_usec += completed_in_us;
520            packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
521            packet->completion_tv.tv_usec %= 1000000;
522    
523            queue_lo = (queue_lo + 1) % MAX_QUEUE;
524    
525            rdpsnd_queue_complete_pending();
526    }
527    
528    int
529    rdpsnd_queue_next_tick(void)
530    {
531            if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
532            {
533                    return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
534            }
535            else
536            {
537                    return (packet_queue[queue_lo].tick + 65535) % 65536;
538            }
539    }
540    
541    static void
542    rdpsnd_queue_complete_pending(void)
543    {
544            struct timeval now;
545            long elapsed;
546            struct audio_packet *packet;
547    
548            gettimeofday(&now, NULL);
549    
550            while (queue_pending != queue_lo)
551            {
552                    packet = &packet_queue[queue_pending];
553    
554                    if (now.tv_sec < packet->completion_tv.tv_sec)
555                            break;
556    
557                    if ((now.tv_sec == packet->completion_tv.tv_sec) &&
558                        (now.tv_usec < packet->completion_tv.tv_usec))
559                            break;
560    
561                    elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
562                            (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
563    
564                    xfree(packet->s.data);
565                    rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
566                    queue_pending = (queue_pending + 1) % MAX_QUEUE;
567            }
568    }
569    
570    static long
571    rdpsnd_queue_next_completion(void)
572    {
573            struct audio_packet *packet;
574            long remaining;
575            struct timeval now;
576    
577            if (queue_pending == queue_lo)
578                    return -1;
579    
580            gettimeofday(&now, NULL);
581    
582            packet = &packet_queue[queue_pending];
583    
584            remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
585                    (packet->completion_tv.tv_usec - now.tv_usec);
586    
587            if (remaining < 0)
588                    return 0;
589    
590            return remaining;
591  }  }

Legend:
Removed from v.435  
changed lines
  Added in v.1302

  ViewVC Help
Powered by ViewVC 1.1.26