00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 #include <libplayercore/playercore.h>
00199 #include <sys/time.h>
00200 #include <string.h>
00201 #include <iostream>
00202 using namespace std;
00203
00204 #include "alsa.h"
00205
00206
00207 Driver* Alsa_Init (ConfigFile* cf, int section)
00208 {
00209 return reinterpret_cast<Driver*> (new Alsa (cf, section));
00210 }
00211
00212
00213 void Alsa_Register (DriverTable* table)
00214 {
00215 table->AddDriver("alsa", Alsa_Init);
00216 }
00217
00219
00221
00222
00223 bool Alsa::AddStoredSample (StoredSample *newSample)
00224 {
00225 if (samplesHead == NULL)
00226 {
00227 samplesHead = samplesTail = newSample;
00228 }
00229 else
00230 {
00231 samplesTail->next = newSample;
00232 samplesTail = newSample;
00233 }
00234
00235 return true;
00236 }
00237
00238 bool Alsa::AddStoredSample (player_audio_wav_t *waveData)
00239 {
00240 StoredSample *newSample = NULL;
00241 if ((newSample = new StoredSample) == NULL)
00242 {
00243 PLAYER_ERROR ("Failed to allocate memory for new stored sample");
00244 return false;
00245 }
00246
00247 if ((newSample->sample = new AudioSample) == NULL)
00248 {
00249 PLAYER_ERROR ("Failed to allocate memory for new stored audio sample");
00250 delete newSample;
00251 return false;
00252 }
00253
00254 if (!newSample->sample->FromPlayer (waveData))
00255 {
00256 delete newSample->sample;
00257 delete newSample;
00258 return false;
00259 }
00260
00261 newSample->index = nextSampleIdx++;
00262 newSample->next = NULL;
00263
00264 if (debugLevel >= 1)
00265 cout << "ALSA: Added stored sample to list at index " << newSample->index << endl;
00266 if (debugLevel >= 3)
00267 newSample->sample->PrintWaveInfo ();
00268 return AddStoredSample (newSample);
00269 }
00270
00271 bool Alsa::AddStoredSample (const char *filePath)
00272 {
00273 StoredSample *newSample = NULL;
00274 if ((newSample = new StoredSample) == NULL)
00275 {
00276 PLAYER_ERROR ("Failed to allocate memory for new stored sample");
00277 return false;
00278 }
00279
00280 if ((newSample->sample = new AudioSample) == NULL)
00281 {
00282 PLAYER_ERROR ("Failed to allocate memory for new stored audio sample");
00283 delete newSample;
00284 return false;
00285 }
00286
00287 if (!newSample->sample->LoadFile (filePath))
00288 {
00289 delete newSample->sample;
00290 delete newSample;
00291 return false;
00292 }
00293
00294 newSample->index = nextSampleIdx++;
00295 newSample->next = NULL;
00296
00297 if (debugLevel >= 1)
00298 cout << "ALSA: Added stored sample " << filePath << " to list at index " << newSample->index << endl;
00299 if (debugLevel >= 3)
00300 newSample->sample->PrintWaveInfo ();
00301 return AddStoredSample (newSample);
00302 }
00303
00304
00305 StoredSample* Alsa::GetSampleAtIndex (int index)
00306 {
00307 if (samplesHead)
00308 {
00309 StoredSample *currentSample = samplesHead;
00310 while (currentSample != NULL)
00311 {
00312 if (currentSample->index == index)
00313 return currentSample;
00314 currentSample = currentSample->next;
00315 }
00316 }
00317 return NULL;
00318 }
00319
00321
00323
00324
00325 void Alsa::ClearQueue (void)
00326 {
00327 QueueItem *currentItem = queueHead;
00328 QueueItem *previousItem = NULL;
00329
00330 while (currentItem != NULL)
00331 {
00332 if (currentItem->temp)
00333 delete currentItem->sample;
00334 previousItem = currentItem;
00335 currentItem = currentItem->next;
00336 delete previousItem;
00337 }
00338 queueHead = NULL;
00339 queueTail = NULL;
00340 }
00341
00342 bool Alsa::AddToQueue (QueueItem *newItem)
00343 {
00344 if (!useQueue)
00345 {
00346 StopPlayback ();
00347 ClearQueue ();
00348 }
00349
00350 if (queueHead == NULL)
00351 {
00352 queueHead = queueTail = newItem;
00353 }
00354 else
00355 {
00356 queueTail->next = newItem;
00357 queueTail = newItem;
00358 }
00359
00360 return true;
00361 }
00362
00363 bool Alsa::AddToQueue (player_audio_wav_t *waveData)
00364 {
00365 QueueItem *newItem = NULL;
00366
00367 if ((newItem = new QueueItem) == NULL)
00368 {
00369 PLAYER_ERROR ("Failed to allocate memory for new queue item");
00370 return false;
00371 }
00372
00373 if ((newItem->sample = new AudioSample) == NULL)
00374 {
00375 PLAYER_ERROR ("Failed to allocate memory for new audio sample");
00376 delete newItem;
00377 return false;
00378 }
00379
00380 if (!newItem->sample->FromPlayer (waveData))
00381 {
00382 delete newItem->sample;
00383 delete newItem;
00384 return false;
00385 }
00386
00387 newItem->temp = true;
00388 newItem->next = NULL;
00389
00390
00391
00392 if (silenceTime != 0 && queueHead != NULL)
00393 {
00394 if (!AddSilence (silenceTime, newItem->sample))
00395 {
00396 delete newItem->sample;
00397 delete newItem;
00398 return false;
00399 }
00400 }
00401
00402 return AddToQueue (newItem);
00403 }
00404
00405 bool Alsa::AddToQueue (AudioSample *sample)
00406 {
00407 QueueItem *newItem = NULL;
00408
00409 if ((newItem = new QueueItem) == NULL)
00410 {
00411 PLAYER_ERROR ("Failed to allocate memory for new queue item");
00412 return false;
00413 }
00414
00415 newItem->sample = sample;
00416 newItem->temp = false;
00417 newItem->next = NULL;
00418
00419
00420
00421 if (silenceTime != 0 && queueHead != NULL)
00422 {
00423 if (!AddSilence (silenceTime, sample))
00424 {
00425 delete newItem;
00426 return false;
00427 }
00428 }
00429
00430 return AddToQueue (newItem);
00431 }
00432
00433
00434
00435
00436
00437 bool Alsa::AddSilence (uint32_t time, AudioSample *format)
00438 {
00439 QueueItem *newItem = NULL;
00440
00441 if ((newItem = new QueueItem) == NULL)
00442 {
00443 PLAYER_ERROR ("Failed to allocate memory for silence queue item");
00444 return false;
00445 }
00446
00447 if ((newItem->sample = new AudioSample) == NULL)
00448 {
00449 PLAYER_ERROR ("Failed to allocate memory for silence audio sample");
00450 delete newItem;
00451 return false;
00452 }
00453
00454 newItem->temp = true;
00455 newItem->next = NULL;
00456
00457
00458 newItem->sample->ClearSample ();
00459
00460 newItem->sample->CopyFormat (format);
00461
00462 if (!newItem->sample->FillSilence (time))
00463 {
00464 delete newItem->sample;
00465 delete newItem;
00466 return false;
00467 }
00468
00469 return AddToQueue (newItem);
00470 }
00471
00472 void Alsa::AdvanceQueue (void)
00473 {
00474
00475 QueueItem *oldHead = queueHead;
00476 queueHead = queueHead->next;
00477
00478
00479 if (oldHead->temp)
00480 delete oldHead->sample;
00481 else
00482
00483 oldHead->sample->SetDataPosition (0);
00484 delete oldHead;
00485
00486
00487
00488
00489
00490
00491 }
00492
00494
00496
00497 bool Alsa::SetupPlayBack (void)
00498 {
00499
00500 if (!pbDevice)
00501 return false;
00502
00503
00504 if (snd_pcm_open (&pbHandle, pbDevice, SND_PCM_STREAM_PLAYBACK, 0) < 0)
00505 {
00506 PLAYER_ERROR1 ("Error opening PCM device %s for playback", pbDevice);
00507 return false;
00508 }
00509
00510
00511
00512
00513
00514
00515 numPBFDs = snd_pcm_poll_descriptors_count (pbHandle);
00516 if ((pbFDs = (struct pollfd*) new struct pollfd[numPBFDs]) == NULL)
00517 {
00518 PLAYER_ERROR ("Error allocating memory for playback file descriptors");
00519 return false;
00520 }
00521 snd_pcm_poll_descriptors (pbHandle, pbFDs, numPBFDs);
00522
00523 return true;
00524 }
00525
00526
00527 bool Alsa::SetPBParams (AudioSample *sample)
00528 {
00529 snd_pcm_hw_params_t *hwparams;
00530 snd_pcm_sw_params_t *swparams;
00531
00532
00533 snd_pcm_hw_params_alloca(&hwparams);
00534
00535
00536 if (snd_pcm_hw_params_any (pbHandle, hwparams) < 0)
00537 {
00538 PLAYER_ERROR ("Cannot configure this playback device");
00539 return false;
00540 }
00541
00542 unsigned int exactRate;
00543
00544
00545 if (snd_pcm_hw_params_set_access (pbHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
00546 {
00547 PLAYER_ERROR ("Error setting interleaved access for playback device");
00548 return false;
00549 }
00550
00551
00552 snd_pcm_format_t format;
00553 switch (sample->GetBitsPerSample ())
00554 {
00555 case 8:
00556 format = SND_PCM_FORMAT_U8;
00557 break;
00558 case 16:
00559 format = SND_PCM_FORMAT_S16_LE;
00560 break;
00561 case 24:
00562 if ((sample->GetBlockAlign () / sample->GetNumChannels ()) == 3)
00563 format = SND_PCM_FORMAT_S24_3LE;
00564 else
00565 format = SND_PCM_FORMAT_S24_LE;
00566 break;
00567 case 32:
00568 format = SND_PCM_FORMAT_S32_LE;
00569 break;
00570 default:
00571 PLAYER_ERROR ("Cannot play audio with this format");
00572 return false;
00573 }
00574 if (snd_pcm_hw_params_set_format (pbHandle, hwparams, format) < 0)
00575 {
00576 PLAYER_ERROR ("Error setting format for playback device");
00577 return false;
00578 }
00579
00580 exactRate = sample->GetSampleRate ();
00581 if (snd_pcm_hw_params_set_rate_near (pbHandle, hwparams, &exactRate, 0) < 0)
00582 {
00583 PLAYER_ERROR ("Error setting sample rate for playback device");
00584 return false;
00585 }
00586 if (exactRate != sample->GetSampleRate ())
00587 PLAYER_WARN2 ("Rate %dHz not supported by hardware for playback device, using %dHz instead", sample->GetSampleRate (), exactRate);
00588
00589
00590 if (snd_pcm_hw_params_set_channels(pbHandle, hwparams, sample->GetNumChannels ()) < 0)
00591 {
00592 PLAYER_ERROR ("Error setting channels for playback device");
00593 return false;
00594 }
00595
00596
00597 actPBBufferTime = cfgPBBufferTime * 1000;
00598 if (snd_pcm_hw_params_set_buffer_time_near (pbHandle, hwparams, &actPBBufferTime, 0) < 0)
00599 {
00600 PLAYER_ERROR ("Error setting periods for playback device");
00601 return false;
00602 }
00603 if (actPBBufferTime < cfgPBBufferTime * 900)
00604 PLAYER_WARN2 ("Buffer length for playback device reduced from %dus to %dus", cfgPBBufferTime * 1000, actPBBufferTime);
00605
00606
00607
00608
00609 actPBPeriodTime = cfgPBPeriodTime * 1000;
00610 if (actPBPeriodTime > (actPBBufferTime / 2))
00611 {
00612 actPBPeriodTime = (actPBBufferTime / 2);
00613 PLAYER_WARN1 ("Period time for playback device too long, reduced to %dms", actPBPeriodTime / 1000);
00614 }
00615 if (snd_pcm_hw_params_set_period_time_near (pbHandle, hwparams, &actPBPeriodTime, 0) < 0)
00616 {
00617 PLAYER_ERROR ("Error setting period time for playback device");
00618 return false;
00619 }
00620 if (actPBPeriodTime < cfgPBPeriodTime * 900)
00621 PLAYER_WARN2 ("Period length for playback device reduced from %dms to %dms", cfgPBPeriodTime, actPBPeriodTime / 1000);
00622
00623 snd_pcm_hw_params_get_period_size (hwparams, &pbPeriodSize, 0);
00624
00625
00626 if (periodBuffer != NULL)
00627 delete[] periodBuffer;
00628 if ((periodBuffer = new uint8_t[pbPeriodSize * sample->GetBlockAlign ()]) == NULL)
00629 {
00630 PLAYER_ERROR ("Failed to allocate memory for period buffer");
00631 return false;
00632 }
00633
00634
00635 if (snd_pcm_hw_params (pbHandle, hwparams) < 0)
00636 {
00637 PLAYER_ERROR ("Error setting HW params for playback device");
00638 return false;
00639 }
00640
00641
00642 snd_pcm_sw_params_alloca (&swparams);
00643
00644 if (snd_pcm_sw_params_current (pbHandle, swparams) < 0)
00645 {
00646 PLAYER_ERROR ("Error getting current SW params for playback device");
00647 return false;
00648 }
00649
00650 if (snd_pcm_sw_params_set_avail_min (pbHandle, swparams, pbPeriodSize) < 0)
00651 {
00652 PLAYER_ERROR ("Error setting avil_min notification for playback device");
00653 return false;
00654 }
00655
00656 if (snd_pcm_sw_params (pbHandle, swparams) < 0)
00657 {
00658 PLAYER_ERROR ("Error setting SW params for playback device");
00659 return false;
00660 }
00661
00662 return true;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 void Alsa::PlaybackCallback (int numFrames)
00813 {
00814 int framesToWrite = 0;
00815
00816
00817
00818 while (framesToWrite < numFrames && playState == PB_STATE_PLAYING)
00819 {
00820 int framesToCopy = numFrames - framesToWrite;
00821
00822
00823
00824 int framesCopied = queueHead->sample->GetData (framesToCopy, &periodBuffer[framesToWrite * queueHead->sample->GetBlockAlign ()]);
00825
00826 if (framesCopied < 0)
00827 {
00828
00829
00830 PLAYER_ERROR ("Error reading wave data");
00831 playState = PB_STATE_DRAIN;
00832 }
00833
00834 else if (framesCopied < framesToCopy)
00835 {
00836
00837
00838 if (queueHead->next != NULL)
00839 {
00840 if (queueHead->sample->SameFormat (queueHead->next->sample))
00841 AdvanceQueue ();
00842
00843 else
00844 playState = PB_STATE_DRAIN;
00845 }
00846
00847 else
00848 {
00849 playState = PB_STATE_DRAIN;
00850 }
00851
00852 framesToWrite += framesCopied;
00853 }
00854
00855 else
00856 framesToWrite += framesCopied;
00857 }
00858
00859
00860 uint8_t *dataPos = periodBuffer;
00861 while (framesToWrite > 0)
00862 {
00863 int framesWritten = snd_pcm_writei (pbHandle, dataPos, framesToWrite);
00864 if (framesWritten > 0 && framesWritten <= framesToWrite)
00865 {
00866 snd_pcm_wait (pbHandle, 100);
00867
00868 framesToWrite -= framesWritten;
00869
00870 dataPos += framesWritten * queueHead->sample->GetBlockAlign ();
00871 }
00872 else if (framesWritten == -EAGAIN)
00873 {
00874 snd_pcm_wait (pbHandle, 100);
00875 }
00876 else if (framesWritten == -EPIPE)
00877 {
00878 PLAYER_WARN ("Buffer underrun occured during playback");
00879
00880 snd_pcm_prepare (pbHandle);
00881 }
00882 else
00883 {
00884 PLAYER_ERROR2 ("Error writing to playback buffer: (%d) %s", framesWritten, snd_strerror (framesWritten));
00885 }
00886 };
00887
00888
00889
00890
00891
00892
00893
00894 if (playState == PB_STATE_DRAIN)
00895 {
00896
00897 snd_pcm_drain (pbHandle);
00898
00899
00900
00901
00902 }
00903 }
00904
00906
00908
00909 bool Alsa::SetupRecord (void)
00910 {
00911
00912 if (!recDevice)
00913 return false;
00914
00915
00916 if (snd_pcm_open (&recHandle, recDevice, SND_PCM_STREAM_CAPTURE, 0) < 0)
00917 {
00918 PLAYER_ERROR1 ("Error opening PCM device %s for recording", recDevice);
00919 return false;
00920 }
00921
00922
00923 if (!SetRecParams ())
00924 return false;
00925
00926
00927 numRecFDs = snd_pcm_poll_descriptors_count (recHandle);
00928 if ((recFDs = (struct pollfd*) new struct pollfd[numRecFDs]) == NULL)
00929 {
00930 PLAYER_ERROR ("Error allocating memory for record file descriptors");
00931 return false;
00932 }
00933 snd_pcm_poll_descriptors (recHandle, recFDs, numRecFDs);
00934
00935 return true;
00936 }
00937
00938
00939 bool Alsa::SetRecParams (void)
00940 {
00941 snd_pcm_hw_params_t *hwparams;
00942 snd_pcm_sw_params_t *swparams;
00943
00944
00945 snd_pcm_hw_params_alloca(&hwparams);
00946
00947
00948 if (snd_pcm_hw_params_any (recHandle, hwparams) < 0)
00949 {
00950 PLAYER_ERROR ("Cannot configure this recording device");
00951 return false;
00952 }
00953
00954 unsigned int exactRate;
00955
00956
00957 if (snd_pcm_hw_params_set_access (recHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
00958 {
00959 PLAYER_ERROR ("Error setting interleaved access for recording device");
00960 return false;
00961 }
00962
00963
00964 snd_pcm_format_t format;
00965 switch (recBits)
00966 {
00967 case 8:
00968 format = SND_PCM_FORMAT_U8;
00969 break;
00970 case 16:
00971 format = SND_PCM_FORMAT_S16_LE;
00972 break;
00973 case 24:
00974 format = SND_PCM_FORMAT_S24_LE;
00975 break;
00976 case 32:
00977 format = SND_PCM_FORMAT_S32_LE;
00978 break;
00979 default:
00980 PLAYER_ERROR ("Cannot record audio with this format");
00981 return false;
00982 }
00983 if (snd_pcm_hw_params_set_format (recHandle, hwparams, format) < 0)
00984 {
00985 PLAYER_ERROR ("Error setting format for recording device");
00986 return false;
00987 }
00988
00989 exactRate = recSampleRate;
00990 if (snd_pcm_hw_params_set_rate_near (recHandle, hwparams, &exactRate, 0) < 0)
00991 {
00992 PLAYER_ERROR ("Error setting sample rate for recording device");
00993 return false;
00994 }
00995 if (exactRate != recSampleRate)
00996 PLAYER_WARN2 ("Rate %dHz not supported by hardware for recording device, using %dHz instead", recSampleRate, exactRate);
00997 recSampleRate = exactRate;
00998
00999
01000 if (snd_pcm_hw_params_set_channels (recHandle, hwparams, recNumChannels) < 0)
01001 {
01002 PLAYER_ERROR ("Error setting channels for recording device");
01003 return false;
01004 }
01005
01006
01007 actRecBufferTime = cfgRecBufferTime * 1000;
01008 if (snd_pcm_hw_params_set_buffer_time_near (recHandle, hwparams, &actRecBufferTime, 0) < 0)
01009 {
01010 PLAYER_ERROR ("Error setting periods for recording device");
01011 return false;
01012 }
01013 if (actRecBufferTime < cfgRecBufferTime * 900)
01014 PLAYER_WARN2 ("Buffer length for recording device reduced from %dus to %dus", cfgRecBufferTime * 1000, actRecBufferTime);
01015
01016
01017
01018
01019 actRecPeriodTime = cfgRecPeriodTime * 1000;
01020 if (actRecPeriodTime > (actRecBufferTime / 2))
01021 {
01022 actRecPeriodTime = (actRecBufferTime / 2);
01023 PLAYER_WARN1 ("Period time for recording device too long, reduced to %dms", actRecPeriodTime / 1000);
01024 }
01025 if (snd_pcm_hw_params_set_period_time_near (recHandle, hwparams, &actRecPeriodTime, 0) < 0)
01026 {
01027 PLAYER_ERROR ("Error setting period time for recording device");
01028 return false;
01029 }
01030 if (actRecPeriodTime < cfgRecPeriodTime * 900)
01031 PLAYER_WARN2 ("Period length for recording device reduced from %dms to %dms", cfgRecPeriodTime, actRecPeriodTime / 1000);
01032
01033 snd_pcm_hw_params_get_period_size (hwparams, &recPeriodSize, 0);
01034
01035
01036 if (snd_pcm_hw_params (recHandle, hwparams) < 0)
01037 {
01038 PLAYER_ERROR ("Error setting HW params for recording device");
01039 return false;
01040 }
01041
01042
01043 snd_pcm_sw_params_alloca (&swparams);
01044
01045 if (snd_pcm_sw_params_current (recHandle, swparams) < 0)
01046 {
01047 PLAYER_ERROR ("Error getting current SW params for recording device");
01048 return false;
01049 }
01050
01051 if (snd_pcm_sw_params_set_avail_min (recHandle, swparams, recPeriodSize) < 0)
01052 {
01053 PLAYER_ERROR ("Error setting avil_min notification for recording device");
01054 return false;
01055 }
01056
01057 if (snd_pcm_sw_params (recHandle, swparams) < 0)
01058 {
01059 PLAYER_ERROR ("Error setting SW params for recording device");
01060 return false;
01061 }
01062
01063 return true;
01064 }
01065
01066
01067
01068 bool Alsa::SetupRecordBuffer (uint32_t length)
01069 {
01070
01071 if (recData)
01072 {
01073 PLAYER_WARN ("recData not empty before starting recording");
01074 delete[] recData;
01075 }
01076
01077 uint32_t bytesPerSec = recNumChannels * (recBits / 8) * recSampleRate;
01078 recDataLength = static_cast<uint32_t> (bytesPerSec * (length / 1000.0f));
01079
01080 recDataLength = recDataLength - (recDataLength % ((recBits / 8) * recNumChannels));
01081 if ((recData = new uint8_t[recDataLength]) == NULL)
01082 {
01083 PLAYER_ERROR ("Failed to allocate memory for recorded data buffer");
01084 return false;
01085 }
01086 recDataOffset = 0;
01087
01088 return true;
01089 }
01090
01091
01092
01093 void Alsa::RecordCallback (int numFrames)
01094 {
01095 int totalRead = 0;
01096
01097
01098 if (!recData)
01099 {
01100 PLAYER_ERROR ("Tried to record to NULL data buffer");
01101 return;
01102 }
01103
01104 while (totalRead < numFrames)
01105 {
01106 int framesToRead = numFrames - totalRead;
01107 if (snd_pcm_frames_to_bytes (recHandle, framesToRead) + recDataOffset > recDataLength)
01108
01109 framesToRead = snd_pcm_bytes_to_frames (recHandle, recDataLength - recDataOffset);
01110 int framesRead = snd_pcm_readi (recHandle, &recData[recDataOffset], framesToRead);
01111
01112 if (framesRead > 0)
01113 {
01114 recDataOffset += snd_pcm_frames_to_bytes (recHandle, framesRead);
01115 totalRead += framesRead;
01116
01117 if (recDataOffset >= recDataLength)
01118 HandleRecordedData ();
01119 }
01120
01121 else if (framesRead == -EPIPE)
01122 {
01123 PLAYER_WARN ("Buffer overrun occured during recording");
01124
01125 snd_pcm_prepare (recHandle);
01126 }
01127
01128 else
01129 {
01130 PLAYER_ERROR2 ("Error reading from record buffer: (%d) %s", framesRead, snd_strerror (framesRead));
01131 StopRecording ();
01132 }
01133 }
01134 }
01135
01136
01137 void Alsa::HandleRecordedData (void)
01138 {
01139
01140 if (recDest < 0)
01141 {
01142 PublishRecordedData ();
01143 return;
01144 }
01145
01146
01147
01148
01149
01150
01151
01152 StoredSample *sampleSlot;
01153 if ((sampleSlot = GetSampleAtIndex (recDest)) == NULL)
01154 {
01155 PLAYER_ERROR1 ("Couldn't find sample at index %d", recDest);
01156 }
01157 else
01158 {
01159
01160 AudioSample *newSample = NULL;
01161 if ((newSample = new AudioSample (recData, recDataLength, recNumChannels, recSampleRate, recBits)) == NULL)
01162 {
01163 PLAYER_ERROR ("Failed to allocate memory for new audio sample");
01164 }
01165 else
01166 {
01167
01168 if (sampleSlot->sample)
01169 delete sampleSlot->sample;
01170
01171 sampleSlot->sample = newSample;
01172 }
01173 }
01174
01175
01176 delete[] recData;
01177 recData = NULL;
01178 StopRecording ();
01179 }
01180
01181
01182 void Alsa::PublishRecordedData (void)
01183 {
01184
01185 if (!recData || recDataOffset == 0)
01186 return;
01187
01188
01189 player_audio_wav_t packet;
01190 memset (&packet, 0, sizeof (player_audio_wav_t));
01191
01192
01193 packet.format = PLAYER_AUDIO_FORMAT_RAW;
01194 if (recNumChannels == 2)
01195 packet.format |= PLAYER_AUDIO_STEREO;
01196 else if (recNumChannels != 1)
01197 {
01198 PLAYER_ERROR ("Cannot convert wave to player struct: wrong number of channels");
01199 delete recData;
01200 recData = NULL;
01201 StopRecording ();
01202 return;
01203 }
01204 switch (recSampleRate)
01205 {
01206 case 11025:
01207 packet.format |= PLAYER_AUDIO_FREQ_11k;
01208 break;
01209 case 22050:
01210 packet.format |= PLAYER_AUDIO_FREQ_22k;
01211 break;
01212 case 44100:
01213 packet.format |= PLAYER_AUDIO_FREQ_44k;
01214 break;
01215 case 48000:
01216 packet.format |= PLAYER_AUDIO_FREQ_48k;
01217 break;
01218 default:
01219 PLAYER_ERROR ("Cannot convert wave to player struct: wrong sample rate");
01220 delete recData;
01221 recData = NULL;
01222 StopRecording ();
01223 return;
01224 }
01225 switch (recBits)
01226 {
01227 case 8:
01228 packet.format |= PLAYER_AUDIO_8BIT;
01229 break;
01230 case 16:
01231 packet.format |= PLAYER_AUDIO_16BIT;
01232 break;
01233 case 24:
01234 packet.format |= PLAYER_AUDIO_24BIT;
01235 break;
01236 default:
01237 PLAYER_ERROR ("Cannot convert wave to player struct: wrong format (bits per sample)");
01238 delete recData;
01239 recData = NULL;
01240 StopRecording ();
01241 return;
01242 }
01243
01244
01245 uint32_t copiedOffset = 0;
01246 while (copiedOffset < recDataOffset)
01247 {
01248
01249 uint32_t bytesToCopy;
01250 if ((recDataOffset - copiedOffset) < (PLAYER_MAX_PAYLOAD_SIZE - sizeof (player_audio_wav_t)))
01251 bytesToCopy = recDataOffset - copiedOffset;
01252 else
01253 bytesToCopy = (PLAYER_MAX_PAYLOAD_SIZE - sizeof (player_audio_wav_t));
01254
01255 if ((packet.data = new uint8_t[bytesToCopy]) == NULL)
01256 {
01257 PLAYER_ERROR ("Failed to allocate temp space");
01258 delete recData;
01259 recData = NULL;
01260 StopRecording ();
01261 return;
01262 }
01263 memcpy (packet.data, &recData[copiedOffset], bytesToCopy);
01264 copiedOffset += bytesToCopy;
01265 packet.data_count = bytesToCopy;
01266
01267
01268 Publish (device_addr, PLAYER_MSGTYPE_DATA, PLAYER_AUDIO_DATA_WAV_REC, reinterpret_cast<void*> (&packet), sizeof (player_audio_wav_t), NULL);
01269 delete[] packet.data;
01270 }
01271
01272 recDataOffset = 0;
01273 }
01274
01276
01278
01279
01280 void Alsa::StartPlayback (void)
01281 {
01282
01283 if (playState != PB_STATE_STOPPED || !pbHandle)
01284 return;
01285
01286
01287 if (queueHead != NULL)
01288 {
01289 if (debugLevel >= 4)
01290 {
01291 cout << "ALSA: Starting playback, sample info:" << endl;
01292 queueHead->sample->PrintWaveInfo ();
01293 }
01294
01295 SetPBParams (queueHead->sample);
01296
01297 playState = PB_STATE_PLAYING;
01298 }
01299
01300
01301 SendStateMessage ();
01302 }
01303
01304
01305
01306 void Alsa::StopPlayback (void)
01307 {
01308 if (debugLevel >= 4)
01309 cout << "ALSA: Stopping playback" << endl;
01310
01311
01312 playState = PB_STATE_STOPPED;
01313
01314 if (pbHandle)
01315 snd_pcm_drop (pbHandle);
01316
01317
01318 SendStateMessage ();
01319 }
01320
01321
01322 void Alsa::StartRecording (void)
01323 {
01324
01325 if (recState != PB_STATE_STOPPED || !recHandle)
01326 return;
01327
01328 if (!recData)
01329 {
01330 PLAYER_ERROR ("Tried to start recording with no local data buffer");
01331 return;
01332 }
01333
01334 if (debugLevel >= 4)
01335 cout << "ALSA: Starting recording, destination: " << ((recDest < 0) ? "clients" : "sample") << endl;
01336
01337 recDataOffset = 0;
01338
01339 snd_pcm_prepare (recHandle);
01340
01341 int result = 0;
01342 if ((result = snd_pcm_start (recHandle)) < 0)
01343 {
01344 PLAYER_ERROR2 ("Error starting recording: (%d) %s", result, snd_strerror (result));
01345 delete recData;
01346 recData = NULL;
01347 return;
01348 }
01349
01350 recState = PB_STATE_RECORDING;
01351
01352
01353 SendStateMessage ();
01354 }
01355
01356
01357 void Alsa::StopRecording (void)
01358 {
01359 if (debugLevel >= 4)
01360 cout << "ALSA: Stopping recording" << endl;
01361
01362
01363 snd_pcm_drop (recHandle);
01364
01365 recState = PB_STATE_STOPPED;
01366
01367 if (recData)
01368 {
01369 HandleRecordedData ();
01370 delete[] recData;
01371 recData = NULL;
01372 }
01373 recDataOffset = 0;
01374
01375
01376 SendStateMessage ();
01377 }
01378
01380
01382
01383
01384 bool Alsa::SetupMixer (void)
01385 {
01386
01387 if (snd_mixer_open (&mixerHandle, 0) < 0)
01388 {
01389 PLAYER_WARN ("Could not open mixer");
01390 return false;
01391 }
01392
01393
01394 if (snd_mixer_attach (mixerHandle, mixerDevice) < 0)
01395 {
01396 PLAYER_WARN1 ("Could not attach mixer to mixer device %s", mixerDevice);
01397 return false;
01398 }
01399
01400
01401 if (snd_mixer_selem_register (mixerHandle, NULL, NULL) < 0)
01402 {
01403 PLAYER_WARN ("Could not register mixer");
01404 return false;
01405 }
01406
01407
01408 if (snd_mixer_load (mixerHandle) < 0)
01409 {
01410 PLAYER_WARN ("Could not load mixer elements");
01411 return false;
01412 }
01413
01414
01415 if (!EnumMixerElements ())
01416 return false;
01417
01418 return true;
01419 }
01420
01421
01422
01423 bool Alsa::EnumMixerElements (void)
01424 {
01425 MixerElement *elements = NULL;
01426 snd_mixer_elem_t *elem = NULL;
01427 uint32_t count = 0;
01428
01429
01430 for (elem = snd_mixer_first_elem (mixerHandle); elem != NULL; elem = snd_mixer_elem_next (elem))
01431 {
01432 if (snd_mixer_elem_get_type (elem) == SND_MIXER_ELEM_SIMPLE && snd_mixer_selem_is_active (elem))
01433 count++;
01434 else if (debugLevel >= 5)
01435 cout << "ALSA: Skipping non-SND_MIXER_ELEM_SIMPLE or inactive element" << endl;
01436 }
01437
01438 if (debugLevel >= 5)
01439 cout << "ALSA: Found " << count << " elements to enumerate" << endl;
01440
01441
01442 if (count <= 0)
01443 {
01444 PLAYER_WARN ("Found zero or less mixer elements");
01445 return false;
01446 }
01447 if ((elements = new MixerElement[count]) == NULL)
01448 {
01449 PLAYER_WARN1 ("Failed to allocate memory to store %d elements", count);
01450 return false;
01451 }
01452 memset (elements, 0, sizeof (MixerElement) * count);
01453
01454
01455 uint32_t ii = 0;
01456 for (elem = snd_mixer_first_elem (mixerHandle); elem != NULL; elem = snd_mixer_elem_next (elem), ii++)
01457 {
01458 if (snd_mixer_elem_get_type (elem) == SND_MIXER_ELEM_SIMPLE && snd_mixer_selem_is_active (elem))
01459 {
01460 elements[ii].elem = elem;
01461 if (!EnumElementCaps (&(elements[ii])))
01462 {
01463 CleanUpMixerElements (elements, count);
01464 return false;
01465 }
01466 }
01467 }
01468
01469
01470 MixerElement *splitElems = NULL;
01471 uint32_t newCount = count;
01472 if ((splitElems = SplitElements (elements, newCount)) == NULL)
01473 {
01474 PLAYER_WARN ("Error splitting mixer elements");
01475 CleanUpMixerElements (elements, count);
01476 return false;
01477 }
01478
01479
01480 CleanUpMixerElements (elements, count);
01481
01482
01483
01484 uint32_t newNewCount = newCount;
01485 if (mixerFilters)
01486 {
01487 if ((mixerElements = FilterElements (splitElems, newNewCount)) == NULL)
01488 {
01489 PLAYER_WARN ("Error filtering mixer elements");
01490 CleanUpMixerElements (splitElems, newCount);
01491 return false;
01492 }
01493
01494 }
01495 else
01496 mixerElements = splitElems;
01497
01498 numElements = newNewCount;
01499
01500 if (debugLevel >= 2)
01501 PrintMixerElements (mixerElements, numElements);
01502 return true;
01503 }
01504
01505
01506 bool Alsa::EnumElementCaps (MixerElement *element)
01507 {
01508 snd_mixer_elem_t *elem = element->elem;
01509 if (!elem)
01510 {
01511 PLAYER_WARN ("Attempted to enumerate NULL element pointer");
01512 return false;
01513 }
01514
01515
01516 element->name = strdup (snd_mixer_selem_get_name (elem));
01517
01518
01519 if (snd_mixer_selem_has_playback_volume (elem))
01520 element->caps |= ELEMCAP_PLAYBACK_VOL;
01521 if (snd_mixer_selem_has_capture_volume (elem))
01522 element->caps |= ELEMCAP_CAPTURE_VOL;
01523 if (snd_mixer_selem_has_common_volume (elem))
01524 element->caps |= ELEMCAP_COMMON_VOL;
01525
01526 if (snd_mixer_selem_has_playback_switch (elem))
01527 element->caps |= ELEMCAP_PLAYBACK_SWITCH;
01528 if (snd_mixer_selem_has_capture_switch (elem))
01529 element->caps |= ELEMCAP_CAPTURE_SWITCH;
01530 if (snd_mixer_selem_has_common_switch (elem))
01531 element->caps |= ELEMCAP_COMMON_SWITCH;
01532
01533
01534
01535
01536
01537
01538 element->playSwitch = 1;
01539 element->capSwitch = 1;
01540 element->comSwitch = 1;
01541
01542 if (debugLevel >= 5)
01543 cout << "ALSA: Found mixer element: " << element->name << endl;
01544
01545 for (int ii = -1; ii <= (int) SND_MIXER_SCHN_LAST; ii++)
01546 {
01547 if (snd_mixer_selem_has_playback_channel (elem, static_cast<snd_mixer_selem_channel_id_t> (ii)))
01548 {
01549
01550 element->caps |= ELEMCAP_CAN_PLAYBACK;
01551
01552 if (!element->curPlayVol)
01553 snd_mixer_selem_get_playback_volume (elem, static_cast<snd_mixer_selem_channel_id_t> (ii), &(element->curPlayVol));
01554
01555 if (element->caps & ELEMCAP_PLAYBACK_SWITCH)
01556 snd_mixer_selem_get_playback_switch (elem, static_cast<snd_mixer_selem_channel_id_t> (ii), &element->playSwitch);
01557 }
01558 if (snd_mixer_selem_has_capture_channel (elem, static_cast<snd_mixer_selem_channel_id_t> (ii)))
01559 {
01560
01561 element->caps |= ELEMCAP_CAN_CAPTURE;
01562
01563 if (!element->curCapVol)
01564 snd_mixer_selem_get_capture_volume (elem, static_cast<snd_mixer_selem_channel_id_t> (ii), &(element->curCapVol));
01565
01566 if (element->caps & ELEMCAP_CAPTURE_SWITCH)
01567 snd_mixer_selem_get_capture_switch (elem, static_cast<snd_mixer_selem_channel_id_t> (ii), &element->capSwitch);
01568 }
01569 }
01570
01571
01572 if ((element->caps & ELEMCAP_CAN_PLAYBACK) && (element->caps & ELEMCAP_PLAYBACK_VOL))
01573 {
01574 snd_mixer_selem_get_playback_volume_range (elem, &(element->minPlayVol), &(element->maxPlayVol));
01575 }
01576 if ((element->caps & ELEMCAP_CAN_CAPTURE) && (element->caps & ELEMCAP_CAPTURE_VOL))
01577 {
01578 snd_mixer_selem_get_capture_volume_range (elem, &(element->minCapVol), &(element->maxCapVol));
01579 }
01580 if (element->caps & ELEMCAP_COMMON_VOL)
01581 {
01582
01583 element->minComVol = element->maxPlayVol ? element->minPlayVol : element->minCapVol;
01584 element->maxComVol = element->maxPlayVol ? element->maxPlayVol : element->maxCapVol;
01585 }
01586
01587
01588 if (element->caps & ELEMCAP_COMMON_SWITCH)
01589 element->comSwitch = element->playSwitch ? element->playSwitch : element->capSwitch;
01590
01591
01592
01593
01594
01595
01596 return true;
01597 }
01598
01599
01600
01601 MixerElement* Alsa::SplitElements (MixerElement *elements, uint32_t &count)
01602 {
01603 MixerElement *result = NULL;
01604
01605
01606 uint32_t numSplitElements = 0;
01607 for (uint32_t ii = 0; ii < count; ii++)
01608 {
01609 if ((elements[ii].caps & ELEMCAP_CAN_PLAYBACK) && (elements[ii].caps & ELEMCAP_CAN_CAPTURE) &&
01610 !(elements[ii].caps & ELEMCAP_COMMON_VOL) && !(elements[ii].caps & ELEMCAP_COMMON_SWITCH))
01611 numSplitElements += 2;
01612 else
01613 numSplitElements += 1;
01614 }
01615
01616
01617 if (numSplitElements <= 0)
01618 {
01619 PLAYER_WARN ("Found zero or less split mixer elements");
01620 return NULL;
01621 }
01622 if ((result = new MixerElement[numSplitElements]) == NULL)
01623 {
01624 PLAYER_WARN1 ("Failed to allocate memory to store %d split elements", numSplitElements);
01625 return NULL;
01626 }
01627 memset (result, 0, sizeof (MixerElement) * numSplitElements);
01628
01629
01630 uint32_t currentIndex = 0;
01631 for (uint32_t ii = 0; ii < count; ii++)
01632 {
01633
01634 if ((elements[ii].caps & ELEMCAP_CAN_PLAYBACK) && (elements[ii].caps & ELEMCAP_CAN_CAPTURE) &&
01635 !(elements[ii].caps & ELEMCAP_COMMON_VOL) && !(elements[ii].caps & ELEMCAP_COMMON_SWITCH))
01636 {
01637
01638
01639 result[currentIndex].elem = elements[ii].elem;
01640 result[currentIndex].caps = ELEMCAP_CAN_PLAYBACK;
01641 result[currentIndex].minPlayVol = elements[ii].minPlayVol;
01642 result[currentIndex].curPlayVol = elements[ii].curPlayVol;
01643 result[currentIndex].maxPlayVol = elements[ii].maxPlayVol;
01644 result[currentIndex].playSwitch = elements[ii].playSwitch;
01645 result[currentIndex].name = reinterpret_cast<char*> (malloc (strlen (elements[ii].name) + strlen (" (Playback)") + 1));
01646 strncpy (result[currentIndex].name, elements[ii].name, strlen (elements[ii].name) + 1);
01647 strncpy (&(result[currentIndex].name[strlen (elements[ii].name)]), " (Playback)", strlen (" (Playback)") + 1);
01648
01649
01650 result[currentIndex + 1].elem = elements[ii].elem;
01651 result[currentIndex + 1].caps = ELEMCAP_CAN_CAPTURE;
01652 result[currentIndex + 1].minCapVol = elements[ii].minCapVol;
01653 result[currentIndex + 1].curCapVol = elements[ii].curCapVol;
01654 result[currentIndex + 1].maxCapVol = elements[ii].maxCapVol;
01655 result[currentIndex + 1].capSwitch = elements[ii].capSwitch;
01656 result[currentIndex + 1].name = reinterpret_cast<char*> (malloc (strlen (elements[ii].name) + strlen (" (Capture)") + 1));
01657 strncpy (result[currentIndex + 1].name, elements[ii].name, strlen (elements[ii].name) + 1);
01658 strncpy (&(result[currentIndex + 1].name[strlen (elements[ii].name)]), " (Capture)", strlen (" (Capture)") + 1);
01659
01660 currentIndex += 2;
01661 }
01662
01663 else if ((elements[ii].caps & ELEMCAP_CAN_PLAYBACK) && !(elements[ii].caps & ELEMCAP_CAN_CAPTURE))
01664 {
01665
01666 result[currentIndex].elem = elements[ii].elem;
01667 result[currentIndex].caps = ELEMCAP_CAN_PLAYBACK;
01668 result[currentIndex].minPlayVol = elements[ii].minPlayVol;
01669 result[currentIndex].curPlayVol = elements[ii].curPlayVol;
01670 result[currentIndex].maxPlayVol = elements[ii].maxPlayVol;
01671 result[currentIndex].playSwitch = elements[ii].playSwitch;
01672 result[currentIndex].name = strdup (elements[ii].name);
01673
01674 currentIndex += 1;
01675 }
01676
01677 else if (!(elements[ii].caps & ELEMCAP_CAN_PLAYBACK) && (elements[ii].caps & ELEMCAP_CAN_CAPTURE))
01678 {
01679
01680 result[currentIndex].elem = elements[ii].elem;
01681 result[currentIndex].caps = ELEMCAP_CAN_CAPTURE;
01682 result[currentIndex].minCapVol = elements[ii].minCapVol;
01683 result[currentIndex].curCapVol = elements[ii].curCapVol;
01684 result[currentIndex].maxCapVol = elements[ii].maxCapVol;
01685 result[currentIndex].capSwitch = elements[ii].capSwitch;
01686 result[currentIndex].name = strdup (elements[ii].name);
01687
01688 currentIndex += 1;
01689 }
01690
01691 else
01692 {
01693 result[currentIndex].elem = elements[ii].elem;
01694 result[currentIndex].caps = ELEMCAP_CAN_PLAYBACK & ELEMCAP_CAN_CAPTURE & ELEMCAP_COMMON;
01695 result[currentIndex].minComVol = elements[ii].minComVol;
01696 result[currentIndex].curComVol = elements[ii].curComVol;
01697 result[currentIndex].maxComVol = elements[ii].maxComVol;
01698 result[currentIndex].comSwitch = elements[ii].comSwitch;
01699 result[currentIndex].name = strdup (elements[ii].name);
01700
01701 currentIndex += 1;
01702 }
01703 }
01704
01705 count = numSplitElements;
01706 return result;
01707 }
01708
01709
01710
01711 MixerElement* Alsa::FilterElements (MixerElement *elements, uint32_t &count)
01712 {
01713 MixerElement *result = NULL;
01714 bool *keep = NULL;
01715
01716
01717 if ((keep = new bool[count]) == NULL)
01718 {
01719 PLAYER_WARN ("Failed to allocate memory to check elements for filter matches");
01720 return NULL;
01721 }
01722 memset (keep, 0, sizeof (bool) * count);
01723
01724 if (debugLevel >= 5)
01725 cout << "Checking " << count << " mixer elements for filter matches" << endl;
01726
01727
01728 uint32_t filteredCount = 0;
01729 for (uint32_t ii = 0; ii < count; ii++)
01730 {
01731
01732 for (uint32_t jj = 0; mixerFilters[jj] != NULL; jj++)
01733 {
01734 if ((!mixerFilterExact && strcasestr (elements[ii].name, mixerFilters[jj]) != NULL) ||
01735 (mixerFilterExact && strcmp (elements[ii].name, mixerFilters[jj]) == 0))
01736 {
01737 if (debugLevel >= 5)
01738 cout << "Found match between " << elements[ii].name << " (" << ii << ") and " << mixerFilters[jj] << endl;
01739
01740 keep[ii] = true;
01741 filteredCount++;
01742 break;
01743 }
01744 }
01745 }
01746
01747
01748 if ((result = new MixerElement[filteredCount]) == NULL)
01749 {
01750 PLAYER_WARN ("Failed to allocate memory to store final list of filtered elements");
01751 return NULL;
01752 }
01753 if (debugLevel >= 5)
01754 cout << "Keeping " << filteredCount << " mixer elements" << endl;
01755
01756
01757 filteredCount = 0;
01758 for (uint32_t ii = 0; ii < count; ii++)
01759 {
01760 if (keep[ii])
01761 {
01762 memcpy (&result[filteredCount], &elements[ii], sizeof (MixerElement));
01763 if (debugLevel >= 5)
01764 cout << "Keeping mixer element \"" << result[filteredCount].name << "\" (" << ii << ")" << endl;
01765 filteredCount++;
01766 }
01767 else
01768 {
01769 if (debugLevel >= 5)
01770 cout << "Deleting mixer element \"" << elements[ii].name << "\" (" << ii << ")" << endl;
01771 if (elements[ii].name)
01772 free (elements[ii].name);
01773 }
01774 }
01775 count = filteredCount;
01776
01777
01778 delete[] elements;
01779
01780 delete[] keep;
01781
01782 return result;
01783 }
01784
01785
01786 void Alsa::CleanUpMixerElements (MixerElement *elements, uint32_t count)
01787 {
01788 for (uint32_t ii = 0; ii < count; ii++)
01789 {
01790 if (elements[ii].name)
01791 free (elements[ii].name);
01792 }
01793 delete[] elements;
01794 }
01795
01796
01797 void Alsa::MixerDetailsToPlayer (player_audio_mixer_channel_list_detail_t *dest)
01798 {
01799 memset (dest, 0, sizeof (player_audio_mixer_channel_list_detail_t));
01800
01801 dest->details_count = numElements;
01802 dest->default_output = 0;
01803 dest->default_input = 0;
01804
01805 for (uint32_t ii = 0; ii < numElements; ii++)
01806 {
01807 dest->details[ii].name_count = strlen (mixerElements[ii].name);
01808 strncpy (dest->details[ii].name, mixerElements[ii].name, strlen (mixerElements[ii].name) + 1);
01809 if ((mixerElements[ii].caps & ELEMCAP_CAN_PLAYBACK) && !(mixerElements[ii].caps & ELEMCAP_CAN_CAPTURE))
01810 dest->details[ii].caps = PLAYER_AUDIO_MIXER_CHANNEL_TYPE_OUTPUT;
01811 else if (!(mixerElements[ii].caps & ELEMCAP_CAN_PLAYBACK) && (mixerElements[ii].caps & ELEMCAP_CAN_CAPTURE))
01812 dest->details[ii].caps = PLAYER_AUDIO_MIXER_CHANNEL_TYPE_INPUT;
01813 else
01814 dest->details[ii].caps = PLAYER_AUDIO_MIXER_CHANNEL_TYPE_INPUT & PLAYER_AUDIO_MIXER_CHANNEL_TYPE_OUTPUT;
01815 }
01816 }
01817
01818
01819 void Alsa::MixerLevelsToPlayer (player_audio_mixer_channel_list_t *dest)
01820 {
01821 memset (dest, 0, sizeof (player_audio_mixer_channel_list_t));
01822
01823 dest->channels_count = numElements;
01824
01825 for (uint32_t ii = 0; ii < numElements; ii++)
01826 {
01827 long min = 0, cur = 0, max = 0;
01828 int switchStatus = 0;
01829 if (mixerElements[ii].caps & ELEMCAP_CAN_PLAYBACK)
01830 {
01831 min = mixerElements[ii].minPlayVol;
01832 cur = mixerElements[ii].curPlayVol;
01833 max = mixerElements[ii].maxPlayVol;
01834 switchStatus = mixerElements[ii].playSwitch;
01835 }
01836 else if (mixerElements[ii].caps & ELEMCAP_CAN_CAPTURE)
01837 {
01838 min = mixerElements[ii].minCapVol;
01839 cur = mixerElements[ii].curCapVol;
01840 max = mixerElements[ii].maxCapVol;
01841 switchStatus = mixerElements[ii].capSwitch;
01842 }
01843 else if (mixerElements[ii].caps & ELEMCAP_COMMON)
01844 {
01845 min = mixerElements[ii].minComVol;
01846 cur = mixerElements[ii].curComVol;
01847 max = mixerElements[ii].maxComVol;
01848 switchStatus = mixerElements[ii].comSwitch;
01849 }
01850 dest->channels[ii].amplitude = LevelToPlayer (min, max, cur);
01851 dest->channels[ii].active.state = switchStatus;
01852 dest->channels[ii].index = ii;
01853 }
01854 }
01855
01856
01857 void Alsa::SetElementLevel (uint32_t index, float level)
01858 {
01859 long newValue = 0;
01860
01861 if (mixerElements[index].caps & ELEMCAP_CAN_PLAYBACK)
01862 {
01863
01864 newValue = LevelFromPlayer (mixerElements[index].minPlayVol, mixerElements[index].maxPlayVol, level);
01865
01866 if (snd_mixer_selem_set_playback_volume_all (mixerElements[index].elem, newValue) < 0)
01867 {
01868 PLAYER_WARN1 ("Error setting playback level for element %d", index);
01869 }
01870 else
01871 mixerElements[index].curPlayVol = newValue;
01872 }
01873 else if (mixerElements[index].caps & ELEMCAP_CAN_CAPTURE)
01874 {
01875
01876 newValue = LevelFromPlayer (mixerElements[index].minCapVol, mixerElements[index].maxCapVol, level);
01877
01878 if (snd_mixer_selem_set_capture_volume_all (mixerElements[index].elem, newValue) < 0)
01879 {
01880 PLAYER_WARN1 ("Error setting capture level for element %d", index);
01881 }
01882 else
01883 mixerElements[index].curCapVol = newValue;
01884 }
01885 else if (mixerElements[index].caps & ELEMCAP_COMMON)
01886 {
01887
01888 newValue = LevelFromPlayer (mixerElements[index].minComVol, mixerElements[index].maxComVol, level);
01889
01890 if (snd_mixer_selem_set_playback_volume_all (mixerElements[index].elem, newValue) < 0)
01891 {
01892 PLAYER_WARN1 ("Error setting common level for element %d", index);
01893 }
01894 else
01895 mixerElements[index].curComVol = newValue;
01896 }
01897 }
01898
01899
01900 void Alsa::SetElementSwitch (uint32_t index, player_bool_t active)
01901 {
01902 if (mixerElements[index].caps & ELEMCAP_CAN_PLAYBACK)
01903 {
01904
01905 if (snd_mixer_selem_set_playback_switch_all (mixerElements[index].elem, active.state) < 0)
01906 {
01907 PLAYER_WARN1 ("Error setting playback switch for element %d", index);
01908 }
01909 else
01910 mixerElements[index].playSwitch = active.state;
01911 }
01912 else if (mixerElements[index].caps & ELEMCAP_CAN_CAPTURE)
01913 {
01914
01915 if (snd_mixer_selem_set_capture_switch_all (mixerElements[index].elem, active.state) < 0)
01916 {
01917 PLAYER_WARN1 ("Error setting capture switch for element %d", index);
01918 }
01919 else
01920 mixerElements[index].capSwitch = active.state;
01921 }
01922 else if (mixerElements[index].caps & ELEMCAP_COMMON)
01923 {
01924
01925 if (snd_mixer_selem_set_playback_switch_all (mixerElements[index].elem, active.state) < 0)
01926 {
01927 PLAYER_WARN1 ("Error setting common switch for element %d", index);
01928 }
01929 else
01930 mixerElements[index].comSwitch = active.state;
01931 }
01932 }
01933
01934
01935 void Alsa::PublishMixerData (void)
01936 {
01937 player_audio_mixer_channel_list_t data;
01938
01939 MixerLevelsToPlayer (&data);
01940 Publish (device_addr, PLAYER_MSGTYPE_DATA, PLAYER_AUDIO_DATA_MIXER_CHANNEL, reinterpret_cast<void*> (&data), sizeof (player_audio_mixer_channel_list_t), NULL);
01941 }
01942
01943
01944 float Alsa::LevelToPlayer (long min, long max, long level)
01945 {
01946 float result = 0.0f;
01947 if ((max - min) != 0)
01948 result = static_cast<float> (level - min) / static_cast<float> (max - min);
01949 return result;
01950 }
01951
01952
01953 long Alsa::LevelFromPlayer (long min, long max, float level)
01954 {
01955 long result = static_cast<long> ((max - min) * level);
01956 return result;
01957 }
01958
01959
01960 void Alsa::PrintMixerElements (MixerElement *elements, uint32_t count)
01961 {
01962 long min, cur, max;
01963 int switchStatus;
01964 cout << "ALSA: Mixer elements:" << endl;
01965 for (uint32_t ii = 0; ii < count; ii++)
01966 {
01967 if (elements[ii].caps & ELEMCAP_CAN_PLAYBACK)
01968 {
01969 min = elements[ii].minPlayVol;
01970 cur = elements[ii].curPlayVol;
01971 max = elements[ii].maxPlayVol;
01972 switchStatus = elements[ii].playSwitch;
01973 }
01974 else if (elements[ii].caps & ELEMCAP_CAN_CAPTURE)
01975 {
01976 min = elements[ii].minCapVol;
01977 cur = elements[ii].curCapVol;
01978 max = elements[ii].maxCapVol;
01979 switchStatus = elements[ii].capSwitch;
01980 }
01981 else if (elements[ii].caps & ELEMCAP_COMMON)
01982 {
01983 min = elements[ii].minComVol;
01984 cur = elements[ii].curComVol;
01985 max = elements[ii].maxComVol;
01986 switchStatus = elements[ii].comSwitch;
01987 }
01988 cout << "\tElement " << ii << ":\t" << elements[ii].name << endl;
01989 cout << "\tCapabilities:\t";
01990 if (elements[ii].caps & ELEMCAP_CAN_PLAYBACK)
01991 cout << "playback\t";
01992 if (elements[ii].caps & ELEMCAP_CAN_CAPTURE)
01993 cout << "capture\t";
01994 if (elements[ii].caps & ELEMCAP_COMMON)
01995 cout << "common";
01996 cout << endl;
01997 cout << "\tVolume range:\t" << min << "->" << max << endl;
01998 cout << "\tCurrent volume:\t" << cur << endl;
01999 cout << "\tActive:\t" << (switchStatus ? "Yes" : "No") << endl;
02000 }
02001 }
02002
02004
02006
02007
02008
02009 Alsa::Alsa (ConfigFile* cf, int section)
02010 : Driver (cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_AUDIO_CODE)
02011 {
02012 pbDevice = mixerDevice = recDevice = NULL;
02013 pbHandle = NULL;
02014 recHandle = NULL;
02015 mixerHandle = NULL;
02016 samplesHead = samplesTail = NULL;
02017 queueHead = queueTail = NULL;
02018 mixerFilters = NULL;
02019 nextSampleIdx = 0;
02020 mixerElements = NULL;
02021 periodBuffer = NULL;
02022 pbFDs = recFDs = NULL;
02023 recData = NULL;
02024 const char *str;
02025
02026
02027 useQueue = cf->ReadBool (section, "usequeue", true);
02028 debugLevel = cf->ReadInt (section, "debug", 0);
02029 mixerFilterExact = cf->ReadBool (section, "mixerfilterexact", false);
02030 str = cf->ReadString (section, "pbdevice", NULL);
02031 if (str)
02032 pbDevice = strdup(str);
02033
02034 str = cf->ReadString (section, "mixerdevice", NULL);
02035 if (str)
02036 mixerDevice = strdup (str);
02037
02038 str = cf->ReadString (section, "recdevice", NULL);
02039 if (str)
02040 recDevice = strdup (str);
02041
02042 cfgPBPeriodTime = cf->ReadInt (section, "pb_periodlength", 50);
02043 cfgPBBufferTime = cf->ReadInt (section, "pb_bufferlength", 500);
02044
02045 silenceTime = useQueue? cf->ReadInt (section, "pb_silence", 0) : 0;
02046 cfgRecPeriodTime = cf->ReadInt (section, "rec_periodlength", 50);
02047 cfgRecBufferTime = cf->ReadInt (section, "rec_bufferlength", 500);
02048 cfgRecStoreTime = cf->ReadInt (section, "rec_storelength", cfgRecBufferTime);
02049 recNumChannels = cf->ReadInt (section, "rec_nch", 1);
02050 recSampleRate = cf->ReadInt (section, "rec_sr", 44100);
02051 recBits = cf->ReadInt (section, "rec_bits", 16);
02052 if (debugLevel > 1)
02053 {
02054 cout << "Playback device: " << pbDevice << endl;
02055 cout << "Mixer device: " << mixerDevice << endl;
02056 cout << "Record device: " << recDevice << endl;
02057 }
02058
02059
02060 if (recNumChannels != 1 && recNumChannels != 2)
02061 {
02062 PLAYER_WARN ("Recording channels must be 1 or 2; recording functionality will not be available");
02063 if (recDevice)
02064 free (recDevice);
02065 recDevice = NULL;
02066 }
02067 if (recSampleRate != 11025 && recSampleRate != 22050 && recSampleRate != 44100 && recSampleRate != 48000)
02068 {
02069 PLAYER_WARN ("Recording sample rate must be one of 11025Hz, 22050Hz, 44100Hz, 48000Hz; recording functionality will not be available");
02070 if (recDevice)
02071 free (recDevice);
02072 recDevice = NULL;
02073 }
02074 if (recBits != 8 && recBits != 16)
02075 {
02076 PLAYER_WARN ("Recording bits per sample must be 8 or 16; recording functionality will not be available");
02077 if (recDevice)
02078 free (recDevice);
02079 recDevice = NULL;
02080 }
02081
02082
02083 int numSamples = cf->GetTupleCount (section, "samples");
02084 if (numSamples > 0)
02085 {
02086 for (int ii = 0; ii < numSamples; ii++)
02087 {
02088 if (!AddStoredSample (cf->ReadTupleString (section, "samples", ii, "error_bad_sample_path")))
02089 {
02090 PLAYER_ERROR1 ("Could not add audio sample %d", cf->ReadTupleString (section, "samples", ii, ""));
02091 return;
02092 }
02093 }
02094 }
02095
02096
02097 int numMixerFilters = cf->GetTupleCount (section, "mixerfilters");
02098 if (numMixerFilters > 0)
02099 {
02100
02101 if ((mixerFilters = new char*[numMixerFilters + 1]) == NULL)
02102 PLAYER_ERROR1 ("Could not create space to store %d mixer filters", numMixerFilters);
02103 else
02104 {
02105 int ii;
02106
02107 for (ii = 0; ii < numMixerFilters; ii++)
02108 {
02109 str = cf->ReadTupleString (section, "mixerfilters", ii, NULL);
02110 if (str)
02111 {
02112 mixerFilters[ii] = strdup (str);
02113 if (debugLevel >= 1)
02114 cout << "ALSA: Added mixer filter: " << mixerFilters[ii] << endl;
02115 }
02116 }
02117
02118 mixerFilters[ii] = NULL;
02119 }
02120 }
02121
02122 return;
02123 }
02124
02125
02126 Alsa::~Alsa (void)
02127 {
02128 if (pbDevice)
02129 free (pbDevice);
02130 if (mixerDevice)
02131 free (mixerDevice);
02132 if (recDevice)
02133 free (recDevice);
02134 if (samplesHead)
02135 {
02136 StoredSample *currentSample = samplesHead;
02137 StoredSample *previousSample = currentSample;
02138 while (currentSample != NULL)
02139 {
02140 if (currentSample->sample)
02141 delete currentSample->sample;
02142 previousSample = currentSample;
02143 currentSample = currentSample->next;
02144 delete previousSample;
02145 }
02146 }
02147 if (mixerFilters)
02148 {
02149 for (int ii = 0; mixerFilters[ii] != NULL; ii++)
02150 free (mixerFilters[ii]);
02151 delete[] mixerFilters;
02152 }
02153 }
02154
02155
02156 int Alsa::Setup (void)
02157 {
02158
02159 ClearQueue ();
02160
02161
02162 if (pbDevice)
02163 {
02164 if (!SetupPlayBack ())
02165 {
02166 PLAYER_WARN ("Error opening playback device, playback functionality will not be available");
02167 pbHandle = NULL;
02168 }
02169 }
02170
02171
02172 if (mixerDevice)
02173 {
02174 if (!SetupMixer ())
02175 {
02176 PLAYER_WARN ("Error opening mixer, mixer functionality will not be available");
02177 mixerHandle = NULL;
02178 }
02179 }
02180
02181
02182 if (recDevice)
02183 {
02184 if (!SetupRecord ())
02185 {
02186 PLAYER_WARN ("Error opening record device, record functionality will not be available");
02187 recHandle = NULL;
02188 }
02189 }
02190
02191 playState = PB_STATE_STOPPED;
02192 recState = PB_STATE_STOPPED;
02193
02194 StartThread ();
02195 return 0;
02196 }
02197
02198
02199
02200 int Alsa::Shutdown (void)
02201 {
02202 StopThread ();
02203
02204
02205 if (pbFDs)
02206 delete[] pbFDs;
02207 pbFDs = NULL;
02208 if (recFDs)
02209 delete[] recFDs;
02210 recFDs = NULL;
02211
02212 if (pbHandle)
02213 {
02214
02215 StopPlayback ();
02216 snd_pcm_close (pbHandle);
02217 }
02218
02219 if (periodBuffer != NULL)
02220 {
02221 delete[] periodBuffer;
02222 periodBuffer = NULL;
02223 }
02224
02225 if (recHandle)
02226 {
02227 StopRecording ();
02228 snd_pcm_close (recHandle);
02229 }
02230
02231 if (recData)
02232 delete recData;
02233
02234 ClearQueue ();
02235
02236 if (mixerHandle)
02237 {
02238 if (numElements > 0)
02239 {
02240 CleanUpMixerElements (mixerElements, numElements);
02241 }
02242 if (snd_mixer_detach (mixerHandle, mixerDevice) < 0)
02243 PLAYER_WARN ("Error detaching mixer interface");
02244 else
02245 {
02246 if (snd_mixer_close (mixerHandle) < 0)
02247 PLAYER_WARN ("Error closing mixer interface");
02248 else
02249 {
02250
02251
02252 }
02253 }
02254 }
02255
02256 return 0;
02257 }
02258
02259
02261
02263
02264 void Alsa::Main (void)
02265 {
02266 while (1)
02267 {
02268 pthread_testcancel ();
02269
02270
02271
02272 if (playState == PB_STATE_DRAIN)
02273 {
02274
02275 if (snd_pcm_state (pbHandle) == SND_PCM_STATE_DRAINING)
02276 {
02277
02278
02279 }
02280
02281 else if (snd_pcm_state (pbHandle) == SND_PCM_STATE_SETUP || snd_pcm_state (pbHandle) == SND_PCM_STATE_PREPARED)
02282 {
02283
02284 AdvanceQueue ();
02285
02286 if (queueHead != NULL)
02287 {
02288
02289 SetPBParams (queueHead->sample);
02290
02291 playState = PB_STATE_PLAYING;
02292 }
02293
02294 else
02295 {
02296 playState = PB_STATE_STOPPED;
02297 SendStateMessage ();
02298 }
02299 }
02300 else
02301 {
02302 PLAYER_WARN1 ("Unexpected PCM state for drain: %d", snd_pcm_state (pbHandle));
02303 playState = PB_STATE_STOPPED;
02304 SendStateMessage ();
02305 }
02306 }
02307
02308 if (playState == PB_STATE_PLAYING)
02309 {
02310 if (poll (pbFDs, numPBFDs, 5) > 0)
02311 {
02312
02313 for (int ii = 0; ii < numPBFDs; ii++)
02314 if (pbFDs[ii].revents > 0)
02315 PlaybackCallback (pbPeriodSize);
02316 }
02317 }
02318
02319
02320 if (recState == PB_STATE_RECORDING)
02321 {
02322 if (poll (recFDs, numRecFDs, 5) > 0)
02323 {
02324
02325 for (int ii = 0; ii < numRecFDs; ii++)
02326 if (recFDs[ii].revents > 0)
02327 RecordCallback (recPeriodSize);
02328 }
02329 }
02330
02331
02332 if (!InQueue->Empty ())
02333 {
02334
02335 ProcessMessages (1);
02336 }
02337 }
02338 }
02339
02340
02341
02342 void Alsa::SendStateMessage (void)
02343 {
02344 player_audio_state_t msg;
02345
02346 msg.state = 0;
02347 if (playState == PB_STATE_PLAYING || playState == PB_STATE_DRAIN)
02348 msg.state |= PLAYER_AUDIO_STATE_PLAYING;
02349 if (recState == PB_STATE_RECORDING)
02350 msg.state |= PLAYER_AUDIO_STATE_RECORDING;
02351 if (msg.state == 0)
02352 msg.state = PLAYER_AUDIO_STATE_STOPPED;
02353
02354 Publish (device_addr, PLAYER_MSGTYPE_DATA, PLAYER_AUDIO_DATA_STATE, reinterpret_cast<void*> (&msg), sizeof (player_audio_state_t), NULL);
02355 }
02356
02357
02359
02361
02362 int Alsa::HandleWavePlayCmd (player_audio_wav_t *data)
02363 {
02364
02365 if (!AddToQueue (data))
02366 {
02367 PLAYER_WARN ("Unable to add wave data to queue");
02368 return -1;
02369 }
02370
02371
02372 StartPlayback ();
02373
02374 return 0;
02375 }
02376
02377 int Alsa::HandleSamplePlayCmd (player_audio_sample_item_t *data)
02378 {
02379 StoredSample *sample;
02380
02381 if ((sample = GetSampleAtIndex (data->index)) == NULL)
02382 {
02383 PLAYER_ERROR1 ("Couldn't find sample at index %d", data->index);
02384 return -1;
02385 }
02386
02387
02388 if (!AddToQueue (sample->sample))
02389 {
02390 PLAYER_WARN ("Unable to add sample to queue");
02391 return -1;
02392 }
02393
02394
02395 StartPlayback ();
02396
02397 return 0;
02398 }
02399
02400 int Alsa::HandleRecordCmd (player_bool_t *data)
02401 {
02402 if (data->state)
02403 {
02404
02405 recDest = -1;
02406
02407 if (!SetupRecordBuffer (cfgRecStoreTime))
02408 {
02409 PLAYER_ERROR ("Failed to setup local recording buffer");
02410 return 0;
02411 }
02412
02413 StartRecording ();
02414 }
02415 else
02416 StopRecording ();
02417
02418 return 0;
02419 }
02420
02421 int Alsa::HandleMixerChannelCmd (player_audio_mixer_channel_list_t *data)
02422 {
02423 for (uint32_t ii = 0; ii < data->channels_count; ii++)
02424 {
02425 SetElementLevel (data->channels[ii].index, data->channels[ii].amplitude);
02426 SetElementSwitch (data->channels[ii].index, data->channels[ii].active);
02427 }
02428
02429 PublishMixerData ();
02430
02431 return 0;
02432 }
02433
02434 int Alsa::HandleSampleLoadReq (player_audio_sample_t *data, QueuePointer &resp_queue)
02435 {
02436
02437 if (data->index == nextSampleIdx || data->index == -1)
02438 {
02439 if (!AddStoredSample (&data->sample))
02440 return -1;
02441
02442 }
02443
02444 else if (data->index < -1 || data->index > nextSampleIdx)
02445 {
02446 PLAYER_ERROR1 ("Can't add sample at negative index %d", data->index);
02447 return -1;
02448 }
02449 else
02450 {
02451
02452 StoredSample *oldSample;
02453 if ((oldSample = GetSampleAtIndex (data->index)) == NULL)
02454 {
02455 PLAYER_ERROR1 ("Couldn't find sample at index %d", data->index);
02456 return -1;
02457 }
02458
02459
02460 AudioSample *newSample = NULL;
02461 if ((newSample = new AudioSample) == NULL)
02462 {
02463 PLAYER_ERROR ("Failed to allocate memory for new audio sample");
02464 return -1;
02465 }
02466 if (!newSample->FromPlayer (&data->sample))
02467 {
02468 PLAYER_ERROR ("Failed to copy new audio sample");
02469 return -1;
02470 }
02471
02472 if (oldSample->sample)
02473 delete oldSample->sample;
02474
02475 oldSample->sample = newSample;
02476 }
02477 Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_AUDIO_REQ_SAMPLE_LOAD, NULL, 0, NULL);
02478 return 0;
02479 }
02480
02481 int Alsa::HandleSampleRetrieveReq (player_audio_sample_t *data, QueuePointer &resp_queue)
02482 {
02483
02484 if (data->index >= nextSampleIdx || data->index < 0)
02485 {
02486 PLAYER_ERROR1 ("Can't retrieve sample from invalid index %d", data->index);
02487 return -1;
02488 }
02489 else
02490 {
02491
02492 StoredSample *sample;
02493 if ((sample = GetSampleAtIndex (data->index)) == NULL)
02494 {
02495 PLAYER_ERROR1 ("Couldn't find sample at index %d", data->index);
02496 return -1;
02497 }
02498
02499 player_audio_sample_t result;
02500 memset (&result, 0, sizeof (player_audio_sample_t));
02501 result.index = data->index;
02502 sample->sample->ToPlayer (&result.sample);
02503 Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_AUDIO_REQ_SAMPLE_RETRIEVE, &result, sizeof (player_audio_sample_t), NULL);
02504 return 0;
02505 }
02506 return -1;
02507 }
02508
02509
02510 int Alsa::HandleSampleRecordReq (player_audio_sample_rec_req_t *data, QueuePointer &resp_queue)
02511 {
02512
02513 if (recState == PB_STATE_RECORDING)
02514 {
02515 PLAYER_WARN ("Tried to record a sample while already recording");
02516 return -1;
02517 }
02518
02519
02520 if (data->index < 0 || data->index == nextSampleIdx)
02521 {
02522
02523
02524 StoredSample *placeHolder = NULL;
02525 if ((placeHolder = new StoredSample) == NULL)
02526 {
02527 PLAYER_ERROR ("Failed to allocate sample storage");
02528 return -1;
02529 }
02530 recDest = nextSampleIdx++;
02531 memset (placeHolder, 0, sizeof (StoredSample));
02532 placeHolder->index = recDest;
02533 AddStoredSample (placeHolder);
02534 }
02535 else if (data->index > nextSampleIdx)
02536 {
02537
02538 PLAYER_ERROR2 ("Can't add sample at index %d, greater than %d", data->index, nextSampleIdx);
02539 return -1;
02540 }
02541 else
02542 {
02543 recDest = data->index;
02544 }
02545 if (debugLevel >= 4)
02546 cout << "ALSA: Recording new sample to index " << recDest << endl;
02547
02548 if (!SetupRecordBuffer (data->length))
02549 {
02550 PLAYER_ERROR ("Failed to setup local recording buffer");
02551 return -1;
02552 }
02553
02554 StartRecording ();
02555
02556 player_audio_sample_rec_req_t response;
02557 response.index = recDest;
02558 response.length = data->length;
02559 Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_AUDIO_REQ_SAMPLE_REC, &response, sizeof (player_audio_sample_rec_req_t), NULL);
02560 return 0;
02561 }
02562
02563 int Alsa::HandleMixerChannelListReq (player_audio_mixer_channel_list_detail_t *data, QueuePointer &resp_queue)
02564 {
02565 player_audio_mixer_channel_list_detail_t result;
02566 MixerDetailsToPlayer (&result);
02567 Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_AUDIO_REQ_MIXER_CHANNEL_LIST, &result, sizeof (player_audio_mixer_channel_list_detail_t), NULL);
02568
02569 return 0;
02570 }
02571
02572 int Alsa::HandleMixerChannelLevelReq (player_audio_mixer_channel_list_t *data, QueuePointer &resp_queue)
02573 {
02574 player_audio_mixer_channel_list_t result;
02575 MixerLevelsToPlayer (&result);
02576 Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_AUDIO_REQ_MIXER_CHANNEL_LEVEL, &result, sizeof (player_audio_mixer_channel_list_t), NULL);
02577
02578 return 0;
02579 }
02580
02581
02582 int Alsa::ProcessMessage (QueuePointer &resp_queue, player_msghdr *hdr, void *data)
02583 {
02584
02585 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_CAPABILTIES_REQ);
02586 if (pbHandle)
02587 {
02588 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_CMD_WAV_PLAY);
02589 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_CMD_SAMPLE_PLAY);
02590 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_SAMPLE_LOAD);
02591 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_SAMPLE_RETRIEVE);
02592 }
02593 if (recHandle)
02594 {
02595 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_CMD_WAV_STREAM_REC);
02596 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_SAMPLE_REC);
02597 }
02598 if (mixerHandle)
02599 {
02600 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_CMD_MIXER_CHANNEL);
02601 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_MIXER_CHANNEL_LIST);
02602 HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_MIXER_CHANNEL_LEVEL);
02603 }
02604
02605
02606 if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_CMD_WAV_PLAY, device_addr) && pbHandle)
02607 {
02608 HandleWavePlayCmd (reinterpret_cast<player_audio_wav_t*> (data));
02609 return 0;
02610 }
02611 else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_CMD_SAMPLE_PLAY, device_addr) && pbHandle)
02612 {
02613 HandleSamplePlayCmd (reinterpret_cast<player_audio_sample_item_t*> (data));
02614 return 0;
02615 }
02616 else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_CMD_WAV_STREAM_REC, device_addr) && recHandle)
02617 {
02618 HandleRecordCmd (reinterpret_cast<player_bool_t*> (data));
02619 return 0;
02620 }
02621 else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_CMD_MIXER_CHANNEL, device_addr) && mixerHandle)
02622 {
02623 HandleMixerChannelCmd (reinterpret_cast<player_audio_mixer_channel_list_t*> (data));
02624 return 0;
02625 }
02626
02627 else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_SAMPLE_LOAD, device_addr) && pbHandle)
02628 {
02629 return HandleSampleLoadReq (reinterpret_cast<player_audio_sample_t*> (data), resp_queue);
02630 }
02631 else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_SAMPLE_RETRIEVE, device_addr) && pbHandle)
02632 {
02633 return HandleSampleRetrieveReq (reinterpret_cast<player_audio_sample_t*> (data), resp_queue);
02634 }
02635 else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_SAMPLE_REC, device_addr) && recHandle)
02636 {
02637 return HandleSampleRecordReq (reinterpret_cast<player_audio_sample_rec_req_t*> (data), resp_queue);
02638 }
02639 else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_MIXER_CHANNEL_LIST, device_addr) && mixerHandle)
02640 {
02641 return HandleMixerChannelListReq (reinterpret_cast<player_audio_mixer_channel_list_detail_t*> (data), resp_queue);
02642 }
02643 else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, PLAYER_AUDIO_REQ_MIXER_CHANNEL_LEVEL, device_addr) && mixerHandle)
02644 {
02645 return HandleMixerChannelLevelReq (reinterpret_cast<player_audio_mixer_channel_list_t*> (data), resp_queue);
02646 }
02647
02648 return -1;
02649 }