~ubuntu-branches/ubuntu/vivid/linphone/vivid

« back to all changes in this revision

Viewing changes to mediastreamer2/src/winsnd.c

  • Committer: Bazaar Package Importer
  • Author(s): Samuel Mimram
  • Date: 2006-11-15 10:34:50 UTC
  • mfrom: (1.2.1 upstream) (2.1.8 feisty)
  • Revision ID: james.westby@ubuntu.com-20061115103450-qgafwcks2lkhctlj
* New upstream release.
* Enable video support.
* Fix mismatched #endif in mscommon.h, closes: #398307.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
mediastreamer2 library - modular sound and video processing and streaming
 
3
Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
 
4
 
 
5
This program is free software; you can redistribute it and/or
 
6
modify it under the terms of the GNU General Public License
 
7
as published by the Free Software Foundation; either version 2
 
8
of the License, or (at your option) any later version.
 
9
 
 
10
This program is distributed in the hope that it will be useful,
 
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
GNU General Public License for more details.
 
14
 
 
15
You should have received a copy of the GNU General Public License
 
16
along with this program; if not, write to the Free Software
 
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
18
*/
 
19
 
 
20
#if defined(_WIN32_WCE)
 
21
#define DISABLE_SPEEX
 
22
#endif
 
23
 
 
24
#ifndef MAX_WAVEHDR
 
25
#define MAX_WAVEHDR 6
 
26
#endif
 
27
 
 
28
#ifndef DISABLE_SPEEX
 
29
#include <speex/speex_preprocess.h>
 
30
#endif
 
31
 
 
32
#include "mediastreamer2/mssndcard.h"
 
33
#include "mediastreamer2/msfilter.h"
 
34
#include "mediastreamer2/msticker.h"
 
35
 
 
36
#ifdef WIN32
 
37
#include <malloc.h> /* for alloca */
 
38
#endif
 
39
 
 
40
#include <mmsystem.h>
 
41
#ifdef _MSC_VER
 
42
#include <mmreg.h>
 
43
#endif
 
44
#include <msacm.h>
 
45
 
 
46
MSFilter *ms_winsnd_read_new(MSSndCard *card);
 
47
MSFilter *ms_winsnd_write_new(MSSndCard *card);
 
48
 
 
49
typedef struct WinSndData{
 
50
        char *pcmdev;
 
51
        char *mixdev;
 
52
 
 
53
    int sound_err;
 
54
    WAVEFORMATEX wfx;
 
55
    WAVEHDR waveouthdr[30];
 
56
    char waveoutbuffer[30][3200];
 
57
    HWAVEOUT waveoutdev;
 
58
    int buffer_playing;
 
59
 
 
60
    WAVEHDR waveinhdr[30];
 
61
    HWAVEIN waveindev;
 
62
    char waveinbuffer[30][3200];
 
63
 
 
64
    int rate;
 
65
        int bits;
 
66
        ms_thread_t thread;
 
67
        ms_mutex_t mutex;
 
68
        queue_t rq;
 
69
        MSBufferizer * bufferizer;
 
70
        bool_t read_started;
 
71
        bool_t write_started;
 
72
        bool_t stereo;
 
73
 
 
74
#ifndef DISABLE_SPEEX
 
75
        SpeexPreprocessState *pst;
 
76
#endif
 
77
 
 
78
        uint64_t bytes_read;
 
79
} WinSndData;
 
80
 
 
81
static uint64_t winsnd_get_cur_time( void *data){
 
82
        WinSndData *d=(WinSndData*)data;
 
83
        uint64_t curtime=(d->bytes_read*1000)/(d->rate*(d->bits/8)*((d->stereo==FALSE) ? 1 : 2));
 
84
        ms_debug("winsnd_get_cur_time: bytes_read=%lu, rate=%i, bits=%i, stereo=%i return %lu\n",
 
85
        (unsigned long)d->bytes_read,d->rate,d->bits,d->stereo,(unsigned long)curtime);
 
86
        return curtime;
 
87
}
 
88
 
 
89
static void CALLBACK
 
90
SpeakerCallback (HWAVEOUT _waveoutdev, UINT uMsg, DWORD dwInstance,
 
91
                 DWORD dwParam1, DWORD dwParam2)
 
92
{
 
93
  WAVEHDR *wHdr;
 
94
  WinSndData *device;
 
95
 
 
96
  switch (uMsg)
 
97
    {
 
98
      case WOM_OPEN:
 
99
          ms_message("SpeakerCallback : WOM_OPEN");
 
100
        break;
 
101
      case WOM_CLOSE:
 
102
          ms_message("SpeakerCallback : WOM_CLOSE");
 
103
        break;
 
104
      case WOM_DONE:
 
105
        wHdr = (WAVEHDR *) dwParam1;
 
106
        device = (WinSndData *)dwInstance;
 
107
        device->buffer_playing--;
 
108
        break;
 
109
      default:
 
110
        break;
 
111
    }
 
112
}
 
113
 
 
114
static void CALLBACK
 
115
WaveInCallback (HWAVEIN waveindev, UINT uMsg, DWORD dwInstance, DWORD dwParam1,
 
116
                DWORD dwParam2)
 
117
{
 
118
  WAVEHDR *wHdr;
 
119
  MMRESULT mr = NOERROR;
 
120
  WinSndData *device;
 
121
 
 
122
  device = (WinSndData *)dwInstance;
 
123
 
 
124
  switch (uMsg)
 
125
    {
 
126
      case MM_WOM_DONE:
 
127
        wHdr = (WAVEHDR *) dwParam1;
 
128
        /* A waveform-audio data block has been played and 
 
129
           can now be freed. */
 
130
        ms_message("WaveInCallback : MM_WOM_DONE");
 
131
        waveInUnprepareHeader (waveindev, (LPWAVEHDR) wHdr, sizeof (WAVEHDR));
 
132
        break;
 
133
 
 
134
      case WIM_OPEN:
 
135
        ms_message("WaveInCallback : WIM_OPEN");
 
136
        break;
 
137
      case WIM_CLOSE:
 
138
        ms_message("WaveInCallback : WIM_CLOSE");
 
139
        break;
 
140
      case WIM_DATA:
 
141
        wHdr = (WAVEHDR *) dwParam1;
 
142
 
 
143
        if (!device->read_started && !device->write_started)
 
144
          {
 
145
            mr = waveInUnprepareHeader (device->waveindev, (LPWAVEHDR) wHdr, sizeof (WAVEHDR));
 
146
            ms_warning("WaveInCallback : unprepare header (waveInUnprepareHeader:0x%i)", mr);
 
147
            return;
 
148
          }
 
149
 
 
150
        if (wHdr->dwBufferLength!=wHdr->dwBytesRecorded)
 
151
        {
 
152
            mr = waveInAddBuffer (device->waveindev,
 
153
                wHdr,
 
154
                sizeof (device->waveinhdr[wHdr->dwUser]));
 
155
            if (mr != MMSYSERR_NOERROR)
 
156
            {
 
157
                ms_warning("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr);
 
158
            }
 
159
            return;
 
160
        }
 
161
        device->bytes_read+=wHdr->dwBytesRecorded;
 
162
        ms_mutex_lock(&device->mutex);
 
163
                if (device->read_started)
 
164
        {
 
165
            mblk_t *rm=NULL;
 
166
            if (rm==NULL) rm=allocb(wHdr->dwBufferLength,0);
 
167
                        memcpy(rm->b_wptr,wHdr->lpData, wHdr->dwBufferLength);
 
168
 
 
169
#ifndef DISABLE_SPEEX
 
170
                        if (device->pst!=NULL)
 
171
                        {
 
172
                                int vad;
 
173
                                //memset(rm->b_wptr,0, wHdr->dwBufferLength);
 
174
 
 
175
                                vad = speex_preprocess(device->pst, (short*)rm->b_wptr, NULL);
 
176
#if 0
 
177
                                if (vad!=1)
 
178
                            ms_message("WaveInCallback : %d", vad);
 
179
#endif
 
180
                        }
 
181
 
 
182
#endif
 
183
                        rm->b_wptr+=wHdr->dwBufferLength;
 
184
                        putq(&device->rq,rm);
 
185
                    rm=NULL;
 
186
        }
 
187
        ms_mutex_unlock(&device->mutex);
 
188
 
 
189
        mr = waveInAddBuffer (device->waveindev,
 
190
            wHdr,
 
191
            sizeof (device->waveinhdr[wHdr->dwUser]));
 
192
        if (mr != MMSYSERR_NOERROR)
 
193
        {
 
194
            ms_warning("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr);
 
195
            return;
 
196
        }
 
197
    }
 
198
}
 
199
 
 
200
static int winsnd_open(WinSndData *device, int devnumber, int bits,int stereo, int rate, int *minsz)
 
201
{
 
202
    MMRESULT mr = NOERROR;
 
203
    DWORD dwFlag;
 
204
    int i;
 
205
    int channel = 1;
 
206
    if (stereo>0)
 
207
        channel = stereo;
 
208
        device->wfx.wFormatTag = WAVE_FORMAT_PCM;
 
209
        device->wfx.cbSize = 0;
 
210
        device->wfx.nAvgBytesPerSec = 16000;
 
211
        device->wfx.nBlockAlign = 2;
 
212
        device->wfx.nChannels = channel;
 
213
        device->wfx.nSamplesPerSec = rate; /* 8000; */
 
214
        device->wfx.wBitsPerSample = bits;
 
215
        
 
216
    dwFlag = CALLBACK_FUNCTION;
 
217
    if (devnumber != WAVE_MAPPER)
 
218
        dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION;
 
219
    mr = waveOutOpen (&(device->waveoutdev), devnumber, &(device->wfx), (DWORD) SpeakerCallback,
 
220
                    (DWORD)device, dwFlag);
 
221
    if (mr != NOERROR)
 
222
    {
 
223
        ms_warning("Failed to open device: trying default device. (waveOutOpen:0x%i)", mr);
 
224
        dwFlag = CALLBACK_FUNCTION;
 
225
        mr = waveOutOpen (&(device->waveoutdev), WAVE_MAPPER, &(device->wfx), (DWORD) SpeakerCallback,
 
226
                        (DWORD)device, dwFlag);
 
227
    }
 
228
    if (mr != NOERROR)
 
229
    {
 
230
        ms_warning("Failed to open windows sound device. (waveOutOpen:0x%i)", mr);
 
231
        return -1;
 
232
    }
 
233
 
 
234
    /* prepare windows buffers */
 
235
 
 
236
 
 
237
    for (i = 0; i < MAX_WAVEHDR; i++)
 
238
    {
 
239
        memset (&(device->waveouthdr[i]), 0, sizeof (device->waveouthdr[i]));
 
240
        device->waveouthdr[i].lpData = device->waveoutbuffer[i];
 
241
        /* BUG: on ne connait pas la taille des frames a recevoir... 
 
242
        on utilise enc_frame_per_packet au lien de dec_frame_per_packet */
 
243
 
 
244
        device->waveouthdr[i].dwBufferLength = device->rate/8000 * 320;
 
245
        /* 480 pour 98 (speex) */
 
246
        device->waveouthdr[i].dwFlags = 0;
 
247
        device->waveouthdr[i].dwUser = i;
 
248
 
 
249
        mr = waveOutPrepareHeader (device->waveoutdev, &(device->waveouthdr[i]),
 
250
            sizeof (device->waveouthdr[i]));
 
251
        if (mr != MMSYSERR_NOERROR){
 
252
            ms_warning("Failed to prepare windows sound device. (waveOutPrepareHeader:0x%i)", mr);
 
253
        }
 
254
        else
 
255
        {
 
256
            ms_message("Sound Header prepared %i for windows sound device. (waveOutPrepareHeader)", i);
 
257
        }
 
258
    }
 
259
 
 
260
 
 
261
    /* Init Microphone device */
 
262
    dwFlag = CALLBACK_FUNCTION;
 
263
    if (devnumber != WAVE_MAPPER)
 
264
        dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION;
 
265
    mr = waveInOpen (&(device->waveindev), devnumber, &(device->wfx),
 
266
                (DWORD) WaveInCallback, (DWORD)device, dwFlag);
 
267
    if (mr != NOERROR)
 
268
    {
 
269
        ms_warning("Failed to open device: trying default device. (waveInOpen:0x%i)", mr);
 
270
        dwFlag = CALLBACK_FUNCTION;
 
271
        mr = waveInOpen (&(device->waveindev), WAVE_MAPPER, &(device->wfx),
 
272
                    (DWORD) WaveInCallback, (DWORD)device, dwFlag);
 
273
    }
 
274
 
 
275
    if (mr != NOERROR)
 
276
    {
 
277
        ms_warning("Failed to prepare windows sound device. (waveInOpen:0x%i)", mr);
 
278
        return -1;
 
279
    }
 
280
 
 
281
 
 
282
 
 
283
    for (i = 0; i < MAX_WAVEHDR; i++)
 
284
    {
 
285
        memset (&(device->waveinhdr[i]), 0, sizeof (device->waveinhdr[i]));
 
286
        device->waveinhdr[i].lpData = device->waveinbuffer[i];
 
287
        /* frameSize */
 
288
        device->waveinhdr[i].dwBufferLength = device->rate/8000 * 320;
 
289
        device->waveinhdr[i].dwFlags = 0;
 
290
        device->waveinhdr[i].dwUser = i;
 
291
        mr = waveInPrepareHeader (device->waveindev, &(device->waveinhdr[i]),             
 
292
            sizeof (device->waveinhdr[i]));
 
293
        if (mr == MMSYSERR_NOERROR){
 
294
            mr = waveInAddBuffer (device->waveindev, &(device->waveinhdr[i]),
 
295
                sizeof (device->waveinhdr[i]));
 
296
            if (mr == MMSYSERR_NOERROR)
 
297
            {
 
298
                ms_message("Sound Header prepared %i for windows sound device. (waveInAddBuffer)", i);
 
299
            }
 
300
            else
 
301
            {
 
302
                ms_warning("Failed to prepare windows sound device. (waveInAddBuffer:0x%i)", mr);
 
303
            }
 
304
        }
 
305
        else
 
306
        {
 
307
            ms_warning("Failed to prepare windows sound device. (waveInPrepareHeader:0x%i)", mr);
 
308
        }
 
309
    }
 
310
 
 
311
#ifndef DISABLE_SPEEX
 
312
#if 0
 
313
        device->pst = speex_preprocess_state_init((device->rate/8000 * 320)/2, device->rate);
 
314
        if (device->pst!=NULL) {
 
315
                float f;
 
316
                i=1;
 
317
                speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_VAD, &i);
 
318
                i=1;
 
319
                speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DENOISE, &i);
 
320
                i=0;
 
321
                speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_AGC, &i);
 
322
                f=8000;
 
323
                speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f);
 
324
                i=0;
 
325
                speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB, &i);
 
326
                f=.4;
 
327
                speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
 
328
                f=.3;
 
329
                speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);
 
330
        }
 
331
#endif
 
332
#endif
 
333
        device->bytes_read=0;
 
334
        mr = waveInStart (device->waveindev);
 
335
    if (mr != MMSYSERR_NOERROR)
 
336
    {
 
337
        ms_warning("Failed to start recording on windows sound device. (waveInStart:0x%i)", mr);
 
338
        return -1;
 
339
    }
 
340
 
 
341
        *minsz=device->rate/8000 * 320;
 
342
        return 0;
 
343
}
 
344
 
 
345
static void winsnd_set_level(MSSndCard *card, MSSndCardMixerElem e, int percent)
 
346
{
 
347
        WinSndData *d=(WinSndData*)card->data;
 
348
    MMRESULT mr = NOERROR;
 
349
    DWORD dwVolume = 0xFFFF;
 
350
    dwVolume = ((0xFFFF) * percent) / 100;
 
351
 
 
352
        if (d->mixdev==NULL) return;
 
353
        switch(e){
 
354
                case MS_SND_CARD_MASTER:
 
355
            mr = waveOutSetVolume(d->waveoutdev, dwVolume);
 
356
                if (mr != MMSYSERR_NOERROR)
 
357
                {
 
358
                ms_warning("Failed to set master volume. (waveOutSetVolume:0x%i)", mr);
 
359
                return;
 
360
                }
 
361
            return;
 
362
        break;
 
363
#if 0
 
364
        case MS_SND_CARD_CAPTURE:
 
365
                        wincmd=SOUND_MIXER_IGAIN;
 
366
                break;
 
367
                case MS_SND_CARD_PLAYBACK:
 
368
                        wincmd=SOUND_MIXER_PCM;
 
369
                break;
 
370
#endif
 
371
        default:
 
372
                        ms_warning("winsnd_card_set_level: unsupported command.");
 
373
                        return;
 
374
        }
 
375
}
 
376
 
 
377
static int winsnd_get_level(MSSndCard *card, MSSndCardMixerElem e)
 
378
{
 
379
        WinSndData *d=(WinSndData*)card->data;
 
380
    MMRESULT mr = NOERROR;
 
381
    DWORD dwVolume = 0x0000;
 
382
 
 
383
        if (d->mixdev==NULL) return -1;
 
384
        switch(e){
 
385
                case MS_SND_CARD_MASTER:
 
386
            mr=waveOutGetVolume(d->waveoutdev, &dwVolume);
 
387
            // Transform to 0 to 100 scale
 
388
            //dwVolume = (dwVolume *100) / (0xFFFF);
 
389
            return 60;
 
390
        break;
 
391
#if 0
 
392
        case MS_SND_CARD_CAPTURE:
 
393
                        osscmd=SOUND_MIXER_IGAIN;
 
394
                break;
 
395
                case MS_SND_CARD_PLAYBACK:
 
396
                        osscmd=SOUND_MIXER_PCM;
 
397
                break;
 
398
#endif
 
399
                default:
 
400
                        ms_warning("winsnd_card_get_level: unsupported command.");
 
401
                        return -1;
 
402
        }
 
403
        return -1;
 
404
}
 
405
 
 
406
static void winsnd_set_source(MSSndCard *card, MSSndCardCapture source)
 
407
{
 
408
        WinSndData *d=(WinSndData*)card->data;
 
409
        if (d->mixdev==NULL) return;
 
410
 
 
411
        switch(source){
 
412
                case MS_SND_CARD_MIC:
 
413
                break;
 
414
                case MS_SND_CARD_LINE:
 
415
                break;
 
416
        }       
 
417
}
 
418
 
 
419
static void winsnd_init(MSSndCard *card){
 
420
        WinSndData *d=ms_new(WinSndData,1);
 
421
    memset(d, 0, sizeof(WinSndData));
 
422
        d->pcmdev=NULL;
 
423
        d->mixdev=NULL;
 
424
    d->sound_err=-1; /* not opened */
 
425
        d->read_started=FALSE;
 
426
        d->write_started=FALSE;
 
427
        d->bits=16;
 
428
        d->rate=8000;
 
429
        d->stereo=FALSE;
 
430
        qinit(&d->rq);
 
431
        d->bufferizer=ms_bufferizer_new();
 
432
        ms_mutex_init(&d->mutex,NULL);
 
433
        card->data=d;
 
434
#ifndef DISABLE_SPEEX
 
435
        d->pst=0;
 
436
#endif
 
437
}
 
438
 
 
439
static void winsnd_uninit(MSSndCard *card){
 
440
        WinSndData *d=(WinSndData*)card->data;
 
441
        if (d==NULL)
 
442
                return;
 
443
        if (d->pcmdev!=NULL) ms_free(d->pcmdev);
 
444
        if (d->mixdev!=NULL) ms_free(d->mixdev);
 
445
        ms_bufferizer_destroy(d->bufferizer);
 
446
        flushq(&d->rq,0);
 
447
 
 
448
        ms_mutex_destroy(&d->mutex);
 
449
 
 
450
#ifndef DISABLE_SPEEX
 
451
        if (d->pst!=NULL)
 
452
            speex_preprocess_state_destroy(d->pst);
 
453
#endif
 
454
 
 
455
        ms_free(d);
 
456
}
 
457
 
 
458
#define DSP_NAME "/dev/dsp"
 
459
#define MIXER_NAME "/dev/mixer"
 
460
 
 
461
static void winsnd_detect(MSSndCardManager *m);
 
462
static  MSSndCard *winsnd_dup(MSSndCard *obj);
 
463
 
 
464
MSSndCardDesc winsnd_card_desc={
 
465
        "WINSND",
 
466
        winsnd_detect,
 
467
        winsnd_init,
 
468
        winsnd_set_level,
 
469
        winsnd_get_level,
 
470
        winsnd_set_source,
 
471
        ms_winsnd_read_new,
 
472
        ms_winsnd_write_new,
 
473
        winsnd_uninit,
 
474
        winsnd_dup
 
475
};
 
476
 
 
477
static  MSSndCard *winsnd_dup(MSSndCard *obj){
 
478
        MSSndCard *card=ms_snd_card_new(&winsnd_card_desc);
 
479
        WinSndData *dcard=(WinSndData*)card->data;
 
480
        WinSndData *dobj=(WinSndData*)obj->data;
 
481
        dcard->pcmdev=ms_strdup(dobj->pcmdev);
 
482
        dcard->mixdev=ms_strdup(dobj->mixdev);
 
483
        card->name=ms_strdup(obj->name);
 
484
        return card;
 
485
}
 
486
 
 
487
static MSSndCard *winsnd_card_new(const char *pcmdev, const char *mixdev){
 
488
        MSSndCard *card=ms_snd_card_new(&winsnd_card_desc);
 
489
        WinSndData *d=(WinSndData*)card->data;
 
490
        d->pcmdev=ms_strdup(pcmdev);
 
491
        d->mixdev=ms_strdup(mixdev);
 
492
        card->name=ms_strdup(pcmdev);
 
493
        return card;
 
494
}
 
495
 
 
496
static void winsnd_detect(MSSndCardManager *m){
 
497
    MMRESULT mr = NOERROR;
 
498
    unsigned int nInDevices = waveInGetNumDevs ();
 
499
    /*unsigned int nOutDevices = waveOutGetNumDevs ();*/
 
500
    unsigned int item;
 
501
        char pcmdev[1024];
 
502
        char mixdev[1024];
 
503
 
 
504
    for (item = 0; item < nInDevices; item++)
 
505
    {
 
506
        WAVEINCAPS caps;
 
507
        mr = waveInGetDevCaps (item, &caps, sizeof (WAVEINCAPS));
 
508
        if (mr == MMSYSERR_NOERROR)
 
509
        {
 
510
            MSSndCard *card;
 
511
                snprintf(pcmdev,sizeof(pcmdev),"%s",caps.szPname);
 
512
                snprintf(mixdev,sizeof(mixdev),"%s",caps.szPname);
 
513
            if (item == 0)
 
514
            {
 
515
                        card=winsnd_card_new(pcmdev,mixdev);
 
516
                        ms_snd_card_manager_add_card(m,card);
 
517
            }
 
518
                        card=winsnd_card_new(pcmdev,mixdev);
 
519
                        ms_snd_card_manager_add_card(m,card);
 
520
        }
 
521
    }
 
522
}
 
523
 
 
524
static void * winsnd_thread(void *p){
 
525
        MSSndCard *card=(MSSndCard*)p;
 
526
        WinSndData *d=(WinSndData*)card->data;
 
527
        int bsize=0;
 
528
        uint8_t *rtmpbuff=NULL;
 
529
        uint8_t *wtmpbuff=NULL;
 
530
        int err;
 
531
#if 0
 
532
        mblk_t *rm=NULL;
 
533
#endif
 
534
 
 
535
    MMRESULT mr = NOERROR;
 
536
    int pos_whdr=0;
 
537
        int devnumber=-1;
 
538
        const MSList *elem = ms_snd_card_manager_get_list(ms_snd_card_manager_get());
 
539
 
 
540
        /* look for devicenumber for card */
 
541
        for (;elem!=NULL;elem=elem->next){
 
542
                MSSndCard *acard=(MSSndCard*)elem->data;
 
543
                if (card==acard)
 
544
                {
 
545
                        break;
 
546
                }
 
547
                devnumber++;
 
548
        }
 
549
 
 
550
        d->sound_err=winsnd_open(d, devnumber, d->bits,d->stereo,d->rate,&bsize);
 
551
        if (d->sound_err==0){
 
552
                rtmpbuff=(uint8_t*)alloca(bsize);
 
553
                wtmpbuff=(uint8_t*)alloca(bsize);
 
554
        }
 
555
        while(d->read_started || d->write_started){
 
556
                if (d->sound_err==0){
 
557
#if 0
 
558
                        if (d->read_started){
 
559
                if (rm==NULL) rm=allocb(bsize,0);
 
560
 
 
561
                /* get data from callback */
 
562
                                //err=read(d->pcmfd,rm->b_wptr,bsize);
 
563
                err=-1;
 
564
 
 
565
                                if (err<0){
 
566
                                        ms_warning("Fail to read %i bytes from soundcard: %s",
 
567
                                        bsize,strerror(errno));
 
568
                                }else{
 
569
                                        rm->b_wptr+=err;
 
570
                                        putq(&d->rq,rm);
 
571
                                        rm=NULL;
 
572
                                }
 
573
                        }else {
 
574
                                int sz;
 
575
                //sz = read(d->pcmfd,rtmpbuff,bsize);
 
576
                sz=-1;
 
577
                                if( sz!=bsize) ms_warning("sound device read returned %i !",sz);
 
578
                        }
 
579
#endif
 
580
                        if (d->write_started){
 
581
 
 
582
                if (d->buffer_playing<4 && d->buffer_playing<MAX_WAVEHDR)
 
583
                {
 
584
                                        /* remove extra buffer when latency is increasing:
 
585
                                        this often happen with USB device */
 
586
                                        ms_mutex_lock(&d->mutex);
 
587
                                        if (d->bufferizer->size>=bsize*7){
 
588
                        ms_warning("Extra data for sound card removed (%ims)", 2*(bsize*20)/320);
 
589
                                            err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize);
 
590
                                            err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize);
 
591
                                        }
 
592
                                    err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize);
 
593
                                        ms_mutex_unlock(&d->mutex);
 
594
                                    if (err==bsize){
 
595
 
 
596
                        /* write to sound devide! */
 
597
                        //err=write(d->pcmfd,wtmpbuff,bsize);
 
598
                        memcpy (d->waveouthdr[pos_whdr].lpData, wtmpbuff, bsize);
 
599
 
 
600
                        mr = waveOutWrite (d->waveoutdev,
 
601
                            &(d->waveouthdr[pos_whdr]),
 
602
                            sizeof (d->waveouthdr[pos_whdr]));
 
603
 
 
604
                        if (mr != MMSYSERR_NOERROR)
 
605
                        {
 
606
                            if (mr == WAVERR_STILLPLAYING)
 
607
                            {
 
608
                                /* retry later */
 
609
                                /* data should go back to queue */
 
610
                                /* TODO */
 
611
                                ms_warning("sound device write STILL_PLAYING (waveOutWrite:0x%i)", mr);
 
612
                            }
 
613
                            else
 
614
                            {
 
615
                                ms_warning("sound device write returned (waveOutWrite:0x%i)", mr);
 
616
                            }
 
617
                        }
 
618
                        else
 
619
                        {
 
620
                            d->buffer_playing++;
 
621
                            pos_whdr++;
 
622
                            if (pos_whdr == MAX_WAVEHDR)
 
623
                                pos_whdr = 0;   /* loop over the prepared blocks */
 
624
                        }
 
625
 
 
626
 
 
627
                                            if (err<0){
 
628
#if !defined(_WIN32_WCE)
 
629
                                                    ms_warning("Fail to write %i bytes from soundcard: %s",
 
630
                                                            bsize,strerror(errno));
 
631
#else
 
632
                                                    ms_warning("Fail to write %i bytes from soundcard: %i",
 
633
                                                            bsize,WSAGetLastError());
 
634
#endif
 
635
                                            }
 
636
                                    }
 
637
                                        else
 
638
                                        {
 
639
                                                        Sleep(10);
 
640
                                        }
 
641
                }
 
642
                else
 
643
                {
 
644
                                        ms_mutex_lock(&d->mutex);
 
645
                                        if (d->bufferizer->size>=bsize*4){
 
646
                        ms_warning("Extra data for sound card removed (%ims)", 3*(bsize*20)/320);
 
647
                                            err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize);
 
648
                                            err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize);
 
649
                                            err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize);
 
650
                                        }
 
651
                                        ms_mutex_unlock(&d->mutex);
 
652
                    Sleep(10);
 
653
                }
 
654
                        }else {
 
655
                if (d->buffer_playing<3 && d->buffer_playing<MAX_WAVEHDR)
 
656
                {
 
657
                                    memset(wtmpbuff,0,bsize);
 
658
                                
 
659
                    memcpy (d->waveouthdr[pos_whdr].lpData, wtmpbuff, bsize);
 
660
                    //sz = write(d->pcmfd,wtmpbuff,bsize);
 
661
                    mr = waveOutWrite (d->waveoutdev,
 
662
                        &(d->waveouthdr[pos_whdr]),
 
663
                        sizeof (d->waveouthdr[pos_whdr]));
 
664
 
 
665
                    if (mr != MMSYSERR_NOERROR)
 
666
                    {
 
667
                        if (mr == WAVERR_STILLPLAYING)
 
668
                        {
 
669
                            /* retry later */
 
670
                            /* data should go back to queue */
 
671
                            /* TODO */
 
672
                            ms_warning("sound device write STILL_PLAYING (waveOutWrite:0x%i)", mr);
 
673
                        }
 
674
                        else
 
675
                        {
 
676
                            ms_warning("sound device write returned (waveOutWrite:0x%i)", mr);
 
677
                        }
 
678
                    }
 
679
                    else
 
680
                    {
 
681
                        d->buffer_playing++;
 
682
                        pos_whdr++;
 
683
                        if (pos_whdr == MAX_WAVEHDR)
 
684
                            pos_whdr = 0;   /* loop over the prepared blocks */
 
685
                    }
 
686
                            }
 
687
                else
 
688
                {
 
689
                    Sleep(10);
 
690
                }
 
691
            }
 
692
                }else Sleep(10);
 
693
        }
 
694
        if (d->sound_err==0) {
 
695
        int i;
 
696
        int count=0;
 
697
        /* close sound card */
 
698
 
 
699
        /* unprepare buffer */
 
700
        for (i = 0; i < MAX_WAVEHDR; i++)
 
701
        {
 
702
            int counttry=0;
 
703
            for (counttry=0;counttry<10;counttry++)
 
704
            {
 
705
                mr = waveInUnprepareHeader (d->waveindev,
 
706
                                        &(d->waveinhdr[i]),
 
707
                                        sizeof (d->waveinhdr[i]));
 
708
                if (mr != MMSYSERR_NOERROR)
 
709
                {
 
710
                    ms_error("Failed to unprepared %i buffer from sound card (waveInUnprepareHeader:0x%i", count, mr);
 
711
                    Sleep (20);
 
712
                } else
 
713
                {
 
714
                    count++;
 
715
                            ms_message("successfully unprepared %i buffer from sound card.", count);
 
716
                    break;
 
717
                }
 
718
            }
 
719
        }
 
720
                ms_warning("unprepared %i buffer from sound card.", count);
 
721
 
 
722
        mr = waveInStop (d->waveindev);
 
723
        if (mr != MMSYSERR_NOERROR)
 
724
        {
 
725
                ms_error("failed to stop recording sound card (waveInStop:0x%i)", mr);
 
726
        } else
 
727
        {
 
728
                ms_message("successfully stopped recording sound card");
 
729
        }
 
730
 
 
731
        mr = waveInReset (d->waveindev);
 
732
        if (mr != MMSYSERR_NOERROR)
 
733
        {
 
734
                ms_warning("failed to reset recording sound card (waveInReset:0x%i)", mr);
 
735
        } else
 
736
        {
 
737
                ms_message("successful reset of recording sound card");
 
738
        }
 
739
 
 
740
        mr = waveInClose (d->waveindev);
 
741
        if (mr != MMSYSERR_NOERROR)
 
742
        {
 
743
                ms_warning("failed to close recording sound card (waveInClose:0x%i)", mr);
 
744
        } else
 
745
        {
 
746
                ms_message("successfully closed recording sound card");
 
747
        }
 
748
                d->sound_err=-1;
 
749
        }
 
750
        return NULL;
 
751
}
 
752
 
 
753
static void winsnd_start_r(MSSndCard *card){
 
754
        WinSndData *d=(WinSndData*)card->data;
 
755
        if (d->read_started==FALSE && d->write_started==FALSE){
 
756
                d->read_started=TRUE;
 
757
                ms_thread_create(&d->thread,NULL,winsnd_thread,card);
 
758
        }else d->read_started=TRUE;
 
759
}
 
760
 
 
761
static void winsnd_stop_r(MSSndCard *card){
 
762
        WinSndData *d=(WinSndData*)card->data;
 
763
        d->read_started=FALSE;
 
764
        if (d->write_started==FALSE){
 
765
                ms_thread_join(d->thread,NULL);
 
766
        }
 
767
}
 
768
 
 
769
static void winsnd_start_w(MSSndCard *card){
 
770
        WinSndData *d=(WinSndData*)card->data;
 
771
        if (d->read_started==FALSE && d->write_started==FALSE){
 
772
                d->write_started=TRUE;
 
773
                ms_thread_create(&d->thread,NULL,winsnd_thread,card);
 
774
        }else{
 
775
                d->write_started=TRUE;
 
776
        }
 
777
}
 
778
 
 
779
static void winsnd_stop_w(MSSndCard *card){
 
780
        WinSndData *d=(WinSndData*)card->data;
 
781
        d->write_started=FALSE;
 
782
        if (d->read_started==FALSE){
 
783
                ms_thread_join(d->thread,NULL);
 
784
        }
 
785
}
 
786
 
 
787
static mblk_t *winsnd_get(MSSndCard *card){
 
788
        WinSndData *d=(WinSndData*)card->data;
 
789
        mblk_t *m;
 
790
        ms_mutex_lock(&d->mutex);
 
791
        m=getq(&d->rq);
 
792
        ms_mutex_unlock(&d->mutex);
 
793
        return m;
 
794
}
 
795
 
 
796
static void winsnd_put(MSSndCard *card, mblk_t *m){
 
797
        WinSndData *d=(WinSndData*)card->data;
 
798
        ms_mutex_lock(&d->mutex);
 
799
        ms_bufferizer_put(d->bufferizer,m);
 
800
        ms_mutex_unlock(&d->mutex);
 
801
}
 
802
 
 
803
 
 
804
static void winsnd_read_preprocess(MSFilter *f){
 
805
        MSSndCard *card=(MSSndCard*)f->data;
 
806
        winsnd_start_r(card);
 
807
        ms_ticker_set_time_func(f->ticker,winsnd_get_cur_time,card->data);
 
808
}
 
809
 
 
810
static void winsnd_read_postprocess(MSFilter *f){
 
811
        MSSndCard *card=(MSSndCard*)f->data;
 
812
        ms_ticker_set_time_func(f->ticker,NULL,NULL);
 
813
        winsnd_stop_r(card);
 
814
}
 
815
 
 
816
static void winsnd_read_process(MSFilter *f){
 
817
        MSSndCard *card=(MSSndCard*)f->data;
 
818
        mblk_t *m;
 
819
        while((m=winsnd_get(card))!=NULL){
 
820
                ms_queue_put(f->outputs[0],m);
 
821
        }
 
822
}
 
823
 
 
824
static void winsnd_write_preprocess(MSFilter *f){
 
825
        MSSndCard *card=(MSSndCard*)f->data;
 
826
        winsnd_start_w(card);
 
827
}
 
828
 
 
829
static void winsnd_write_postprocess(MSFilter *f){
 
830
        MSSndCard *card=(MSSndCard*)f->data;
 
831
        winsnd_stop_w(card);
 
832
}
 
833
 
 
834
static void winsnd_write_process(MSFilter *f){
 
835
        MSSndCard *card=(MSSndCard*)f->data;
 
836
        mblk_t *m;
 
837
        while((m=ms_queue_get(f->inputs[0]))!=NULL){
 
838
                winsnd_put(card,m);
 
839
        }
 
840
}
 
841
 
 
842
static int set_rate(MSFilter *f, void *arg){
 
843
        MSSndCard *card=(MSSndCard*)f->data;
 
844
        WinSndData *d=(WinSndData*)card->data;
 
845
        d->rate=*((int*)arg);
 
846
        return 0;
 
847
}
 
848
 
 
849
static int set_nchannels(MSFilter *f, void *arg){
 
850
        MSSndCard *card=(MSSndCard*)f->data;
 
851
        WinSndData *d=(WinSndData*)card->data;
 
852
        d->stereo=(*((int*)arg)==2);
 
853
        return 0;
 
854
}
 
855
 
 
856
 
 
857
static MSFilterMethod winsnd_methods[]={
 
858
        {       MS_FILTER_SET_SAMPLE_RATE       , set_rate      },
 
859
        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
 
860
        {       0                               , NULL          }
 
861
};
 
862
 
 
863
MSFilterDesc winsnd_read_desc={
 
864
        MS_WINSND_READ_ID,
 
865
        "MSWinSndRead",
 
866
        "Sound capture filter for Windows Sound drivers",
 
867
        MS_FILTER_OTHER,
 
868
        NULL,
 
869
    0,
 
870
        1,
 
871
        NULL,
 
872
    winsnd_read_preprocess,
 
873
        winsnd_read_process,
 
874
        winsnd_read_postprocess,
 
875
    NULL,
 
876
        winsnd_methods
 
877
};
 
878
 
 
879
 
 
880
MSFilterDesc winsnd_write_desc={
 
881
        MS_WINSND_WRITE_ID,
 
882
        "MSWinSndWrite",
 
883
        "Sound playback filter for Windows Sound drivers",
 
884
        MS_FILTER_OTHER,
 
885
        NULL,
 
886
    1,
 
887
        0,
 
888
        NULL,
 
889
    winsnd_write_preprocess,
 
890
        winsnd_write_process,
 
891
        winsnd_write_postprocess,
 
892
        NULL,
 
893
    winsnd_methods
 
894
};
 
895
 
 
896
MSFilter *ms_winsnd_read_new(MSSndCard *card){
 
897
        MSFilter *f=ms_filter_new_from_desc(&winsnd_read_desc);
 
898
        f->data=card;
 
899
        return f;
 
900
}
 
901
 
 
902
 
 
903
MSFilter *ms_winsnd_write_new(MSSndCard *card){
 
904
        MSFilter *f=ms_filter_new_from_desc(&winsnd_write_desc);
 
905
        f->data=card;
 
906
        return f;
 
907
}
 
908
 
 
909
MS_FILTER_DESC_EXPORT(winsnd_read_desc)
 
910
MS_FILTER_DESC_EXPORT(winsnd_write_desc)