/[rdesktop]/sourceforge.net/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 /sourceforge.net/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 1298 by ossman_, Thu Oct 19 11:27:40 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;
51    struct audio_packet packet_queue[MAX_QUEUE];
52    
53    void (*wave_out_play) (void);
54    
55    static STREAM
56    rdpsnd_init_packet(uint16 type, uint16 size)
57    {
58            STREAM s;
59    
60            s = channel_init(rdpsnd_channel, size + 4);
61            out_uint16_le(s, type);
62            out_uint16_le(s, size);
63            return s;
64    }
65    
66    static void
67    rdpsnd_send(STREAM s)
68    {
69    #ifdef RDPSND_DEBUG
70            printf("RDPSND send:\n");
71            hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
72    #endif
73    
74            channel_send(s, rdpsnd_channel);
75    }
76    
77    void
78    rdpsnd_send_completion(uint16 tick, uint8 packet_index)
79    {
80            STREAM s;
81    
82            s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
83            out_uint16_le(s, tick);
84            out_uint8(s, packet_index);
85            out_uint8(s, 0);
86            s_mark_end(s);
87            rdpsnd_send(s);
88    }
89    
90    static void
91    rdpsnd_process_negotiate(STREAM in)
92    {
93            unsigned int in_format_count, i;
94            WAVEFORMATEX *format;
95            STREAM out;
96            BOOL device_available = False;
97            int readcnt;
98            int discardcnt;
99    
100            in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */
101            in_uint16_le(in, in_format_count);
102            in_uint8s(in, 4);       /* pad, status, pad */
103    
104            if (current_driver->wave_out_open())
105            {
106                    current_driver->wave_out_close();
107                    device_available = True;
108            }
109    
110            format_count = 0;
111            if (s_check_rem(in, 18 * in_format_count))
112            {
113                    for (i = 0; i < in_format_count; i++)
114                    {
115                            format = &formats[format_count];
116                            in_uint16_le(in, format->wFormatTag);
117                            in_uint16_le(in, format->nChannels);
118                            in_uint32_le(in, format->nSamplesPerSec);
119                            in_uint32_le(in, format->nAvgBytesPerSec);
120                            in_uint16_le(in, format->nBlockAlign);
121                            in_uint16_le(in, format->wBitsPerSample);
122                            in_uint16_le(in, format->cbSize);
123    
124                            /* read in the buffer of unknown use */
125                            readcnt = format->cbSize;
126                            discardcnt = 0;
127                            if (format->cbSize > MAX_CBSIZE)
128                            {
129                                    fprintf(stderr, "cbSize too large for buffer: %d\n",
130                                            format->cbSize);
131                                    readcnt = MAX_CBSIZE;
132                                    discardcnt = format->cbSize - MAX_CBSIZE;
133                            }
134                            in_uint8a(in, format->cb, readcnt);
135                            in_uint8s(in, discardcnt);
136    
137                            if (device_available && current_driver->wave_out_format_supported(format))
138                            {
139                                    format_count++;
140                                    if (format_count == MAX_FORMATS)
141                                            break;
142                            }
143                    }
144            }
145    
146            out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
147            out_uint32_le(out, 3);  /* flags */
148            out_uint32(out, 0xffffffff);    /* volume */
149            out_uint32(out, 0);     /* pitch */
150            out_uint16(out, 0);     /* UDP port */
151    
152            out_uint16_le(out, format_count);
153            out_uint8(out, 0x95);   /* pad? */
154            out_uint16_le(out, 2);  /* status */
155            out_uint8(out, 0x77);   /* pad? */
156    
157            for (i = 0; i < format_count; i++)
158            {
159                    format = &formats[i];
160                    out_uint16_le(out, format->wFormatTag);
161                    out_uint16_le(out, format->nChannels);
162                    out_uint32_le(out, format->nSamplesPerSec);
163                    out_uint32_le(out, format->nAvgBytesPerSec);
164                    out_uint16_le(out, format->nBlockAlign);
165                    out_uint16_le(out, format->wBitsPerSample);
166                    out_uint16(out, 0);     /* cbSize */
167            }
168    
169            s_mark_end(out);
170            rdpsnd_send(out);
171    }
172    
173    static void
174    rdpsnd_process_servertick(STREAM in)
175    {
176            uint16 tick1, tick2;
177            STREAM out;
178    
179            /* in_uint8s(in, 4); unknown */
180            in_uint16_le(in, tick1);
181            in_uint16_le(in, tick2);
182    
183            out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
184            out_uint16_le(out, tick1);
185            out_uint16_le(out, tick2);
186            s_mark_end(out);
187            rdpsnd_send(out);
188    }
189    
190  static void  static void
191  rdpsnd_process(STREAM s)  rdpsnd_process(STREAM s)
192  {  {
193          printf("rdpsnd_process\n");          uint8 type;
194            uint16 datalen;
195            uint32 volume;
196            static uint16 tick, format;
197            static uint8 packet_index;
198            static BOOL awaiting_data_packet;
199            static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
200    
201    #ifdef RDPSND_DEBUG
202            printf("RDPSND recv:\n");
203          hexdump(s->p, s->end - s->p);          hexdump(s->p, s->end - s->p);
204    #endif
205    
206            if (awaiting_data_packet)
207            {
208                    if (format >= MAX_FORMATS)
209                    {
210                            error("RDPSND: Invalid format index\n");
211                            return;
212                    }
213    
214                    if (!device_open || (format != current_format))
215                    {
216                            if (!device_open && !current_driver->wave_out_open())
217                            {
218                                    rdpsnd_send_completion(tick, packet_index);
219                                    return;
220                            }
221                            if (!current_driver->wave_out_set_format(&formats[format]))
222                            {
223                                    rdpsnd_send_completion(tick, packet_index);
224                                    current_driver->wave_out_close();
225                                    device_open = False;
226                                    return;
227                            }
228                            device_open = True;
229                            current_format = format;
230                    }
231    
232                    /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
233                    memcpy(s->data, missing_bytes, 4);
234    
235                    current_driver->
236                            wave_out_write(rdpsnd_dsp_process
237                                           (s, current_driver, &formats[current_format]), tick,
238                                           packet_index);
239                    awaiting_data_packet = False;
240                    return;
241            }
242    
243            in_uint8(s, type);
244            in_uint8s(s, 1);        /* unknown? */
245            in_uint16_le(s, datalen);
246    
247            switch (type)
248            {
249                    case RDPSND_WRITE:
250                            in_uint16_le(s, tick);
251                            in_uint16_le(s, format);
252                            in_uint8(s, packet_index);
253                            /* Here are our lost bytes, but why? */
254                            memcpy(missing_bytes, s->end - 4, 4);
255                            awaiting_data_packet = True;
256                            break;
257                    case RDPSND_CLOSE:
258                            current_driver->wave_out_close();
259                            device_open = False;
260                            break;
261                    case RDPSND_NEGOTIATE:
262                            rdpsnd_process_negotiate(s);
263                            break;
264                    case RDPSND_SERVERTICK:
265                            rdpsnd_process_servertick(s);
266                            break;
267                    case RDPSND_SET_VOLUME:
268                            in_uint32(s, volume);
269                            if (device_open)
270                            {
271                                    current_driver->wave_out_volume((volume & 0xffff),
272                                                                    (volume & 0xffff0000) >> 16);
273                            }
274                            break;
275                    default:
276                            unimpl("RDPSND packet type %d\n", type);
277                            break;
278            }
279    }
280    
281    static BOOL
282    rdpsnd_auto_open(void)
283    {
284            static BOOL failed = False;
285    
286            if (!failed)
287            {
288                    struct audio_driver *auto_driver = current_driver;
289    
290                    current_driver = drivers;
291                    while (current_driver != NULL)
292                    {
293                            DEBUG(("trying %s...\n", current_driver->name));
294                            if (current_driver->wave_out_open())
295                            {
296                                    DEBUG(("selected %s\n", current_driver->name));
297                                    return True;
298                            }
299                            g_dsp_fd = 0;
300                            current_driver = current_driver->next;
301                    }
302    
303                    warning("no working audio-driver found\n");
304                    failed = True;
305                    current_driver = auto_driver;
306            }
307    
308            return False;
309    }
310    
311    static void
312    rdpsnd_register_drivers(char *options)
313    {
314            struct audio_driver **reg;
315    
316            /* The order of registrations define the probe-order
317               when opening the device for the first time */
318            reg = &drivers;
319    #if defined(RDPSND_ALSA)
320            *reg = alsa_register(options);
321            assert(*reg);
322            reg = &((*reg)->next);
323    #endif
324    #if defined(RDPSND_SUN)
325            *reg = sun_register(options);
326            assert(*reg);
327            reg = &((*reg)->next);
328    #endif
329    #if defined(RDPSND_OSS)
330            *reg = oss_register(options);
331            assert(*reg);
332            reg = &((*reg)->next);
333    #endif
334    #if defined(RDPSND_SGI)
335            *reg = sgi_register(options);
336            assert(*reg);
337            reg = &((*reg)->next);
338    #endif
339    #if defined(RDPSND_LIBAO)
340            *reg = libao_register(options);
341        assert(*reg);
342            reg = &((*reg)->next);
343    #endif
344  }  }
345    
346  BOOL  BOOL
347  rdpsnd_init(void)  rdpsnd_init(char *optarg)
348  {  {
349            static struct audio_driver auto_driver;
350            struct audio_driver *pos;
351            char *driver = NULL, *options = NULL;
352    
353            drivers = NULL;
354    
355          rdpsnd_channel =          rdpsnd_channel =
356                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
357                                   rdpsnd_process);                                   rdpsnd_process);
358          return (rdpsnd_channel != NULL);  
359            if (rdpsnd_channel == NULL)
360            {
361                    error("channel_register\n");
362                    return False;
363            }
364    
365            if (optarg != NULL && strlen(optarg) > 0)
366            {
367                    driver = options = optarg;
368    
369                    while (*options != '\0' && *options != ':')
370                            options++;
371    
372                    if (*options == ':')
373                    {
374                            *options = '\0';
375                            options++;
376                    }
377    
378                    if (*options == '\0')
379                            options = NULL;
380            }
381    
382            rdpsnd_register_drivers(options);
383    
384            if (!driver)
385            {
386                    auto_driver.wave_out_open = &rdpsnd_auto_open;
387                    current_driver = &auto_driver;
388                    return True;
389            }
390    
391            pos = drivers;
392            while (pos != NULL)
393            {
394                    if (!strcmp(pos->name, driver))
395                    {
396                            DEBUG(("selected %s\n", pos->name));
397                            current_driver = pos;
398                            return True;
399                    }
400                    pos = pos->next;
401            }
402            return False;
403    }
404    
405    void
406    rdpsnd_show_help(void)
407    {
408            struct audio_driver *pos;
409    
410            rdpsnd_register_drivers(NULL);
411    
412            pos = drivers;
413            while (pos != NULL)
414            {
415                    fprintf(stderr, "                     %s:\t%s\n", pos->name, pos->description);
416                    pos = pos->next;
417            }
418    }
419    
420    void
421    rdpsnd_play(void)
422    {
423            current_driver->wave_out_play();
424    }
425    
426    inline void
427    rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
428    {
429            struct audio_packet *packet = &packet_queue[queue_hi];
430            unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
431    
432            if (next_hi == queue_lo)
433            {
434                    error("No space to queue audio packet\n");
435                    return;
436            }
437    
438            queue_hi = next_hi;
439    
440            packet->s = *s;
441            packet->tick = tick;
442            packet->index = index;
443    
444            if (!g_dsp_busy)
445                    current_driver->wave_out_play();
446    }
447    
448    inline struct audio_packet *
449    rdpsnd_queue_current_packet(void)
450    {
451            return &packet_queue[queue_lo];
452    }
453    
454    inline BOOL
455    rdpsnd_queue_empty(void)
456    {
457            return (queue_lo == queue_hi);
458    }
459    
460    inline void
461    rdpsnd_queue_init(void)
462    {
463            queue_lo = queue_hi = 0;
464    }
465    
466    inline void
467    rdpsnd_queue_next(void)
468    {
469            xfree(packet_queue[queue_lo].s.data);
470            queue_lo = (queue_lo + 1) % MAX_QUEUE;
471    }
472    
473    inline int
474    rdpsnd_queue_next_tick(void)
475    {
476            if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
477            {
478                    return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
479            }
480            else
481            {
482                    return (packet_queue[queue_lo].tick + 65535) % 65536;
483            }
484  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26