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

Legend:
Removed from v.432  
changed lines
  Added in v.1256

  ViewVC Help
Powered by ViewVC 1.1.26