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

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

  ViewVC Help
Powered by ViewVC 1.1.26