~ubuntu-branches/ubuntu/wily/freerdp/wily-proposed

« back to all changes in this revision

Viewing changes to channels/drdynvc/audin/audin_main.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
   Copyright (c) 2010 Vic Lee
3
 
 
4
 
   Permission is hereby granted, free of charge, to any person obtaining a
5
 
   copy of this software and associated documentation files (the "Software"),
6
 
   to deal in the Software without restriction, including without limitation
7
 
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 
   and/or sell copies of the Software, and to permit persons to whom the
9
 
   Software is furnished to do so, subject to the following conditions:
10
 
 
11
 
   The above copyright notice and this permission notice shall be included
12
 
   in all copies or substantial portions of the Software.
13
 
 
14
 
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
 
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
 
   DEALINGS IN THE SOFTWARE.
21
 
 
22
 
*/
 
1
/**
 
2
 * FreeRDP: A Remote Desktop Protocol client.
 
3
 * Audio Input Redirection Virtual Channel
 
4
 *
 
5
 * Copyright 2010-2011 Vic Lee
 
6
 *
 
7
 * Licensed under the Apache License, Version 2.0 (the "License");
 
8
 * you may not use this file except in compliance with the License.
 
9
 * You may obtain a copy of the License at
 
10
 *
 
11
 *     http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
13
 * Unless required by applicable law or agreed to in writing, software
 
14
 * distributed under the License is distributed on an "AS IS" BASIS,
 
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
16
 * See the License for the specific language governing permissions and
 
17
 * limitations under the License.
 
18
 */
23
19
 
24
20
#include <stdio.h>
25
21
#include <stdlib.h>
26
22
#include <string.h>
27
 
#include "drdynvc_types.h"
 
23
#include <freerdp/utils/memory.h>
 
24
#include <freerdp/utils/stream.h>
 
25
#include <freerdp/utils/load_plugin.h>
 
26
 
28
27
#include "audin_main.h"
29
28
 
30
29
#define MSG_SNDIN_VERSION       0x01
40
39
{
41
40
        IWTSListenerCallback iface;
42
41
 
43
 
        IWTSPlugin * plugin;
44
 
        IWTSVirtualChannelManager * channel_mgr;
 
42
        IWTSPlugin* plugin;
 
43
        IWTSVirtualChannelManager* channel_mgr;
45
44
};
46
45
 
47
46
typedef struct _AUDIN_CHANNEL_CALLBACK AUDIN_CHANNEL_CALLBACK;
49
48
{
50
49
        IWTSVirtualChannelCallback iface;
51
50
 
52
 
        IWTSPlugin * plugin;
53
 
        IWTSVirtualChannelManager * channel_mgr;
54
 
        IWTSVirtualChannel * channel;
 
51
        IWTSPlugin* plugin;
 
52
        IWTSVirtualChannelManager* channel_mgr;
 
53
        IWTSVirtualChannel* channel;
55
54
 
56
 
        /* Hardware-specific data */
57
 
        void * device_data;
58
 
        /* The supported format list sent back to the server, which needs to
59
 
           be stored as reference when the server sends the format index in
60
 
           Open PDU and Format Change PDU */
61
 
        char ** formats_data;
 
55
        /**
 
56
         * The supported format list sent back to the server, which needs to
 
57
         * be stored as reference when the server sends the format index in
 
58
         * Open PDU and Format Change PDU
 
59
         */
 
60
        audinFormat* formats;
62
61
        int formats_count;
63
62
};
64
63
 
67
66
{
68
67
        IWTSPlugin iface;
69
68
 
70
 
        AUDIN_LISTENER_CALLBACK * listener_callback;
 
69
        AUDIN_LISTENER_CALLBACK* listener_callback;
 
70
 
 
71
        /* Parsed plugin data */
 
72
        uint16 fixed_format;
 
73
        uint16 fixed_channel;   
 
74
        uint32 fixed_rate;
 
75
 
 
76
        /* Device interface */
 
77
        IAudinDevice* device;
71
78
};
72
79
 
73
 
static int
74
 
audin_process_version(IWTSVirtualChannelCallback * pChannelCallback,
75
 
        char * data, uint32 data_size)
 
80
static int audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s)
76
81
{
77
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) pChannelCallback;
 
82
        int error;
 
83
        STREAM* out;
78
84
        uint32 Version;
79
 
        uint32 out_size;
80
 
        char * out_data;
81
 
        int error;
82
 
 
83
 
        Version = GET_UINT32(data, 0);
84
 
        LLOGLN(10, ("audin_process_version: Version=%d", Version));
85
 
 
86
 
        out_size = 5;
87
 
        out_data = (char *) malloc(out_size);
88
 
        memset(out_data, 0, out_size);
89
 
        SET_UINT8(out_data, 0, MSG_SNDIN_VERSION);
90
 
        SET_UINT32(out_data, 1, Version);
91
 
        error = callback->channel->Write(callback->channel, out_size, out_data, NULL);
92
 
        free(out_data);
 
85
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
 
86
 
 
87
        stream_read_uint32(s, Version);
 
88
 
 
89
        DEBUG_DVC("Version=%d", Version);
 
90
 
 
91
        out = stream_new(5);
 
92
        stream_write_uint8(out, MSG_SNDIN_VERSION);
 
93
        stream_write_uint32(out, Version);
 
94
        error = callback->channel->Write(callback->channel, stream_get_length(s), stream_get_head(s), NULL);
 
95
        stream_free(out);
93
96
 
94
97
        return error;
95
98
}
96
99
 
97
 
static int
98
 
audin_send_incoming_data_pdu(IWTSVirtualChannelCallback * pChannelCallback)
 
100
static int audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCallback)
99
101
{
100
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) pChannelCallback;
101
 
        char out_data[1];
 
102
        uint8 out_data[1];
 
103
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
102
104
 
103
 
        SET_UINT8(out_data, 0, MSG_SNDIN_DATA_INCOMING);
 
105
        out_data[0] = MSG_SNDIN_DATA_INCOMING;
104
106
        return callback->channel->Write(callback->channel, 1, out_data, NULL);
105
107
}
106
108
 
107
 
static int
108
 
audin_process_formats(IWTSVirtualChannelCallback * pChannelCallback,
109
 
        char * data, uint32 data_size)
 
109
static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s)
110
110
{
111
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) pChannelCallback;
 
111
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
 
112
        AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
 
113
        uint32 i;
 
114
        uint8* fm;
 
115
        int error;
 
116
        STREAM* out;
112
117
        uint32 NumFormats;
113
 
        uint32 i;
114
 
        int size;
115
 
        int out_size;
116
 
        char * ldata;
117
 
        char * out_data;
118
 
        char * lout_formats;
119
 
        int out_format_count;
120
 
        int error;
 
118
        audinFormat format;
 
119
        uint32 cbSizeFormatsPacket;
121
120
 
122
 
        NumFormats = GET_UINT32(data, 0);
 
121
        stream_read_uint32(s, NumFormats);
 
122
        DEBUG_DVC("NumFormats %d", NumFormats);
123
123
        if ((NumFormats < 1) || (NumFormats > 1000))
124
124
        {
125
 
                LLOGLN(0, ("audin_process_formats: bad NumFormats %d",
126
 
                        NumFormats));
 
125
                DEBUG_WARN("bad NumFormats %d", NumFormats);
127
126
                return 1;
128
127
        }
129
 
        /* Ignore cbSizeFormatsPacket */
130
 
 
131
 
        size = sizeof(char *) * (NumFormats + 1);
132
 
        callback->formats_data = (char **) malloc(size);
133
 
        memset(callback->formats_data, 0, size);
134
 
 
135
 
        out_size = data_size + 1;
136
 
        out_data = (char *) malloc(out_size);
137
 
        memset(out_data, 0, out_size);
138
 
 
139
 
        lout_formats = out_data + 9;
140
 
        /* remainder is sndFormats (variable) */
141
 
        ldata = data + 8;
142
 
        out_format_count = 0;
 
128
        stream_seek_uint32(s); /* cbSizeFormatsPacket */
 
129
 
 
130
        callback->formats = (audinFormat*) xzalloc(NumFormats * sizeof(audinFormat));
 
131
 
 
132
        out = stream_new(9);
 
133
        stream_seek(out, 9);
 
134
 
 
135
        /* SoundFormats (variable) */
143
136
        for (i = 0; i < NumFormats; i++)
144
137
        {
145
 
                size = 18 + GET_UINT16(ldata, 16);
146
 
                if (wave_in_format_supported(callback->device_data, ldata, size))
 
138
                stream_get_mark(s, fm);
 
139
                stream_read_uint16(s, format.wFormatTag);
 
140
                stream_read_uint16(s, format.nChannels);
 
141
                stream_read_uint32(s, format.nSamplesPerSec);
 
142
                stream_seek_uint32(s); /* nAvgBytesPerSec */
 
143
                stream_read_uint16(s, format.nBlockAlign);
 
144
                stream_read_uint16(s, format.wBitsPerSample);
 
145
                stream_read_uint16(s, format.cbSize);
 
146
                format.data = stream_get_tail(s);
 
147
                stream_seek(s, format.cbSize);
 
148
                
 
149
                DEBUG_DVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d "
 
150
                        "nBlockAlign=%d wBitsPerSample=%d cbSize=%d",
 
151
                        format.wFormatTag, format.nChannels, format.nSamplesPerSec,
 
152
                        format.nBlockAlign, format.wBitsPerSample, format.cbSize);
 
153
 
 
154
                if (audin->fixed_format > 0 && audin->fixed_format != format.wFormatTag)
 
155
                        continue;
 
156
                if (audin->fixed_channel > 0 && audin->fixed_channel != format.nChannels)
 
157
                        continue;
 
158
                if (audin->fixed_rate > 0 && audin->fixed_rate != format.nSamplesPerSec)
 
159
                        continue;
 
160
                if (audin->device && audin->device->FormatSupported(audin->device, &format))
147
161
                {
 
162
                        DEBUG_DVC("format ok");
 
163
 
148
164
                        /* Store the agreed format in the corresponding index */
149
 
                        callback->formats_data[out_format_count] = (char *) malloc(size);
150
 
                        memcpy(callback->formats_data[out_format_count], ldata, size);
 
165
                        callback->formats[callback->formats_count++] = format;
151
166
                        /* Put the format to output buffer */
152
 
                        memcpy(lout_formats, ldata, size);
153
 
                        lout_formats += size;
154
 
                        out_format_count++;
 
167
                        stream_check_size(out, 18 + format.cbSize);
 
168
                        stream_write(out, fm, 18 + format.cbSize);
155
169
                }
156
 
                ldata += size;
157
170
        }
158
 
        callback->formats_count = out_format_count;
159
171
 
160
172
        audin_send_incoming_data_pdu(pChannelCallback);
161
173
 
162
 
        /* cbSizeFormatsPacket: the size of the entire PDU minus the size of ExtraData */
163
 
        size = lout_formats - out_data; 
164
 
        SET_UINT8(out_data, 0, MSG_SNDIN_FORMATS);
165
 
        SET_UINT32(out_data, 1, out_format_count);
166
 
        SET_UINT32(out_data, 5, size);
167
 
        error = callback->channel->Write(callback->channel, size, out_data, NULL);
168
 
        free(out_data);
169
 
 
170
 
        return error;
171
 
}
172
 
 
173
 
static int
174
 
audin_send_format_change_pdu(IWTSVirtualChannelCallback * pChannelCallback, uint32 NewFormat)
175
 
{
176
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) pChannelCallback;
177
 
        char out_data[5];
178
 
 
179
 
        SET_UINT8(out_data, 0, MSG_SNDIN_FORMATCHANGE);
180
 
        SET_UINT32(out_data, 1, NewFormat);
181
 
        return callback->channel->Write(callback->channel, 5, out_data, NULL);
182
 
}
183
 
 
184
 
static int
185
 
audin_send_open_reply_pdu(IWTSVirtualChannelCallback * pChannelCallback, uint32 Result)
186
 
{
187
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) pChannelCallback;
188
 
        char out_data[5];
189
 
 
190
 
        SET_UINT8(out_data, 0, MSG_SNDIN_OPEN_REPLY);
191
 
        SET_UINT32(out_data, 1, Result);
192
 
        return callback->channel->Write(callback->channel, 5, out_data, NULL);
193
 
}
194
 
 
195
 
static int
196
 
audin_receive_wave_data(char * wave_data, int size, void * user_data)
197
 
{
198
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) user_data;
199
 
        int out_size;
200
 
        char * out_data;
201
 
        int error;
202
 
 
203
 
        error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback *) callback);
 
174
        cbSizeFormatsPacket = stream_get_pos(out);
 
175
        stream_set_pos(out, 0);
 
176
 
 
177
        stream_write_uint8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */
 
178
        stream_write_uint32(out, callback->formats_count); /* NumFormats (4 bytes) */
 
179
        stream_write_uint32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */
 
180
 
 
181
        error = callback->channel->Write(callback->channel, cbSizeFormatsPacket, stream_get_head(out), NULL);
 
182
        stream_free(out);
 
183
 
 
184
        return error;
 
185
}
 
186
 
 
187
static int audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback, uint32 NewFormat)
 
188
{
 
189
        int error;
 
190
        STREAM* out;
 
191
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
 
192
 
 
193
        out = stream_new(5);
 
194
        stream_write_uint8(out, MSG_SNDIN_FORMATCHANGE);
 
195
        stream_write_uint32(out, NewFormat);
 
196
        error = callback->channel->Write(callback->channel, 5, stream_get_head(out), NULL);
 
197
        stream_free(out);
 
198
 
 
199
        return error;
 
200
}
 
201
 
 
202
static int audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallback, uint32 Result)
 
203
{
 
204
        int error;
 
205
        STREAM* out;
 
206
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
 
207
 
 
208
        out = stream_new(5);
 
209
        stream_write_uint8(out, MSG_SNDIN_OPEN_REPLY);
 
210
        stream_write_uint32(out, Result);
 
211
        error = callback->channel->Write(callback->channel, 5, stream_get_head(out), NULL);
 
212
        stream_free(out);
 
213
 
 
214
        return error;
 
215
}
 
216
 
 
217
static boolean audin_receive_wave_data(uint8* data, int size, void* user_data)
 
218
{
 
219
        int error;
 
220
        STREAM* out;
 
221
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) user_data;
 
222
 
 
223
        error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback);
204
224
        if (error != 0)
205
 
                return error;
206
 
 
207
 
        out_size = size + 1;
208
 
        out_data = (char *) malloc(out_size);
209
 
        SET_UINT8(out_data, 0, MSG_SNDIN_DATA);
210
 
        memcpy(out_data + 1, wave_data, size);
211
 
        error = callback->channel->Write(callback->channel, out_size, out_data, NULL);
212
 
        free(out_data);
213
 
        return error;
 
225
                return false;
 
226
 
 
227
        out = stream_new(size + 1);
 
228
        stream_write_uint8(out, MSG_SNDIN_DATA);
 
229
        stream_write(out, data, size);
 
230
        error = callback->channel->Write(callback->channel, stream_get_length(out), stream_get_head(out), NULL);
 
231
        stream_free(out);
 
232
 
 
233
        return (error == 0 ? true : false);
214
234
}
215
235
 
216
 
static int
217
 
audin_process_open(IWTSVirtualChannelCallback * pChannelCallback,
218
 
        char * data, uint32 data_size)
 
236
static int audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s)
219
237
{
220
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) pChannelCallback;
 
238
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
 
239
        AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
 
240
        audinFormat* format;
 
241
        uint32 initialFormat;
221
242
        uint32 FramesPerPacket;
222
 
        uint32 initialFormat;
223
 
        char * format;
224
 
        int size;
225
 
        int result;
226
 
 
227
 
        FramesPerPacket = GET_UINT32(data, 0);
228
 
        initialFormat = GET_UINT32(data, 4);
229
 
        LLOGLN(10, ("audin_process_open: FramesPerPacket=%d initialFormat=%d",
230
 
                FramesPerPacket, initialFormat));
 
243
 
 
244
        stream_read_uint32(s, FramesPerPacket);
 
245
        stream_read_uint32(s, initialFormat);
 
246
 
 
247
        DEBUG_DVC("FramesPerPacket=%d initialFormat=%d",
 
248
                FramesPerPacket, initialFormat);
 
249
 
231
250
        if (initialFormat >= callback->formats_count)
232
251
        {
233
 
                LLOGLN(0, ("audin_process_open: invalid format index %d (total %d)",
234
 
                        initialFormat, callback->formats_count));
 
252
                DEBUG_WARN("invalid format index %d (total %d)",
 
253
                        initialFormat, callback->formats_count);
235
254
                return 1;
236
255
        }
237
 
        format = callback->formats_data[initialFormat];
238
 
        size = 18 + GET_UINT16(format, 16);
239
 
        wave_in_set_format(callback->device_data, FramesPerPacket, format, size);
240
 
        result = wave_in_open(callback->device_data,
241
 
                audin_receive_wave_data, callback);
242
256
 
243
 
        if (result == 0)
 
257
        format = &callback->formats[initialFormat];
 
258
        if (audin->device)
244
259
        {
245
 
                audin_send_format_change_pdu(pChannelCallback, initialFormat);
 
260
                IFCALL(audin->device->SetFormat, audin->device, format, FramesPerPacket);
 
261
                IFCALL(audin->device->Open, audin->device, audin_receive_wave_data, callback);
246
262
        }
247
 
        audin_send_open_reply_pdu(pChannelCallback, result);
 
263
 
 
264
        audin_send_format_change_pdu(pChannelCallback, initialFormat);
 
265
        audin_send_open_reply_pdu(pChannelCallback, 0);
248
266
 
249
267
        return 0;
250
268
}
251
269
 
252
 
static int
253
 
audin_process_format_change(IWTSVirtualChannelCallback * pChannelCallback,
254
 
        char * data, uint32 data_size)
 
270
static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s)
255
271
{
256
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) pChannelCallback;
 
272
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
 
273
        AUDIN_PLUGIN * audin = (AUDIN_PLUGIN *) callback->plugin;
257
274
        uint32 NewFormat;
258
 
        char * format;
259
 
        int size;
260
 
 
261
 
        NewFormat = GET_UINT32(data, 0);
262
 
        LLOGLN(10, ("audin_process_format_change: NewFormat=%d",
263
 
                NewFormat));
 
275
        audinFormat* format;
 
276
 
 
277
        stream_read_uint32(s, NewFormat);
 
278
 
 
279
        DEBUG_DVC("NewFormat=%d", NewFormat);
 
280
 
264
281
        if (NewFormat >= callback->formats_count)
265
282
        {
266
 
                LLOGLN(0, ("audin_process_format_change: invalid format index %d (total %d)",
267
 
                        NewFormat, callback->formats_count));
 
283
                DEBUG_WARN("invalid format index %d (total %d)",
 
284
                        NewFormat, callback->formats_count);
268
285
                return 1;
269
286
        }
270
287
 
271
 
        wave_in_close(callback->device_data);
272
 
 
273
 
        format = callback->formats_data[NewFormat];
274
 
        size = 18 + GET_UINT16(format, 16);
275
 
        wave_in_set_format(callback->device_data, 0, format, size);
 
288
        format = &callback->formats[NewFormat];
 
289
 
 
290
        if (audin->device)
 
291
        {
 
292
                IFCALL(audin->device->Close, audin->device);
 
293
                IFCALL(audin->device->SetFormat, audin->device, format, 0);
 
294
                IFCALL(audin->device->Open, audin->device, audin_receive_wave_data, callback);
 
295
        }
 
296
 
276
297
        audin_send_format_change_pdu(pChannelCallback, NewFormat);
277
298
 
278
 
        wave_in_open(callback->device_data,
279
 
                audin_receive_wave_data, callback);
280
 
 
281
299
        return 0;
282
300
}
283
301
 
284
 
static int
285
 
audin_on_data_received(IWTSVirtualChannelCallback * pChannelCallback,
 
302
static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
286
303
        uint32 cbSize,
287
 
        char * pBuffer)
 
304
        uint8* pBuffer)
288
305
{
 
306
        int error;
 
307
        STREAM* s;
289
308
        uint8 MessageId;
290
309
 
291
 
        MessageId = GET_UINT8(pBuffer, 0);
292
 
        LLOGLN(10, ("audin_on_data_received: MessageId=0x%x", MessageId));
 
310
        s = stream_new(0);
 
311
        stream_attach(s, pBuffer, cbSize);
 
312
 
 
313
        stream_read_uint8(s, MessageId);
 
314
 
 
315
        DEBUG_DVC("MessageId=0x%x", MessageId);
 
316
 
293
317
        switch (MessageId)
294
318
        {
295
319
                case MSG_SNDIN_VERSION:
296
 
                        audin_process_version(pChannelCallback, pBuffer + 1, cbSize - 1);
 
320
                        error = audin_process_version(pChannelCallback, s);
297
321
                        break;
 
322
 
298
323
                case MSG_SNDIN_FORMATS:
299
 
                        audin_process_formats(pChannelCallback, pBuffer + 1, cbSize - 1);
 
324
                        error = audin_process_formats(pChannelCallback, s);
300
325
                        break;
 
326
 
301
327
                case MSG_SNDIN_OPEN:
302
 
                        audin_process_open(pChannelCallback, pBuffer + 1, cbSize - 1);
 
328
                        error = audin_process_open(pChannelCallback, s);
303
329
                        break;
 
330
 
304
331
                case MSG_SNDIN_FORMATCHANGE:
305
 
                        audin_process_format_change(pChannelCallback, pBuffer + 1, cbSize - 1);
 
332
                        error = audin_process_format_change(pChannelCallback, s);
306
333
                        break;
 
334
 
307
335
                default:
308
 
                        LLOGLN(0, ("audin_on_data_received: unknown MessageId=0x%x", MessageId));
 
336
                        DEBUG_WARN("unknown MessageId=0x%x", MessageId);
 
337
                        error = 1;
309
338
                        break;
310
339
        }
311
 
        return 0;
312
 
}
313
 
 
314
 
static int
315
 
audin_on_close(IWTSVirtualChannelCallback * pChannelCallback)
316
 
{
317
 
        AUDIN_CHANNEL_CALLBACK * callback = (AUDIN_CHANNEL_CALLBACK *) pChannelCallback;
318
 
        int i;
319
 
 
320
 
        LLOGLN(10, ("audin_on_close:"));
321
 
        wave_in_close(callback->device_data);
322
 
        wave_in_free(callback->device_data);
323
 
        if (callback->formats_data)
324
 
        {
325
 
                for (i = 0; i < callback->formats_count; i++)
326
 
                {
327
 
                        free(callback->formats_data[i]);
328
 
                }
329
 
                free(callback->formats_data);
330
 
        }
331
 
        free(callback);
332
 
        return 0;
333
 
}
334
 
 
335
 
static int
336
 
audin_on_new_channel_connection(IWTSListenerCallback * pListenerCallback,
337
 
        IWTSVirtualChannel * pChannel,
338
 
        char * Data,
339
 
        int * pbAccept,
340
 
        IWTSVirtualChannelCallback ** ppCallback)
341
 
{
342
 
        AUDIN_LISTENER_CALLBACK * listener_callback = (AUDIN_LISTENER_CALLBACK *) pListenerCallback;
343
 
        AUDIN_CHANNEL_CALLBACK * callback;
344
 
 
345
 
        LLOGLN(10, ("audin_on_new_channel_connection:"));
346
 
        callback = (AUDIN_CHANNEL_CALLBACK *) malloc(sizeof(AUDIN_CHANNEL_CALLBACK));
347
 
        memset(callback, 0, sizeof(AUDIN_CHANNEL_CALLBACK));
 
340
 
 
341
        stream_detach(s);
 
342
        stream_free(s);
 
343
 
 
344
        return error;
 
345
}
 
346
 
 
347
static int audin_on_close(IWTSVirtualChannelCallback* pChannelCallback)
 
348
{
 
349
        AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
 
350
        AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
 
351
 
 
352
        DEBUG_DVC("");
 
353
 
 
354
        if (audin->device)
 
355
                IFCALL(audin->device->Close, audin->device);
 
356
 
 
357
        xfree(callback->formats);
 
358
        xfree(callback);
 
359
 
 
360
        return 0;
 
361
}
 
362
 
 
363
static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
 
364
        IWTSVirtualChannel* pChannel,
 
365
        uint8* Data,
 
366
        int* pbAccept,
 
367
        IWTSVirtualChannelCallback** ppCallback)
 
368
{
 
369
        AUDIN_CHANNEL_CALLBACK* callback;
 
370
        AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback;
 
371
 
 
372
        DEBUG_DVC("");
 
373
 
 
374
        callback = xnew(AUDIN_CHANNEL_CALLBACK);
348
375
 
349
376
        callback->iface.OnDataReceived = audin_on_data_received;
350
377
        callback->iface.OnClose = audin_on_close;
351
378
        callback->plugin = listener_callback->plugin;
352
379
        callback->channel_mgr = listener_callback->channel_mgr;
353
380
        callback->channel = pChannel;
354
 
        callback->device_data = wave_in_new();
355
 
 
356
 
        *ppCallback = (IWTSVirtualChannelCallback *) callback;
 
381
 
 
382
        *ppCallback = (IWTSVirtualChannelCallback*) callback;
 
383
 
357
384
        return 0;
358
385
}
359
386
 
360
 
static int
361
 
audin_plugin_initialize(IWTSPlugin * pPlugin, IWTSVirtualChannelManager * pChannelMgr)
 
387
static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
362
388
{
363
 
        AUDIN_PLUGIN * audin = (AUDIN_PLUGIN *) pPlugin;
364
 
 
365
 
        LLOGLN(10, ("audin_plugin_initialize:"));
366
 
        audin->listener_callback = (AUDIN_LISTENER_CALLBACK *) malloc(sizeof(AUDIN_LISTENER_CALLBACK));
367
 
        memset(audin->listener_callback, 0, sizeof(AUDIN_LISTENER_CALLBACK));
 
389
        AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
 
390
 
 
391
        DEBUG_DVC("");
 
392
 
 
393
        audin->listener_callback = xnew(AUDIN_LISTENER_CALLBACK);
368
394
 
369
395
        audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection;
370
396
        audin->listener_callback->plugin = pPlugin;
371
397
        audin->listener_callback->channel_mgr = pChannelMgr;
372
398
        return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0,
373
 
                (IWTSListenerCallback *) audin->listener_callback, NULL);
 
399
                (IWTSListenerCallback*) audin->listener_callback, NULL);
374
400
}
375
401
 
376
 
static int
377
 
audin_plugin_terminated(IWTSPlugin * pPlugin)
 
402
static int audin_plugin_terminated(IWTSPlugin* pPlugin)
378
403
{
379
 
        AUDIN_PLUGIN * audin = (AUDIN_PLUGIN *) pPlugin;
380
 
 
381
 
        LLOGLN(10, ("audin_plugin_terminated:"));
382
 
        if (audin->listener_callback)
383
 
                free(audin->listener_callback);
384
 
        free(audin);
 
404
        AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
 
405
 
 
406
        DEBUG_DVC("");
 
407
 
 
408
        if (audin->device)
 
409
        {
 
410
                IFCALL(audin->device->Close, audin->device);
 
411
                IFCALL(audin->device->Free, audin->device);
 
412
                audin->device = NULL;
 
413
        }
 
414
        xfree(audin->listener_callback);
 
415
        xfree(audin);
 
416
 
385
417
        return 0;
386
418
}
387
419
 
388
 
int
389
 
DVCPluginEntry(IDRDYNVC_ENTRY_POINTS * pEntryPoints)
390
 
{
391
 
        AUDIN_PLUGIN * audin;
392
 
 
393
 
        audin = (AUDIN_PLUGIN *) malloc(sizeof(AUDIN_PLUGIN));
394
 
        memset(audin, 0, sizeof(AUDIN_PLUGIN));
395
 
 
396
 
        audin->iface.Initialize = audin_plugin_initialize;
397
 
        audin->iface.Connected = NULL;
398
 
        audin->iface.Disconnected = NULL;
399
 
        audin->iface.Terminated = audin_plugin_terminated;
400
 
        return pEntryPoints->RegisterPlugin(pEntryPoints, (IWTSPlugin *) audin);
 
420
static void audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* device)
 
421
{
 
422
        AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
 
423
 
 
424
        if (audin->device)
 
425
        {
 
426
                DEBUG_WARN("existing device, abort.");
 
427
                return;
 
428
        }
 
429
 
 
430
        DEBUG_DVC("device registered.");
 
431
 
 
432
        audin->device = device;
 
433
}
 
434
 
 
435
static boolean audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, RDP_PLUGIN_DATA* data)
 
436
{
 
437
        char* fullname;
 
438
        PFREERDP_AUDIN_DEVICE_ENTRY entry;
 
439
        FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
 
440
 
 
441
        if (strrchr(name, '.') != NULL)
 
442
                entry = (PFREERDP_AUDIN_DEVICE_ENTRY)freerdp_load_plugin(name, AUDIN_DEVICE_EXPORT_FUNC_NAME);
 
443
        else
 
444
        {
 
445
                fullname = xzalloc(strlen(name) + 8);
 
446
                strcpy(fullname, "audin_");
 
447
                strcat(fullname, name);
 
448
                entry = (PFREERDP_AUDIN_DEVICE_ENTRY)freerdp_load_plugin(fullname, AUDIN_DEVICE_EXPORT_FUNC_NAME);
 
449
                xfree(fullname);
 
450
        }
 
451
        if (entry == NULL)
 
452
        {
 
453
                return false;
 
454
        }
 
455
 
 
456
        entryPoints.plugin = pPlugin;
 
457
        entryPoints.pRegisterAudinDevice = audin_register_device_plugin;
 
458
        entryPoints.plugin_data = data;
 
459
        if (entry(&entryPoints) != 0)
 
460
        {
 
461
                DEBUG_WARN("%s entry returns error.", name);
 
462
                return false;
 
463
        }
 
464
 
 
465
        return true;
 
466
}
 
467
 
 
468
static boolean audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
 
469
{
 
470
        boolean ret;
 
471
        AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
 
472
        RDP_PLUGIN_DATA default_data[2] = { { 0 }, { 0 } };
 
473
 
 
474
        if (data->data[0] && (strcmp((char*)data->data[0], "audin") == 0 || strstr((char*)data->data[0], "/audin.") != NULL) )
 
475
        {
 
476
                if (data->data[1] && strcmp((char*)data->data[1], "format") == 0)
 
477
                {
 
478
                        audin->fixed_format = atoi(data->data[2]);
 
479
                        return true;
 
480
                }
 
481
                else if (data->data[1] && strcmp((char*)data->data[1], "rate") == 0)
 
482
                {
 
483
                        audin->fixed_rate = atoi(data->data[2]);
 
484
                        return true;
 
485
                }
 
486
                else if (data->data[1] && strcmp((char*)data->data[1], "channel") == 0)
 
487
                {
 
488
                        audin->fixed_channel = atoi(data->data[2]);
 
489
                        return true;
 
490
                }
 
491
                else if (data->data[1] && ((char*)data->data[1])[0])
 
492
                {
 
493
                        return audin_load_device_plugin(pPlugin, (char*)data->data[1], data);
 
494
                }
 
495
                else
 
496
                {
 
497
                        default_data[0].size = sizeof(RDP_PLUGIN_DATA);
 
498
                        default_data[0].data[0] = "audin";
 
499
                        default_data[0].data[1] = "pulse";
 
500
                        default_data[0].data[2] = "";
 
501
                        ret = audin_load_device_plugin(pPlugin, "pulse", default_data);
 
502
                        if (!ret)
 
503
                        {
 
504
                                default_data[0].size = sizeof(RDP_PLUGIN_DATA);
 
505
                                default_data[0].data[0] = "audin";
 
506
                                default_data[0].data[1] = "alsa";
 
507
                                default_data[0].data[2] = "default";
 
508
                                ret = audin_load_device_plugin(pPlugin, "alsa", default_data);
 
509
                        }
 
510
                        return ret;
 
511
                }
 
512
        }
 
513
 
 
514
        return true;
 
515
}
 
516
 
 
517
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
 
518
{
 
519
        int error = 0;
 
520
        AUDIN_PLUGIN* audin;
 
521
 
 
522
        audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin");
 
523
        if (audin == NULL)
 
524
        {
 
525
                audin = xnew(AUDIN_PLUGIN);
 
526
 
 
527
                audin->iface.Initialize = audin_plugin_initialize;
 
528
                audin->iface.Connected = NULL;
 
529
                audin->iface.Disconnected = NULL;
 
530
                audin->iface.Terminated = audin_plugin_terminated;
 
531
                error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
 
532
        }
 
533
 
 
534
        if (error == 0)
 
535
        {
 
536
                audin_process_plugin_data((IWTSPlugin*) audin,
 
537
                        pEntryPoints->GetPluginData(pEntryPoints));
 
538
        }
 
539
 
 
540
        return error;
401
541
}
402
542