Ticket #7517: volume_control_trunk_r24896.patch
| File volume_control_trunk_r24896.patch, 126.2 KB (added by , 16 years ago) |
|---|
-
mythplugins/mythmusic/mythmusic/playbackbox.cpp
98 98 99 99 // Possibly (user-defined) control the volume 100 100 101 volume_control = false; 102 volume_display_timer = new QTimer(this); 103 if (gCoreContext->GetNumSetting("MythControlsVolume", 0)) 101 volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 102 if (volume_control) 104 103 { 105 volume_control = true; 104 connect(volume_control.data(), SIGNAL(changedVolume(int)), 105 this, SLOT(VolumeChanged(int))); 106 connect(volume_control.data(), SIGNAL(changedMute(bool)), 107 this, SLOT(MuteChanged(bool))); 106 108 } 109 110 volume_display_timer = new QTimer(this); 107 111 volume_display_timer->setSingleShot(true); 108 112 volume_display_timer->start(2000); 109 113 connect(volume_display_timer, SIGNAL(timeout()), … … 1178 1182 if (volume_control && gPlayer->getOutput()) 1179 1183 { 1180 1184 if (up_or_down) 1181 gPlayer-> getOutput()->AdjustCurrentVolume(2);1185 gPlayer->incVolume(); 1182 1186 else 1183 gPlayer-> getOutput()->AdjustCurrentVolume(-2);1187 gPlayer->decVolume(); 1184 1188 showVolume(true); 1185 1189 } 1186 1190 } … … 1201 1205 { 1202 1206 if (volume_control && gPlayer->getOutput()) 1203 1207 { 1204 gPlayer-> getOutput()->ToggleMute();1208 gPlayer->toggleMute(); 1205 1209 showVolume(true); 1206 1210 } 1207 1211 } … … 1243 1247 { 1244 1248 if (on_or_off) 1245 1249 { 1246 volume_status->SetUsed(gPlayer->get Output()->GetCurrentVolume());1250 volume_status->SetUsed(gPlayer->getVolume()); 1247 1251 volume_status->SetOrder(0); 1248 1252 volume_status->refresh(); 1249 1253 volume_display_timer->setSingleShot(true); … … 2454 2458 2455 2459 return time_string; 2456 2460 } 2461 2462 void PlaybackBoxMusic::VolumeChanged(int) 2463 { 2464 showVolume(true); 2465 } 2466 2467 void PlaybackBoxMusic::MuteChanged(bool) 2468 { 2469 showVolume(true); 2470 } -
mythplugins/mythmusic/mythmusic/musicplayer.h
3 3 4 4 #include <mythdialogs.h> 5 5 #include <audiooutput.h> 6 #include <libmyth/volumecontrolmanager.h> 6 7 #include <mythobservable.h> 7 8 8 9 #include "metadata.h" … … 55 56 56 57 void setCDDevice(const QString &dev) { m_CDdevice = dev; } 57 58 58 void toggleMute(void); 59 MuteState getMuteState(void) const; 60 bool isMuted(void) const { return getMuteState() == kMuteAll; } 59 void toggleMute(void); 60 bool isMuted(void) const; 61 61 62 62 void setVolume(int volume); 63 63 void incVolume(void); … … 176 176 AudioOutput *m_output; 177 177 Decoder *m_decoder; 178 178 179 QSharedPointer<VolumeControl> volume_control; ///< Volume control interface 180 179 181 QSet<QObject*> m_visualisers; 180 182 181 183 QString m_CDdevice; -
mythplugins/mythmusic/mythmusic/musicplayer.cpp
88 88 89 89 m_autoShowPlayer = (gCoreContext->GetNumSetting("MusicAutoShowPlayer", 1) > 0); 90 90 91 volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 92 91 93 gCoreContext->addListener(this); 92 94 } 93 95 … … 375 377 // TODO: Error checking that device is opened correctly! 376 378 m_output = AudioOutput::OpenAudio( 377 379 adevice, pdevice, FORMAT_S16, 2, 0, 44100, 378 AUDIOOUTPUT_MUSIC, true,false,380 AUDIOOUTPUT_MUSIC, false, 379 381 gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1); 380 382 m_output->setBufferSize(256 * 1024); 381 383 … … 934 936 935 937 void MusicPlayer::incVolume() 936 938 { 937 if ( getOutput())939 if (volume_control) 938 940 { 939 getOutput()->AdjustCurrentVolume(2);941 volume_control->increaseVolume(); 940 942 sendVolumeChangedEvent(); 941 943 } 942 944 } 943 945 944 946 void MusicPlayer::decVolume() 945 947 { 946 if ( getOutput())948 if (volume_control) 947 949 { 948 getOutput()->AdjustCurrentVolume(-2);950 volume_control->decreaseVolume(); 949 951 sendVolumeChangedEvent(); 950 952 } 951 953 } 952 954 953 955 void MusicPlayer::setVolume(int volume) 954 956 { 955 if ( getOutput())957 if (volume_control) 956 958 { 957 getOutput()->SetCurrentVolume(volume);959 volume_control->setVolume(volume); 958 960 sendVolumeChangedEvent(); 959 961 } 960 962 } 961 963 962 964 uint MusicPlayer::getVolume(void) const 963 965 { 964 if ( m_output)965 return m_output->GetCurrentVolume();966 if (volume_control) 967 return volume_control->volume(); 966 968 return 0; 967 969 } 968 970 969 971 void MusicPlayer::toggleMute(void) 970 972 { 971 if ( m_output)973 if (volume_control) 972 974 { 973 m_output->ToggleMute();975 volume_control->setMute(!volume_control->mute()); 974 976 sendVolumeChangedEvent(); 975 977 } 976 978 } 977 979 978 MuteState MusicPlayer::getMuteState(void) const980 bool MusicPlayer::isMuted(void) const 979 981 { 980 if ( m_output)981 return m_output->GetMuteState();982 return kMuteAll;982 if (volume_control) 983 return volume_control->mute(); 984 return true; 983 985 } 984 986 985 987 void MusicPlayer::toMap(QHash<QString, QString> &map) -
mythplugins/mythmusic/mythmusic/playbackbox.h
8 8 // mythtv 9 9 #include <mythwidgets.h> 10 10 #include <dialogbox.h> 11 #include < audiooutput.h>11 #include <libmyth/volumecontrolmanager.h> 12 12 13 13 // mythmusic 14 14 #include "mainvisual.h" … … 101 101 bool getInsertPLOptions(InsertPLOption &insertOption, 102 102 PlayPLOption &playOption, bool &bRemoveDups); 103 103 104 protected slots: 105 void VolumeChanged(int volume); 106 void MuteChanged(bool mute); 107 104 108 signals: 105 109 106 110 void dummy(); // debugging … … 172 176 bool show_album_art; 173 177 bool show_whole_tree; 174 178 bool keyboard_accelerators; 175 bool volume_control;179 QSharedPointer<VolumeControl> volume_control; ///< Volume control interface 176 180 177 181 QString exit_action; 178 182 -
mythtv/configure
637 637 eval "$var=\"\$$var $*\"" 638 638 } 639 639 640 prepend(){ 641 var=$1 642 shift 643 flags_saved && eval "SAVE_$var=\"$* \$SAVE_$var\"" 644 eval "$var=\"$* \$$var\"" 645 } 646 640 647 append_uniq(){ 641 648 log append_uniq "$@" 642 649 var=$1 … … 3640 3647 { { ! enabled audio_alsa || die "ERROR: Alsa >= 1.0.16 required"; } && 3641 3648 disable audio_alsa; } 3642 3649 3650 # OSS probe 3651 if ! disabled audio_oss ; then 3652 if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h && 3653 check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3654 disable soundcard_h 3655 enable sys_soundcard_h 3656 prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include" 3657 elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h && 3658 check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3659 disable soundcard_h 3660 enable sys_soundcard_h 3661 prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include" 3662 else 3663 if enabled soundcard_h ; then 3664 check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" && 3665 enable audio_oss || 3666 disable audio_oss 3667 elif enabled sys_soundcard_h ; then 3668 check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" && 3669 enable audio_oss || 3670 disable audio_oss 3671 fi 3672 fi 3673 fi 3643 3674 3644 3675 # JACK probe 3645 3676 ! disabled audio_jack && -
mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
103 103 kDisplayNUVTeletextCaptions, 104 104 }; 105 105 106 NuppelVideoPlayer::NuppelVideoPlayer( bool muted)106 NuppelVideoPlayer::NuppelVideoPlayer() 107 107 : decoder(NULL), decoder_change_lock(QMutex::Recursive), 108 108 videoOutput(NULL), player_ctx(NULL), 109 109 no_hardware_decoders(false), … … 173 173 audio_channels(2), audio_codec(0), 174 174 audio_format(FORMAT_NONE), audio_samplerate(44100), 175 175 audio_stretchfactor(1.0f), audio_lock(QMutex::Recursive), 176 audio_muted_on_creation(muted),177 176 // Picture-in-Picture stuff 178 177 pip_active(false), pip_visible(true), 179 178 // Preview window support … … 373 372 audio_samplerate = (int)samplerate; 374 373 } 375 374 376 uint NuppelVideoPlayer::GetVolume(void)377 {378 QMutexLocker lock(&audio_lock);379 if (audioOutput)380 return audioOutput->GetCurrentVolume();381 return 0;382 }383 384 bool NuppelVideoPlayer::SetMuted(bool mute)385 {386 QMutexLocker lock(&audio_lock);387 bool is_muted = IsMuted();388 389 if (audioOutput && !is_muted && mute &&390 (kMuteAll == SetMuteState(kMuteAll)))391 {392 VERBOSE(VB_AUDIO, "muting sound " <<IsMuted());393 return true;394 }395 else if (audioOutput && is_muted && !mute &&396 (kMuteOff == SetMuteState(kMuteOff)))397 {398 VERBOSE(VB_AUDIO, "unmuting sound "<<IsMuted());399 return true;400 }401 402 VERBOSE(VB_AUDIO, "not changing sound mute state "<<IsMuted());403 404 return false;405 }406 407 MuteState NuppelVideoPlayer::SetMuteState(MuteState mstate)408 {409 QMutexLocker lock(&audio_lock);410 if (audioOutput)411 return audioOutput->SetMuteState(mstate);412 return kMuteAll;413 }414 415 MuteState NuppelVideoPlayer::IncrMuteState(void)416 {417 QMutexLocker lock(&audio_lock);418 MuteState mstate = kMuteAll;419 if (audioOutput)420 mstate = SetMuteState(VolumeBase::NextMuteState(GetMuteState()));421 return mstate;422 }423 424 MuteState NuppelVideoPlayer::GetMuteState(void)425 {426 QMutexLocker lock(&audio_lock);427 if (audioOutput)428 return audioOutput->GetMuteState();429 return kMuteAll;430 }431 432 uint NuppelVideoPlayer::AdjustVolume(int change)433 {434 QMutexLocker lock(&audio_lock);435 if (audioOutput)436 audioOutput->AdjustCurrentVolume(change);437 return GetVolume();438 }439 440 375 void NuppelVideoPlayer::PauseDecoder(void) 441 376 { 442 377 decoder_lock.lock(); … … 881 816 882 817 if (!audioOutput && !using_null_videoout && player_ctx->IsAudioNeeded()) 883 818 { 884 bool setVolume = gCoreContext->GetNumSetting("MythControlsVolume", 1);885 819 audioOutput = AudioOutput::OpenAudio(audio_main_device, 886 820 audio_passthru_device, 887 821 audio_format, audio_channels, 888 822 audio_codec, audio_samplerate, 889 823 AUDIOOUTPUT_VIDEO, 890 setVolume,audio_passthru);824 audio_passthru); 891 825 if (!audioOutput) 892 826 errMsg = QObject::tr("Unable to create AudioOutput."); 893 827 else … … 909 843 VERBOSE(VB_IMPORTANT, LOC + "Enabling Audio"); 910 844 no_audio_out = false; 911 845 } 912 if (audio_muted_on_creation)913 {914 SetMuteState(kMuteAll);915 audio_muted_on_creation = false;916 }917 846 } 918 847 919 848 if (audioOutput) -
mythtv/libs/libmythtv/avformatdecoder.cpp
496 496 // Audio 497 497 audioSamples(NULL), 498 498 allow_ac3_passthru(false), allow_dts_passthru(false), 499 internal_vol(false),500 499 disable_passthru(false), max_channels(2), 501 500 last_ac3_channels(0), last_framesRead(0), 502 501 dummy_frame(NULL), … … 529 528 if (stmp.startsWith("JACK:")) 530 529 allow_dts_passthru = allow_ac3_passthru = false; 531 530 532 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);533 531 534 532 audioIn.sample_size = -32; // force SetupAudioStream to run once 535 533 itv = GetNVP()->GetInteractiveTV(); … … 4668 4666 4669 4667 if (ctx->codec_id == CODEC_ID_AC3) 4670 4668 passthru = allow_ac3_passthru && 4671 ctx->channels >= (int)max_channels && 4672 !internal_vol; 4669 ctx->channels >= (int)max_channels; 4673 4670 else if (ctx->codec_id == CODEC_ID_DTS) 4674 passthru = allow_dts_passthru && !internal_vol;4671 passthru = allow_dts_passthru; 4675 4672 4676 4673 passthru &= !transcoding && !disable_passthru; 4677 4674 // Don't know any cards that support spdif clocked at < 44100 -
mythtv/libs/libmythtv/tv_play.h
33 33 #include "programinfo.h" 34 34 #include "channelutil.h" 35 35 #include "videoouttypes.h" 36 #include "volume base.h"36 #include "volumecontrolmanager.h" 37 37 #include "inputinfo.h" 38 38 #include "channelgroup.h" 39 39 … … 300 300 void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*); 301 301 void ClearUDPNotifyEvents(void); 302 302 303 void VolumeChanged(int volume); 304 void MuteChanged(bool mute); 305 303 306 protected: 304 307 void TreeMenuEntered(OSDListTreeItemEnteredEvent *e); 305 308 void TreeMenuSelected(OSDListTreeItemSelectedEvent *e); … … 508 511 509 512 vector<long long> TeardownAllNVPs(PlayerContext*); 510 513 void RestartAllNVPs(PlayerContext *lctx, 511 const vector<long long> &pos, 512 MuteState mctx_mute); 514 const vector<long long> &pos); 513 515 void RestartMainNVP(PlayerContext *mctx); 514 516 515 517 void PxPToggleView( PlayerContext *actx, bool wantPBP); … … 668 670 /// Picture attribute to modify (on arrow left or right) 669 671 PictureAttribute adjustingPictureAttribute; 670 672 673 QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface 674 671 675 // Ask Allow state 672 676 AskAllowType askAllowType; 673 677 QMap<QString,AskProgramInfo> askAllowPrograms; -
mythtv/libs/libmythtv/playercontext.cpp
432 432 433 433 bool PlayerContext::CreateNVP(TV *tv, QWidget *widget, 434 434 TVState desiredState, 435 WId embedwinid, const QRect *embedbounds, 436 bool muted) 435 WId embedwinid, const QRect *embedbounds) 437 436 { 438 437 int exact_seeking = gCoreContext->GetNumSetting("ExactSeeking", 0); 439 438 … … 444 443 return false; 445 444 } 446 445 447 NuppelVideoPlayer *_nvp = new NuppelVideoPlayer( muted);446 NuppelVideoPlayer *_nvp = new NuppelVideoPlayer(); 448 447 449 448 if (nohardwaredecoders) 450 449 _nvp->DisableHardwareDecoders(); … … 498 497 VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg); 499 498 } 500 499 } 501 else if (pipState == kPBPRight)502 nvp->SetMuted(true);503 500 504 501 int maxWait = -1; 505 502 //if (isPIP()) -
mythtv/libs/libmythtv/NuppelVideoPlayer.h
4 4 #include <sys/time.h> 5 5 6 6 #include "playercontext.h" 7 #include "volumebase.h"8 7 #include "audiooutputsettings.h" 9 8 #include "RingBuffer.h" 10 9 #include "osd.h" … … 90 89 friend class PlayerContext; 91 90 92 91 public: 93 NuppelVideoPlayer( bool muted = false);92 NuppelVideoPlayer(); 94 93 ~NuppelVideoPlayer(); 95 94 96 95 // Initialization … … 113 112 void SetAudioInfo(const QString &main, const QString &passthru, uint rate); 114 113 void SetAudioParams(AudioFormat format, int channels, int codec, int samplerate, bool passthru); 115 114 void SetEffDsp(int dsprate); 116 uint AdjustVolume(int change);117 bool SetMuted(bool mute);118 MuteState SetMuteState(MuteState);119 MuteState IncrMuteState(void);120 115 void SetAudioCodec(void *ac); 121 116 122 117 // Sets … … 173 168 float GetVideoAspect(void) const { return video_aspect; } 174 169 float GetFrameRate(void) const { return video_frame_rate; } 175 170 176 uint GetVolume(void);177 171 int GetSecondsBehind(void) const; 178 172 AspectOverrideMode GetAspectOverride(void) const; 179 173 AdjustFillMode GetAdjustFill(void) const; 180 MuteState GetMuteState(void);181 174 CommSkipMode GetAutoCommercialSkip(void) const; 182 175 183 176 int GetFFRewSkip(void) const { return ffrew_skip; } … … 212 205 bool HasAudioOut(void) const { return !no_audio_out; } 213 206 bool IsPIPActive(void) const { return pip_active; } 214 207 bool IsPIPVisible(void) const { return pip_visible; } 215 bool IsMuted(void) { return GetMuteState() == kMuteAll; }216 208 bool UsingNullVideo(void) const { return using_null_videoout; } 217 209 bool HasTVChainNext(void) const; 218 210 -
mythtv/libs/libmythtv/tv_play.cpp
1024 1024 player.push_back(new PlayerContext(kPlayerInUseID)); 1025 1025 playerActive = 0; 1026 1026 playerLock.unlock(); 1027 1028 volumeControl = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 1029 if (volumeControl) 1030 { 1031 connect(volumeControl.data(), SIGNAL(changedVolume(int)), 1032 this, SLOT(VolumeChanged(int)), Qt::QueuedConnection); 1033 connect(volumeControl.data(), SIGNAL(changedMute(bool)), 1034 this, SLOT(MuteChanged(bool)), Qt::QueuedConnection); 1035 } 1036 1027 1037 VERBOSE(VB_PLAYBACK, LOC + "ctor -- end"); 1028 1038 } 1029 1039 … … 5435 5445 } 5436 5446 } 5437 5447 5438 MuteState mctx_mute = kMuteOff;5439 mctx->LockDeleteNVP(__FILE__, __LINE__);5440 if (mctx->nvp)5441 mctx_mute = mctx->nvp->GetMuteState();5442 mctx->UnlockDeleteNVP(__FILE__, __LINE__);5443 5444 5448 vector<long long> pos = TeardownAllNVPs(mctx); 5445 5449 5446 5450 if (wantPBP) … … 5458 5462 } 5459 5463 } 5460 5464 5461 RestartAllNVPs(mctx, pos , mctx_mute);5465 RestartAllNVPs(mctx, pos); 5462 5466 5463 5467 VERBOSE(VB_PLAYBACK, LOC + 5464 5468 QString("PxPToggleType() converting from %1 to %2 -- end") … … 5602 5606 * \brief Recreate Main and PIP windows. Could be either PIP or PBP views. 5603 5607 */ 5604 5608 void TV::RestartAllNVPs(PlayerContext *lctx, 5605 const vector<long long> &pos, 5606 MuteState mctx_mute) 5609 const vector<long long> &pos) 5607 5610 { 5608 5611 QString loc = LOC + QString("RestartAllNVPs(): "); 5609 5612 … … 5650 5653 pipctx->LockDeleteNVP(__FILE__, __LINE__); 5651 5654 if (pipctx->nvp) 5652 5655 { 5653 pipctx->nvp->SetMuted(true);5654 5656 pipctx->nvp->JumpToFrame(pos[i]); 5655 5657 } 5656 5658 pipctx->UnlockDeleteNVP(__FILE__, __LINE__); … … 5662 5664 ForceNextStateNone(pipctx); 5663 5665 } 5664 5666 } 5665 5666 // If old main player had a kMuteAll | kMuteOff setting,5667 // apply old main player's mute setting to new main player.5668 mctx->LockDeleteNVP(__FILE__, __LINE__);5669 if (mctx->nvp && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))5670 mctx->nvp->SetMuteState(mctx_mute);5671 mctx->UnlockDeleteNVP(__FILE__, __LINE__);5672 5667 } 5673 5668 5674 5669 void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx) … … 5696 5691 return; 5697 5692 } 5698 5693 5699 MuteState mctx_mute = mctx->nvp->GetMuteState();5700 5694 mctx->deleteNVPLock.unlock(); 5701 5695 pipctx->deleteNVPLock.unlock(); 5702 5696 … … 5710 5704 playerActive = (ctx_index == playerActive) ? 5711 5705 0 : ((ctx_index == 0) ? ctx_index : playerActive); 5712 5706 5713 RestartAllNVPs(mctx, pos , mctx_mute);5707 RestartAllNVPs(mctx, pos); 5714 5708 5715 5709 SetActive(mctx, playerActive, false); 5716 5710 … … 5731 5725 mctx->deleteNVPLock.unlock(); 5732 5726 return; 5733 5727 } 5734 5735 MuteState mctx_mute = mctx->nvp->GetMuteState();5736 5737 // HACK - FIXME5738 // workaround muted audio when NVP is re-created5739 mctx_mute = kMuteOff;5740 // FIXME - end5741 5728 mctx->deleteNVPLock.unlock(); 5742 5729 5743 5730 vector<long long> pos = TeardownAllNVPs(mctx); 5744 RestartAllNVPs(mctx, pos , mctx_mute);5731 RestartAllNVPs(mctx, pos); 5745 5732 SetActive(mctx, playerActive, false); 5746 5733 5747 5734 VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end"); … … 6475 6462 if (mctx != ctx) 6476 6463 PIPRemovePlayer(mctx, ctx); 6477 6464 6478 bool muted = false;6479 ctx->LockDeleteNVP(__FILE__, __LINE__);6480 if (ctx->nvp && ctx->nvp->IsMuted())6481 muted = true;6482 ctx->UnlockDeleteNVP(__FILE__, __LINE__);6483 6484 6465 // pause the decoder first, so we're not reading too close to the end. 6485 6466 ctx->buffer->IgnoreLiveEOF(true); 6486 6467 ctx->buffer->StopReads(); … … 6532 6513 6533 6514 if (ctx->CreateNVP( 6534 6515 this, GetMythMainWindow(), ctx->GetState(), 6535 mctx->embedWinID, &mctx->embedBounds , muted))6516 mctx->embedWinID, &mctx->embedBounds)) 6536 6517 { 6537 6518 ScheduleStateChange(ctx); 6538 6519 ok = true; … … 8171 8152 8172 8153 void TV::ChangeVolume(PlayerContext *ctx, bool up) 8173 8154 { 8174 ctx->LockDeleteNVP(__FILE__, __LINE__); 8175 if (!ctx->nvp) 8155 if (volumeControl) 8176 8156 { 8177 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8178 return; 8157 if (up) 8158 volumeControl->increaseVolume(); 8159 else 8160 volumeControl->decreaseVolume(); 8179 8161 } 8180 uint curvol = ctx->nvp->AdjustVolume((up) ? +2 : -2);8181 ctx->UnlockDeleteNVP(__FILE__, __LINE__);8182 8183 QString text = tr("Volume %1 %").arg(curvol);8184 8185 OSD *osd = GetOSDLock(ctx);8186 if (osd && !browsemode)8187 {8188 osd->ShowStatus(curvol * 10, true, tr("Adjust Volume"), text, 5,8189 kOSDFunctionalType_PictureAdjust);8190 SetUpdateOSDPosition(false);8191 }8192 ReturnOSDLock(ctx, osd);8193 8162 } 8194 8163 8195 8164 void TV::ToggleTimeStretch(PlayerContext *ctx) … … 8338 8307 8339 8308 void TV::ToggleMute(PlayerContext *ctx, const bool muteIndividualChannels) 8340 8309 { 8341 ctx->LockDeleteNVP(__FILE__, __LINE__); 8342 if (!ctx->nvp || !ctx->nvp->HasAudioOut()) 8343 { 8344 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8345 return; 8346 } 8347 8348 MuteState mute_status; 8349 8350 if (!muteIndividualChannels) 8351 { 8352 ctx->nvp->SetMuted(!ctx->nvp->IsMuted()); 8353 mute_status = (ctx->nvp->IsMuted()) ? kMuteAll : kMuteOff; 8354 } 8355 else 8356 { 8357 mute_status = ctx->nvp->IncrMuteState(); 8358 } 8359 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8360 8361 QString text; 8362 8363 switch (mute_status) 8364 { 8365 case kMuteOff: text = tr("Mute Off"); break; 8366 case kMuteAll: text = tr("Mute On"); break; 8367 case kMuteLeft: text = tr("Left Channel Muted"); break; 8368 case kMuteRight: text = tr("Right Channel Muted"); break; 8369 } 8370 8371 OSD *osd = GetOSDLock(ctx); 8372 if (osd && !browsemode) 8373 osd->SetSettingsText(text, 5); 8374 ReturnOSDLock(ctx, osd); 8310 if (volumeControl) 8311 volumeControl->setMute(!volumeControl->mute()); 8375 8312 } 8376 8313 8377 8314 void TV::ToggleSleepTimer(const PlayerContext *ctx) … … 9309 9246 { 9310 9247 value = ctx->nvp->getVideoOutput()->GetPictureAttribute(attr); 9311 9248 } 9312 else if (ctx->nvp->HasAudioOut() )9249 else if (ctx->nvp->HasAudioOut() && volumeControl) 9313 9250 { 9314 value = ctx->nvp->GetVolume();9251 value = volumeControl->volume(); 9315 9252 title = tr("Adjust Volume"); 9316 9253 } 9317 9254 } … … 11912 11849 ReturnPlayerLock(mctx); 11913 11850 } 11914 11851 11852 void TV::VolumeChanged(int volume) 11853 { 11854 OSD *osd = GetOSDL(__FILE__, __LINE__); 11855 if (osd && !browsemode) 11856 { 11857 osd->ShowStatus(volume * 10, true, tr("Adjust Volume"), 11858 tr("Volume %1 %").arg(volume), 5, 11859 kOSDFunctionalType_PictureAdjust); 11860 SetUpdateOSDPosition(false); 11861 } 11862 ReturnOSDLock(osd); 11863 } 11864 11865 void TV::MuteChanged(bool mute) 11866 { 11867 OSD *osd = GetOSDL(__FILE__, __LINE__); 11868 if (osd && !browsemode) 11869 osd->SetSettingsText(mute ? tr("Mute On") : tr("Mute Off"), 5); 11870 ReturnOSDLock(osd); 11871 } 11872 11873 11915 11874 OSD *TV::GetOSDL(const char *file, int location) 11916 11875 { 11917 11876 PlayerContext *actx = GetPlayerReadLock(-1, file, location); -
mythtv/libs/libmythtv/playercontext.h
47 47 // Actions 48 48 bool CreateNVP(TV *tv, QWidget *widget, 49 49 TVState desiredState, 50 WId embedwinid, const QRect *embedBounds, 51 bool muted = false); 50 WId embedwinid, const QRect *embedBounds); 52 51 void TeardownPlayer(void); 53 52 bool StartDecoderThread(int maxWait = -1); 54 53 bool StartOSD(TV *tv); -
mythtv/libs/libmythtv/avformatdecoder.h
300 300 short int *audioSamples; 301 301 bool allow_ac3_passthru; 302 302 bool allow_dts_passthru; 303 bool internal_vol;304 303 bool disable_passthru; 305 304 uint max_channels; 306 305 uint last_ac3_channels; -
mythtv/libs/libmyth/audiooutputwin.cpp
274 274 return m_nPkts * fragment_size; 275 275 } 276 276 277 int AudioOutputWin::GetVolumeChannel(int channel) const278 {279 DWORD dwVolume = 0xffffffff;280 int Volume = 100;281 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))282 {283 Volume = (channel == 0) ?284 (LOWORD(dwVolume) / (0xffff / 100)) :285 (HIWORD(dwVolume) / (0xffff / 100));286 }287 288 VERBOSE(VB_AUDIO, "GetVolume(" << channel << ") "289 << Volume << "(" << dwVolume << ")");290 291 return Volume;292 }293 294 void AudioOutputWin::SetVolumeChannel(int channel, int volume)295 {296 if (channel > 1)297 VBERROR("Windows volume only supports stereo!");298 299 DWORD dwVolume = 0xffffffff;300 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))301 {302 if (channel == 0)303 dwVolume = dwVolume & 0xffff0000 | volume * (0xffff / 100);304 else305 dwVolume = dwVolume & 0xffff | ((volume * (0xffff / 100)) << 16);306 }307 else308 {309 dwVolume = volume * (0xffff / 100);310 dwVolume |= (dwVolume << 16);311 }312 313 VBAUDIO(QString("SetVolume(%1) %2(%3)")314 .arg(channel).arg(volume).arg(dwVolume));315 316 waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, dwVolume);317 } -
mythtv/libs/libmyth/volumecontrolmanager.cpp
1 #include "volumecontrolmanager.h" 2 3 #include "mythverbose.h" 4 #ifdef USE_ALSA 5 #include "volumecontrolalsa.h" 6 #endif 7 #ifdef USE_COREAUDIO 8 #include "volumecontrolcoreaudio.h" 9 #endif 10 #ifdef USING_OSS 11 #include "volumecontroloss.h" 12 #endif 13 #ifdef USING_MINGW 14 #include "volumecontrolendpoint.h" 15 #endif 16 #include "volumecontrolsoftware.h" 17 18 19 QHash<QString, QString> VolumeControlManager::Enumerate() 20 { 21 QHash<QString, QString> result; 22 23 #ifdef USE_ALSA 24 result.unite(VolumeControlALSA::Enumerate()); 25 #endif 26 #ifdef USE_COREAUDIO 27 result.unite(VolumeControlCoreAudio::Enumerate()); 28 #endif 29 #ifdef USING_OSS 30 result.unite(VolumeControlOSS::Enumerate()); 31 #endif 32 #ifdef USING_MINGW 33 result.unite(VolumeControlEndpoint::Enumerate()); 34 #endif 35 result.unite(VolumeControlSoftware::Enumerate()); 36 37 return result; 38 } 39 40 QSharedPointer<VolumeControl> VolumeControlManager::GetControl(QString device) 41 { 42 QSharedPointer<VolumeControl> result; 43 QString api = device.section(':', 0, 0); 44 device = device.remove(0, api.size() + 1); 45 46 if (api == "ALSA") 47 { 48 #ifdef USE_ALSA 49 result = QSharedPointer<VolumeControl>(new VolumeControlALSA(device)); 50 #else 51 VERBOSE(VB_IMPORTANT, 52 QString("Volume control device is set to an ALSA device but " 53 "ALSA support is not compiled in!")); 54 #endif 55 } 56 else if (api == "CoreAudio") 57 { 58 #ifdef USE_COREAUDIO 59 result = QSharedPointer<VolumeControl>(new VolumeControlCoreAudio(device)); 60 #else 61 VERBOSE(VB_IMPORTANT, 62 QString("Volume control device is set to an Core Audio device " 63 "but Core Audio support is not compiled in!")); 64 #endif 65 } 66 else if (api == "OSS" || api.isEmpty()) 67 { 68 #ifdef USING_OSS 69 result = QSharedPointer<VolumeControl>(new VolumeControlOSS(device)); 70 #else 71 VERBOSE(VB_IMPORTANT, 72 QString("Volume control device is set to an OSS device but OSS " 73 "support is not compiled in!")); 74 #endif 75 } 76 else if (api == "Endpoint" || api.isEmpty()) 77 { 78 #ifdef USING_MINGW 79 result = QSharedPointer<VolumeControl>(new VolumeControlEndpoint(device)); 80 #else 81 VERBOSE(VB_IMPORTANT, 82 QString("Volume control device is set to an Endpoint device " 83 "but End Point support is not compiled in!")); 84 #endif 85 } 86 else if (api == "Software" || api.isEmpty()) 87 { 88 result = QSharedPointer<VolumeControl>(new VolumeControlSoftware(device)); 89 } 90 else 91 { 92 VERBOSE(VB_IMPORTANT, 93 QString("Volume control device is set to an unknown API \"%1\"") 94 .arg(api)); 95 } 96 97 return result; 98 } -
mythtv/libs/libmyth/volumecontrolalsa.cpp
1 #include "volumecontrolalsa.h" 2 3 #include "mythverbose.h" 4 #include <algorithm> 5 6 // static 7 QHash<QString, QString> VolumeControlALSA::Enumerate() 8 { 9 QHash<QString, QString> result; 10 11 result.insert("ALSA:default", "Default ALSA device"); 12 13 int card = -1; 14 while (snd_card_next(&card) >= 0 && card >= 0) 15 { 16 snd_ctl_t* handle; 17 if (!snd_ctl_open(&handle, 18 QString("hw:%1").arg(card).toAscii().constData(), 0)) 19 { 20 snd_ctl_card_info_t* info; 21 snd_ctl_card_info_alloca(&info); 22 23 if (!snd_ctl_card_info(handle, info)) 24 { 25 result.insert(QString("ALSA:hw:%1") 26 .arg(snd_ctl_card_info_get_id(info)), 27 snd_ctl_card_info_get_name(info)); 28 } 29 snd_ctl_close(handle); 30 } 31 } 32 33 return result; 34 } 35 36 VolumeControlALSA::VolumeControlALSA(QString device) : 37 m_MixerHandle(NULL), 38 m_MixerElement(NULL), 39 m_Range(1) 40 { 41 if (snd_mixer_open(&m_MixerHandle, 0) < 0) 42 { 43 VERBOSE(VB_IMPORTANT, 44 QString("VolumeControlALSA::VolumeControlALSA() - ERROR: " 45 "opening mixer")); 46 return; 47 } 48 49 if (snd_mixer_attach(m_MixerHandle, device.toAscii().constData()) < 0) 50 { 51 VERBOSE(VB_IMPORTANT, 52 QString("VolumeControlALSA::VolumeControlALSA() - ERROR: " 53 "attaching mixer \"%1\"") 54 .arg(device)); 55 return; 56 } 57 58 if (snd_mixer_selem_register(m_MixerHandle, NULL, NULL) < 0) 59 { 60 VERBOSE(VB_IMPORTANT, 61 QString("VolumeControlALSA::VolumeControlALSA() - ERROR: " 62 "registering mixer")); 63 return; 64 } 65 66 if (snd_mixer_load(m_MixerHandle) < 0) 67 { 68 VERBOSE(VB_IMPORTANT, 69 QString("VolumeControlALSA::VolumeControlALSA() - ERROR: " 70 "loading mixer")); 71 return; 72 } 73 74 for (m_MixerElement = snd_mixer_first_elem(m_MixerHandle); 75 m_MixerElement; 76 m_MixerElement = snd_mixer_elem_next(m_MixerElement)) 77 { 78 if (!snd_mixer_selem_is_active(m_MixerElement)) 79 continue; 80 81 if (!snd_mixer_selem_has_playback_volume(m_MixerElement)) 82 continue; 83 84 VERBOSE(VB_AUDIO, 85 QString("VolumeControlALSA::VolumeControlALSA() - " 86 "Using \"%1\"") 87 .arg(snd_mixer_selem_get_name(m_MixerElement))); 88 89 break; 90 } 91 92 if (!m_MixerElement) 93 { 94 VERBOSE(VB_IMPORTANT, 95 QString("VolumeControlALSA::VolumeControlALSA() - ERROR: " 96 "unable to find volume control")); 97 return; 98 } 99 100 long min, max; 101 snd_mixer_selem_get_playback_volume_range(m_MixerElement, &min, &max); 102 m_Range = std::min(std::max(1l, max - min), 100l); 103 104 snd_mixer_selem_set_playback_volume_range(m_MixerElement, 0, 100); 105 106 snd_mixer_elem_set_callback_private(m_MixerElement, this); 107 snd_mixer_elem_set_callback(m_MixerElement, &event); 108 109 if (!pipe(m_Exit)) 110 start(); 111 } 112 113 VolumeControlALSA::~VolumeControlALSA() 114 { 115 if (isRunning()) 116 { 117 write(m_Exit[1], "", 1); 118 119 wait(); 120 121 close(m_Exit[0]); 122 close(m_Exit[1]); 123 } 124 125 if (m_MixerHandle) 126 snd_mixer_close(m_MixerHandle); 127 } 128 129 int VolumeControlALSA::volume() const 130 { 131 long volume = 0; 132 if (m_MixerElement) 133 { 134 if (snd_mixer_selem_has_playback_switch(m_MixerElement) || !mute()) 135 snd_mixer_selem_get_playback_volume(m_MixerElement, 136 SND_MIXER_SCHN_MONO, 137 &volume); 138 else 139 volume = m_Volume; 140 } 141 142 VERBOSE(VB_AUDIO, 143 QString("VolumeControlALSA::volume() = %1") 144 .arg(volume)); 145 146 return volume; 147 } 148 149 void VolumeControlALSA::setVolume(int volume) 150 { 151 VERBOSE(VB_AUDIO, 152 QString("VolumeControlALSA::setVolume(%1)") 153 .arg(volume)); 154 155 volume = std::min(std::max(0, volume), 100); 156 157 if (mute() && volume > VolumeControlALSA::volume()) 158 setMute(false); 159 160 if (m_MixerElement) 161 if (snd_mixer_selem_has_playback_switch(m_MixerElement) || !mute()) 162 snd_mixer_selem_set_playback_volume_all(m_MixerElement, 163 volume); 164 165 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 166 emit changedVolume(volume); 167 } 168 169 void VolumeControlALSA::increaseVolume() 170 { 171 setVolume((volume() * m_Range + 100) / m_Range); 172 } 173 174 void VolumeControlALSA::decreaseVolume() 175 { 176 setVolume((volume() * m_Range - 100) / m_Range); 177 } 178 179 bool VolumeControlALSA::mute() const 180 { 181 union { 182 int _switch; 183 long int _volume; 184 } playback; 185 186 playback._switch = true; 187 188 if (m_MixerElement) 189 { 190 if (snd_mixer_selem_has_playback_switch(m_MixerElement)) 191 snd_mixer_selem_get_playback_switch(m_MixerElement, 192 SND_MIXER_SCHN_MONO, 193 &playback._switch); 194 else 195 snd_mixer_selem_get_playback_volume(m_MixerElement, 196 SND_MIXER_SCHN_MONO, 197 &playback._volume); 198 } 199 200 VERBOSE(VB_AUDIO, 201 QString("VolumeControlALSA::mute() = %1") 202 .arg(!playback._switch ? "mute" : "unmute")); 203 204 return !playback._switch; 205 } 206 207 void VolumeControlALSA::setMute(bool mute) 208 { 209 VERBOSE(VB_AUDIO, 210 QString("VolumeControlALSA::setMute(%1)") 211 .arg(mute ? "mute" : "unmute")); 212 213 if (m_MixerElement) 214 { 215 if (snd_mixer_selem_has_playback_switch(m_MixerElement)) 216 snd_mixer_selem_set_playback_switch_all(m_MixerElement, 217 !mute); 218 else 219 snd_mixer_selem_set_playback_volume_all(m_MixerElement, 220 mute ? 0 : static_cast<int>(m_Volume)); 221 } 222 223 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 224 emit changedMute(mute); 225 } 226 227 // static 228 int VolumeControlALSA::event(snd_mixer_elem_t* elem, unsigned int mask) 229 { 230 VERBOSE(VB_AUDIO, 231 QString("VolumeControlALSA::event(%1)") 232 .arg(mask)); 233 234 VolumeControlALSA* that = 235 static_cast<VolumeControlALSA*>(snd_mixer_elem_get_callback_private(elem)); 236 237 if (mask == SND_CTL_EVENT_MASK_REMOVE) 238 { 239 that->m_MixerElement = NULL; 240 return 0; 241 } 242 243 if (mask & SND_CTL_EVENT_MASK_VALUE) 244 { 245 int volume = that->volume(); 246 if (that->m_Volume.fetchAndStoreRelaxed(volume) != volume) 247 emit that->changedVolume(volume); 248 249 bool mute = that->mute(); 250 if (that->m_Mute.fetchAndStoreRelaxed(mute) != mute) 251 emit that->changedMute(mute); 252 } 253 254 return 0; 255 } 256 257 void VolumeControlALSA::run() 258 { 259 VERBOSE(VB_AUDIO, 260 QString("VolumeControlALSA::run() - begin")); 261 262 m_Volume = volume(); 263 m_Mute = mute(); 264 265 int poll_descriptors_count = -1; 266 struct pollfd* poll_descriptors = NULL; 267 268 for(;;) 269 { 270 int poll_descriptors_count_new = 271 snd_mixer_poll_descriptors_count(m_MixerHandle); 272 273 if (poll_descriptors_count_new < 0) 274 { 275 VERBOSE(VB_IMPORTANT, 276 QString("VolumeControlALSA::run() - ERROR: " 277 "snd_mixer_poll_descriptors_count")); 278 break; 279 } 280 281 if (poll_descriptors_count != poll_descriptors_count_new) 282 { 283 delete(poll_descriptors); 284 285 poll_descriptors_count = poll_descriptors_count_new; 286 poll_descriptors = new struct pollfd[poll_descriptors_count + 1]; 287 288 if (!poll_descriptors) 289 { 290 VERBOSE(VB_IMPORTANT, 291 QString("VolumeControlALSA::run() - ERROR: " 292 "malloc")); 293 break; 294 } 295 } 296 297 bzero(poll_descriptors, 298 poll_descriptors_count * sizeof (struct pollfd)); 299 300 poll_descriptors->fd = m_Exit[0]; 301 poll_descriptors->events = POLLIN; 302 303 if (snd_mixer_poll_descriptors(m_MixerHandle, 304 poll_descriptors + 1, 305 poll_descriptors_count) != 306 poll_descriptors_count) 307 { 308 VERBOSE(VB_IMPORTANT, 309 QString("VolumeControlALSA::run() - ERROR: " 310 "snd_mixer_poll_descriptors")); 311 break; 312 } 313 314 if (poll(poll_descriptors, poll_descriptors_count + 1, -1) < 0) 315 { 316 VERBOSE(VB_IMPORTANT, 317 QString("VolumeControlALSA::run() - ERROR: " 318 "poll %1") 319 .arg(errno)); 320 break; 321 } 322 323 if (poll_descriptors->revents & POLLIN) 324 break; 325 326 unsigned short revents; 327 if (snd_mixer_poll_descriptors_revents(m_MixerHandle, 328 poll_descriptors + 1, 329 poll_descriptors_count, 330 &revents) < 0) 331 { 332 VERBOSE(VB_IMPORTANT, 333 QString("VolumeControlALSA::run() - ERROR: " 334 "snd_mixer_poll_descriptors_revents")); 335 break; 336 } 337 338 if (revents & (POLLNVAL | POLLERR)) 339 { 340 VERBOSE(VB_IMPORTANT, 341 QString("VolumeControlALSA::run() - ERROR: " 342 "snd_mixer_poll_descriptors_revents")); 343 break; 344 } 345 346 if (snd_mixer_handle_events(m_MixerHandle) < 0) 347 { 348 VERBOSE(VB_IMPORTANT, 349 QString("VolumeControlALSA::run() - ERROR: " 350 "snd_mixer_handle_events")); 351 break; 352 } 353 } 354 355 delete(poll_descriptors); 356 357 VERBOSE(VB_AUDIO, 358 QString("VolumeControlALSA::run() - end")); 359 } -
mythtv/libs/libmyth/audiooutputbase.h
19 19 #include "audiooutputsettings.h" 20 20 #include "samplerate.h" 21 21 #include "mythverbose.h" 22 #include "volumecontrolmanager.h" 22 23 23 24 #define VBAUDIO(str) VERBOSE(VB_AUDIO, LOC + str) 24 25 #define VBAUDIOTS(str) VERBOSE(VB_AUDIO+VB_TIMESTAMP, LOC + str) … … 53 54 54 55 virtual void Reset(void); 55 56 56 void SetSWVolume(int new_volume, bool save);57 int GetSWVolume(void);58 59 57 // timecode is in milliseconds. 60 58 virtual bool AddSamples(void *buffer, int frames, long long timecode); 61 59 … … 143 141 bool killaudio; 144 142 145 143 bool pauseaudio, actually_paused, was_paused, unpause_when_ready; 146 bool set_initial_vol;147 144 bool buffer_output_data_for_use; // used by AudioOutputNULL 148 145 149 146 int configured_channels; … … 168 165 int surround_mode; 169 166 bool allow_ac3_passthru; 170 167 float old_stretchfactor; 171 int volume;168 QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface 172 169 QString volumeControl; 173 170 174 171 bool processing; -
mythtv/libs/libmyth/audiooutputalsa.cpp
1 #include "audiooutputalsa.h" 2 1 3 #include <cstdio> 2 4 #include <cstdlib> 3 5 #include <sys/time.h> … … 8 10 9 11 #include <QFile> 10 12 #include "mythcorecontext.h" 11 #include "audiooutputalsa.h"12 13 13 14 #define LOC QString("ALSA: ") 14 15 #define LOC_WARN QString("ALSA, Warning: ") … … 40 41 m_device(-1), 41 42 m_subdevice(-1) 42 43 { 43 m_mixer.handle = NULL;44 m_mixer.elem = NULL;45 46 44 // Set everything up 47 45 Reconfigure(settings); 48 46 } … … 397 395 return OpenDevice(); 398 396 } 399 397 400 if (internal_vol && !OpenMixer())401 {402 CloseDevice();403 return false;404 }405 406 398 // Device opened successfully 407 399 return true; 408 400 } 409 401 410 402 void AudioOutputALSA::CloseDevice() 411 403 { 412 if (m_mixer.handle)413 snd_mixer_close(m_mixer.handle);414 m_mixer.handle = NULL;415 404 if (pcm_handle) 416 405 { 417 406 snd_pcm_close(pcm_handle); … … 660 649 return 0; 661 650 } 662 651 663 int AudioOutputALSA::GetVolumeChannel(int channel) const664 {665 int retvol = 0;666 667 if (!m_mixer.elem)668 return retvol;669 670 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;671 if (!snd_mixer_selem_has_playback_channel(m_mixer.elem, chan))672 return retvol;673 674 long mixervol;675 int chk;676 if ((chk = snd_mixer_selem_get_playback_volume(m_mixer.elem,677 chan,678 &mixervol)) < 0)679 {680 VBERROR(QString("failed to get channel %1 volume, mixer %2/%3: %4")681 .arg(channel).arg(m_mixer.device)682 .arg(m_mixer.control)683 .arg(snd_strerror(chk)));684 }685 else686 {687 retvol = (m_mixer.volrange != 0L) ? (mixervol - m_mixer.volmin) *688 100.0f / m_mixer.volrange + 0.5f689 : 0;690 retvol = max(retvol, 0);691 retvol = min(retvol, 100);692 VBAUDIO(QString("get volume channel %1: %2")693 .arg(channel).arg(retvol));694 }695 return retvol;696 }697 698 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)699 {700 if (!(internal_vol && m_mixer.elem))701 return;702 703 long mixervol = volume * m_mixer.volrange / 100.0f - m_mixer.volmin + 0.5f;704 mixervol = max(mixervol, m_mixer.volmin);705 mixervol = min(mixervol, m_mixer.volmax);706 707 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;708 if (snd_mixer_selem_set_playback_volume(m_mixer.elem, chan, mixervol) < 0)709 VBERROR(QString("failed to set channel %1 volume").arg(channel));710 else711 VBAUDIO(QString("channel %1 volume set %2 => %3")712 .arg(channel).arg(volume).arg(mixervol));713 }714 715 bool AudioOutputALSA::OpenMixer(void)716 {717 if (!pcm_handle)718 {719 VBERROR("mixer setup without a pcm");720 return false;721 }722 m_mixer.device = gCoreContext->GetSetting("MixerDevice", "default");723 m_mixer.device = m_mixer.device.remove(QString("ALSA:"));724 if (m_mixer.device.toLower() == "software")725 return true;726 727 m_mixer.control = gCoreContext->GetSetting("MixerControl", "PCM");728 729 QString mixer_device_tag = QString("mixer device %1").arg(m_mixer.device);730 731 int chk;732 if ((chk = snd_mixer_open(&m_mixer.handle, 0)) < 0)733 {734 VBERROR(QString("failed to open mixer device %1: %2")735 .arg(mixer_device_tag).arg(snd_strerror(chk)));736 return false;737 }738 739 QByteArray dev_ba = m_mixer.device.toAscii();740 struct snd_mixer_selem_regopt regopts =741 {1, SND_MIXER_SABSTRACT_NONE, dev_ba.constData(), NULL, NULL};742 743 if ((chk = snd_mixer_selem_register(m_mixer.handle, ®opts, NULL)) < 0)744 {745 snd_mixer_close(m_mixer.handle);746 m_mixer.handle = NULL;747 VBERROR(QString("failed to register %1: %2")748 .arg(mixer_device_tag).arg(snd_strerror(chk)));749 return false;750 }751 752 if ((chk = snd_mixer_load(m_mixer.handle)) < 0)753 {754 snd_mixer_close(m_mixer.handle);755 m_mixer.handle = NULL;756 VBERROR(QString("failed to load %1: %2")757 .arg(mixer_device_tag).arg(snd_strerror(chk)));758 return false;759 }760 761 m_mixer.elem = NULL;762 uint elcount = snd_mixer_get_count(m_mixer.handle);763 snd_mixer_elem_t* elx = snd_mixer_first_elem(m_mixer.handle);764 765 for (uint ctr = 0; elx != NULL && ctr < elcount; ctr++)766 {767 QString tmp = QString(snd_mixer_selem_get_name(elx));768 if (m_mixer.control == tmp &&769 !snd_mixer_selem_is_enumerated(elx) &&770 snd_mixer_selem_has_playback_volume(elx) &&771 snd_mixer_selem_is_active(elx))772 {773 m_mixer.elem = elx;774 VBAUDIO(QString("found playback control %1 on %2")775 .arg(m_mixer.control)776 .arg(mixer_device_tag));777 break;778 }779 elx = snd_mixer_elem_next(elx);780 }781 if (!m_mixer.elem)782 {783 snd_mixer_close(m_mixer.handle);784 m_mixer.handle = NULL;785 VBERROR(QString("no playback control %1 found on %2")786 .arg(m_mixer.control).arg(mixer_device_tag));787 return false;788 }789 if ((snd_mixer_selem_get_playback_volume_range(m_mixer.elem,790 &m_mixer.volmin,791 &m_mixer.volmax) < 0))792 {793 snd_mixer_close(m_mixer.handle);794 m_mixer.handle = NULL;795 VBERROR(QString("failed to get volume range on %1/%2")796 .arg(mixer_device_tag).arg(m_mixer.control));797 return false;798 }799 800 m_mixer.volrange = m_mixer.volmax - m_mixer.volmin;801 VBAUDIO(QString("mixer volume range on %1/%2 - min %3, max %4, range %5")802 .arg(mixer_device_tag).arg(m_mixer.control)803 .arg(m_mixer.volmin).arg(m_mixer.volmax).arg(m_mixer.volrange));804 VBAUDIO(QString("%1/%2 set up successfully")805 .arg(mixer_device_tag)806 .arg(m_mixer.control));807 808 if (set_initial_vol)809 {810 int initial_vol;811 if (m_mixer.control == "PCM")812 initial_vol = gCoreContext->GetNumSetting("PCMMixerVolume", 80);813 else814 initial_vol = gCoreContext->GetNumSetting("MasterMixerVolume", 80);815 for (int ch = 0; ch < channels; ++ch)816 SetVolumeChannel(ch, initial_vol);817 }818 819 return true;820 }821 822 652 QMap<QString, QString> *AudioOutputALSA::GetALSADevices(const char *type) 823 653 { 824 654 QMap<QString, QString> *alsadevs = new QMap<QString, QString>(); -
mythtv/libs/libmyth/volumebase.cpp
1 #include <cstdio>2 #include <cstdlib>3 4 #include <algorithm>5 using namespace std;6 7 #include <QString>8 9 #include "volumebase.h"10 #include "mythcorecontext.h"11 12 VolumeBase::VolumeBase() :13 internal_vol(false), volume(80),14 current_mute_state(kMuteOff)15 {16 swvol = swvol_setting =17 (gCoreContext->GetSetting("MixerDevice", "default").toLower() == "software");18 }19 20 bool VolumeBase::SWVolume(void)21 {22 return swvol;23 }24 25 void VolumeBase::SWVolume(bool set)26 {27 if (swvol_setting)28 return;29 swvol = set;30 }31 32 uint VolumeBase::GetCurrentVolume(void) const33 {34 return volume;35 }36 37 void VolumeBase::SetCurrentVolume(int value)38 {39 volume = max(min(value, 100), 0);40 UpdateVolume();41 42 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");43 controlLabel += "MixerVolume";44 gCoreContext->SaveSetting(controlLabel, volume);45 }46 47 void VolumeBase::AdjustCurrentVolume(int change)48 {49 SetCurrentVolume(volume + change);50 }51 52 MuteState VolumeBase::SetMuteState(MuteState mstate)53 {54 current_mute_state = mstate;55 UpdateVolume();56 return current_mute_state;57 }58 59 void VolumeBase::ToggleMute(void)60 {61 bool is_muted = GetMuteState() == kMuteAll;62 SetMuteState((is_muted) ? kMuteOff : kMuteAll);63 }64 65 MuteState VolumeBase::GetMuteState(void) const66 {67 return current_mute_state;68 }69 70 MuteState VolumeBase::NextMuteState(MuteState cur)71 {72 MuteState next = cur;73 74 switch (cur)75 {76 case kMuteOff:77 next = kMuteLeft;78 break;79 case kMuteLeft:80 next = kMuteRight;81 break;82 case kMuteRight:83 next = kMuteAll;84 break;85 case kMuteAll:86 next = kMuteOff;87 break;88 }89 90 return (next);91 }92 93 void VolumeBase::UpdateVolume(void)94 {95 int new_volume = volume;96 bool save = true;97 if (current_mute_state == kMuteAll)98 {99 new_volume = 0;100 save = false;101 }102 103 if (swvol)104 {105 SetSWVolume(new_volume, save);106 return;107 }108 109 for (int i = 0; i < channels; i++)110 {111 SetVolumeChannel(i, new_volume);112 }113 114 // Individual channel muting is handled in GetAudioData,115 // this code demonstrates the old method.116 // if (current_mute_state == kMuteLeft)117 // {118 // SetVolumeChannel(0, 0);119 // }120 // else if (current_mute_state == kMuteRight)121 // {122 // SetVolumeChannel(1, 0);123 // }124 }125 126 void VolumeBase::SyncVolume(void)127 {128 // Read the volume from the audio driver and setup our internal state to match129 if (swvol)130 volume = GetSWVolume();131 else132 volume = GetVolumeChannel(0);133 }134 135 void VolumeBase::SetChannels(int new_channels)136 {137 channels = new_channels;138 } -
mythtv/libs/libmyth/volumecontrolcoreaudio.h
1 #ifndef VOLUMECONTROLCOREAUDIO 2 #define VOLUMECONTROLCOREAUDIO 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QAtomicInt> 8 #include <CoreAudio/CoreAudio.h> 9 10 11 class VolumeControlCoreAudio : public VolumeControl 12 { 13 public: 14 static QHash<QString, QString> Enumerate(); 15 16 public: 17 VolumeControlCoreAudio(QString device); 18 virtual ~VolumeControlCoreAudio(); 19 20 public: 21 int volume() const; 22 void setVolume(int volume); 23 void increaseVolume(); 24 void decreaseVolume(); 25 26 bool mute() const; 27 void setMute(bool mute); 28 29 protected: 30 static OSStatus event(AudioDeviceID deviceId, UInt32 channel, 31 Boolean input, AudioDevicePropertyID property, 32 void* context); 33 34 private: 35 AudioDeviceID m_DeviceId; //< Core Audio device ID 36 QAtomicInt m_Volume; //< Volume state cache 37 QAtomicInt m_Mute; //< Mute state cache 38 }; 39 40 #endif // VOLUMECONTROLCOREAUDIO -
mythtv/libs/libmyth/volumecontrolsoftware.h
1 #ifndef VOLUMECONTROLSOFTWARE 2 #define VOLUMECONTROLSOFTWARE 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QAtomicInt> 8 9 10 class VolumeControlSoftware : public VolumeControl 11 { 12 public: 13 static QHash<QString, QString> Enumerate(); 14 15 public: 16 VolumeControlSoftware(QString device); 17 virtual ~VolumeControlSoftware(); 18 19 public: 20 int volume() const; 21 void setVolume(int volume); 22 void increaseVolume(); 23 void decreaseVolume(); 24 25 bool mute() const; 26 void setMute(bool mute); 27 28 private: 29 static QAtomicInt m_Volume; //< Volume state cache 30 static QAtomicInt m_Mute; //< Mute state cache 31 }; 32 33 #endif // VOLUMECONTROLSOFTWARE -
mythtv/libs/libmyth/volumecontrolcoreaudio.cpp
1 #include "volumecontrolcoreaudio.h" 2 3 #include <CoreServices/CoreServices.h> 4 #include <CoreAudio/CoreAudio.h> 5 6 #include "mythverbose.h" 7 #include <algorithm> 8 9 // static 10 QHash<QString, QString> VolumeControlCoreAudio::Enumerate() 11 { 12 QHash<QString, QString> result; 13 14 result.insert("CoreAudio:default", "Default Core Audio device"); 15 16 UInt32 size; 17 AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, 18 &size, NULL); 19 UInt32 count = size / sizeof(AudioDeviceID); 20 21 AudioDeviceID* devices = new AudioDeviceID[count]; 22 AudioHardwareGetProperty(kAudioHardwarePropertyDevices, 23 &size, devices); 24 25 for (unsigned int index = 0; index < count; ++index) 26 { 27 bool output = false; 28 29 AudioDeviceGetPropertyInfo(devices[index], 0, 0, 30 kAudioDevicePropertyStreamConfiguration, 31 &size, NULL); 32 if (!size) 33 continue; 34 35 AudioBufferList* buffers = static_cast<AudioBufferList*>(malloc(size)); 36 AudioDeviceGetProperty(devices[index], 0, 0, 37 kAudioDevicePropertyStreamConfiguration, 38 &size, buffers); 39 for (UInt32 buffer = 0; buffer < buffers->mNumberBuffers; ++buffer) 40 { 41 if (buffers->mBuffers[buffer].mNumberChannels) 42 { 43 output = true; 44 break; 45 } 46 } 47 48 free(buffers); 49 50 if (!output) 51 continue; 52 53 QString uid; 54 CFStringRef uidcf; 55 size = sizeof(CFStringRef); 56 AudioDeviceGetProperty(devices[index], 0, 0, 57 kAudioDevicePropertyDeviceUID, 58 &size, &uidcf); 59 if (uidcf) 60 { 61 char buffer[256]; 62 CFStringGetCString(uidcf, buffer, 256, 63 CFStringGetFastestEncoding(uidcf)); 64 uid = QString(buffer); 65 CFRelease(uidcf); 66 } 67 68 AudioDeviceGetPropertyInfo(devices[index], 0, 0, 69 kAudioDevicePropertyDeviceName, 70 &size, NULL); 71 if (!size) 72 continue; 73 74 char* name = static_cast<char*>(malloc(size)); 75 AudioDeviceGetProperty(devices[index], 0, 0, 76 kAudioDevicePropertyDeviceName, 77 &size, name); 78 79 result.insert(QString("CoreAudio:") + uid, name); 80 81 free(name); 82 } 83 84 delete devices; 85 86 return result; 87 } 88 89 VolumeControlCoreAudio::VolumeControlCoreAudio(QString device) : 90 m_DeviceId(kAudioDeviceUnknown) 91 { 92 if (device == QString("default")) 93 { 94 UInt32 size = sizeof(AudioDeviceID); 95 AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, 96 &size, &m_DeviceId); 97 } 98 else 99 { 100 CFStringRef cfString = 101 CFStringCreateWithCharacters(kCFAllocatorDefault, 102 reinterpret_cast<const UniChar*>(device.unicode()), 103 device.length()); 104 105 AudioValueTranslation translateUidToId = { 106 mInputData: &cfString, 107 mInputDataSize: sizeof(CFStringRef), 108 mOutputData: &m_DeviceId, 109 mOutputDataSize: sizeof(AudioDeviceID) 110 }; 111 112 UInt32 translateUidToIdSize = sizeof(AudioValueTranslation); 113 AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, 114 &translateUidToIdSize, 115 &translateUidToId); 116 CFRelease(cfString); 117 } 118 119 AudioDeviceAddPropertyListener(m_DeviceId, 1, false, 120 kAudioDevicePropertyVolumeScalar, 121 &event, 122 this); 123 124 AudioDeviceAddPropertyListener(m_DeviceId, 1, false, 125 kAudioDevicePropertyVolumeDecibels, 126 &event, 127 this); 128 129 AudioDeviceAddPropertyListener(m_DeviceId, 0, false, 130 kAudioDevicePropertyMute, 131 &event, 132 this); 133 134 m_Volume = volume(); 135 m_Mute = mute(); 136 } 137 138 VolumeControlCoreAudio::~VolumeControlCoreAudio() 139 { 140 AudioDeviceRemovePropertyListener(m_DeviceId, 1, false, 141 kAudioDevicePropertyVolumeScalar, 142 &event); 143 144 AudioDeviceRemovePropertyListener(m_DeviceId, 1, false, 145 kAudioDevicePropertyVolumeDecibels, 146 &event); 147 148 AudioDeviceRemovePropertyListener(m_DeviceId, 0, false, 149 kAudioDevicePropertyMute, 150 &event); 151 } 152 153 int VolumeControlCoreAudio::volume() const 154 { 155 Float32 volume = 0; 156 157 if (!mute()) 158 { 159 UInt32 size = sizeof(Float32); 160 AudioDeviceGetProperty(m_DeviceId, 1, false, 161 kAudioDevicePropertyVolumeScalar, 162 &size, &volume); 163 } 164 else 165 volume = static_cast<Float32>(m_Volume) / 100.0f; 166 167 VERBOSE(VB_AUDIO, 168 QString("VolumeControlCoreAudio::volume() = %1") 169 .arg(static_cast<int>(100.0f * volume))); 170 171 return static_cast<int>(100.0f * volume); 172 } 173 174 void VolumeControlCoreAudio::setVolume(int volume) 175 { 176 VERBOSE(VB_AUDIO, 177 QString("VolumeControlCoreAudio::setVolume(%1)") 178 .arg(volume)); 179 180 volume = std::min(std::max(0, volume), 100); 181 182 if (mute() && volume > VolumeControlCoreAudio::volume()) 183 setMute(false); 184 185 if (!mute()) 186 { 187 Float32 value = static_cast<Float32>(volume) / 100.0f; 188 AudioDeviceSetProperty(m_DeviceId, NULL, 1, false, 189 kAudioDevicePropertyVolumeScalar, 190 sizeof(UInt32), &value); 191 } 192 193 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 194 emit changedVolume(volume); 195 } 196 197 void VolumeControlCoreAudio::increaseVolume() 198 { 199 setVolume(volume() + 10); 200 } 201 202 void VolumeControlCoreAudio::decreaseVolume() 203 { 204 setVolume(volume() - 10); 205 } 206 207 bool VolumeControlCoreAudio::mute() const 208 { 209 UInt32 mute = false; 210 211 UInt32 size = sizeof(UInt32); 212 AudioDeviceGetProperty(m_DeviceId, 0, false, 213 kAudioDevicePropertyMute, &size, &mute); 214 215 VERBOSE(VB_AUDIO, 216 QString("VolumeControlCoreAudio::mute() = %1") 217 .arg(mute ? "mute" : "unmute")); 218 219 return mute; 220 } 221 222 void VolumeControlCoreAudio::setMute(bool mute) 223 { 224 VERBOSE(VB_AUDIO, 225 QString("VolumeControlCoreAudio::setMute(%1)") 226 .arg(mute ? "mute" : "unmute")); 227 228 if (VolumeControlCoreAudio::mute()) 229 { 230 Float32 value = static_cast<Float32>(m_Volume) / 100.0f; 231 AudioDeviceSetProperty(m_DeviceId, NULL, 1, false, 232 kAudioDevicePropertyVolumeScalar, 233 sizeof(UInt32), &value); 234 } 235 236 UInt32 value = mute; 237 AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, 238 kAudioDevicePropertyMute, sizeof(UInt32), &value); 239 240 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 241 emit changedMute(mute); 242 } 243 244 // static 245 OSStatus VolumeControlCoreAudio::event(AudioDeviceID deviceId, UInt32 channel, 246 Boolean input, 247 AudioDevicePropertyID property, 248 void* context) 249 { 250 VolumeControlCoreAudio* that = 251 static_cast<VolumeControlCoreAudio*>(context); 252 253 if (deviceId == that->m_DeviceId && !input) 254 switch(property) 255 { 256 case kAudioDevicePropertyVolumeScalar: 257 case kAudioDevicePropertyVolumeDecibels: 258 int volume = that->volume(); 259 if (that->m_Volume.fetchAndStoreRelaxed(volume) != volume) 260 emit that->changedVolume(volume); 261 break; 262 263 case kAudioDevicePropertyMute: 264 bool mute = that->mute(); 265 if (that->m_Mute.fetchAndStoreRelaxed(mute) != mute) 266 emit that->changedMute(mute); 267 break; 268 } 269 270 return noErr; 271 } -
mythtv/libs/libmyth/volumebase.h
1 #ifndef __VOLUME_BASE__2 #define __VOLUME_BASE__3 4 #include "mythexp.h"5 6 typedef enum {7 kMuteOff = 0,8 kMuteLeft,9 kMuteRight,10 kMuteAll,11 } MuteState;12 13 class MPUBLIC VolumeBase14 {15 public:16 VolumeBase();17 virtual ~VolumeBase() {};18 19 void SWVolume(bool set);20 bool SWVolume(void);21 virtual uint GetCurrentVolume(void) const;22 virtual void SetCurrentVolume(int value);23 virtual void AdjustCurrentVolume(int change);24 virtual void ToggleMute(void);25 26 virtual MuteState GetMuteState(void) const;27 virtual MuteState SetMuteState(MuteState);28 29 static MuteState NextMuteState(MuteState);30 31 protected:32 33 virtual int GetVolumeChannel(int channel) const = 0; // Returns 0-10034 virtual void SetVolumeChannel(int channel, int volume) = 0; // range 0-100 for vol35 virtual void SetSWVolume(int new_volume, bool save) = 0;36 virtual int GetSWVolume(void) = 0;37 38 void UpdateVolume(void);39 void SyncVolume(void);40 void SetChannels(int new_channels);41 bool internal_vol;42 43 private:44 45 int volume;46 MuteState current_mute_state;47 bool swvol;48 bool swvol_setting;49 int channels;50 51 };52 53 #endif // __VOLUME_BASE__ -
mythtv/libs/libmyth/volumecontrol.h
1 #ifndef VOLUMECONTROL 2 #define VOLUMECONTROL 3 4 #include <QObject> 5 #include <QString> 6 7 class VolumeControl : public QObject 8 { 9 Q_OBJECT 10 11 public: 12 virtual int volume() const = 0; 13 virtual void setVolume(int volume) = 0; 14 virtual void increaseVolume() = 0; 15 virtual void decreaseVolume() = 0; 16 17 virtual bool mute() const = 0; 18 virtual void setMute(bool mute) = 0; 19 20 signals: 21 void changedVolume(int volume); 22 void changedMute(bool mute); 23 }; 24 25 #endif // VOLUMECONTROL -
mythtv/libs/libmyth/volumecontrolsoftware.cpp
1 #include "volumecontrolsoftware.h" 2 3 #include "mythcorecontext.h" 4 #include "mythverbose.h" 5 #include <algorithm> 6 7 // static 8 QHash<QString, QString> VolumeControlSoftware::Enumerate() 9 { 10 QHash<QString, QString> result; 11 12 result.insert("Software:", "Software Volume Processing"); 13 14 return result; 15 } 16 17 VolumeControlSoftware::VolumeControlSoftware(QString device) 18 { 19 int volume = gCoreContext->GetNumSetting("SoftwareVolume", 80); 20 m_Volume = std::min(std::max(0, volume), 100); 21 m_Mute = gCoreContext->GetNumSetting("SoftwareMute", false) ? true : false; 22 } 23 24 VolumeControlSoftware::~VolumeControlSoftware() 25 { 26 27 } 28 29 int VolumeControlSoftware::volume() const 30 { 31 int volume = m_Volume; 32 33 VERBOSE(VB_AUDIO, 34 QString("VolumeControlSoftware::volume() = %1") 35 .arg(volume)); 36 37 return volume; 38 } 39 40 void VolumeControlSoftware::setVolume(int volume) 41 { 42 VERBOSE(VB_AUDIO, 43 QString("VolumeControlSoftware::setVolume(%1)") 44 .arg(volume)); 45 46 volume = std::min(std::max(0, volume), 100); 47 48 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 49 { 50 gCoreContext->SaveSetting("SoftwareVolume", volume); 51 emit changedVolume(volume); 52 } 53 } 54 55 void VolumeControlSoftware::increaseVolume() 56 { 57 setVolume(volume() + 1); 58 } 59 60 void VolumeControlSoftware::decreaseVolume() 61 { 62 setVolume(volume() - 1); 63 } 64 65 bool VolumeControlSoftware::mute() const 66 { 67 bool mute = m_Mute ? true : false; 68 69 VERBOSE(VB_AUDIO, 70 QString("VolumeControlSoftware::mute() = %1") 71 .arg(mute ? "mute" : "unmute")); 72 73 return mute; 74 } 75 76 void VolumeControlSoftware::setMute(bool mute) 77 { 78 VERBOSE(VB_AUDIO, 79 QString("VolumeControlSoftware::setMute(%1)") 80 .arg(mute ? "mute" : "unmute")); 81 82 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 83 { 84 gCoreContext->SaveSetting("SoftwareMute", mute); 85 emit changedMute(mute); 86 } 87 } 88 89 QAtomicInt VolumeControlSoftware::m_Volume; 90 QAtomicInt VolumeControlSoftware::m_Mute; -
mythtv/libs/libmyth/audiooutputpulse.h
30 30 AudioOutputPulseAudio(const AudioSettings &settings); 31 31 ~AudioOutputPulseAudio(); 32 32 33 int GetVolumeChannel(int channel) const;34 void SetVolumeChannel(int channel, int volume);35 33 void Drain(void); 36 34 37 35 protected: -
mythtv/libs/libmyth/volumecontroloss.h
1 #ifndef VOLUMECONTROLOSS 2 #define VOLUMECONTROLOSS 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QThread> 8 #include <QAtomicInt> 9 10 11 class VolumeControlOSS : public VolumeControl, protected QThread 12 { 13 public: 14 static QHash<QString, QString> Enumerate(); 15 16 public: 17 VolumeControlOSS(QString device); 18 virtual ~VolumeControlOSS(); 19 20 public: 21 int volume() const; 22 void setVolume(int volume); 23 void increaseVolume(); 24 void decreaseVolume(); 25 26 bool mute() const; 27 void setMute(bool mute); 28 29 protected: 30 virtual void run(); 31 32 private: 33 int m_Mixer; //< OSS mixer file descriptor 34 int m_MixerDev; //< OSS mixer device ID 35 int m_VolumeCtrl; //< OSS control ID for volume 36 int m_VolumeMax; //< OSS maximum for volume 37 int m_VolumeType; //< OSS control type for volume 38 int m_VolumeTimestamp; //< OSS timestamp for volume 39 int m_MuteCtrl; //< OSS control ID for mute 40 int m_MuteTimestamp; //< OSS timestamp for mute 41 int m_Range; //< Range of volume control 42 volatile bool m_Exit; //< Flag to notify thread to exit 43 QAtomicInt m_Volume; //< Volume state cache 44 QAtomicInt m_Mute; //< Mute state cache 45 }; 46 47 #endif // VOLUMECONTROLOSS -
mythtv/libs/libmyth/volumecontrolalsa.h
1 #ifndef VOLUMECONTROLALSA 2 #define VOLUMECONTROLALSA 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QThread> 8 #include <QAtomicInt> 9 #include <alsa/asoundlib.h> 10 11 12 class VolumeControlALSA : public VolumeControl, protected QThread 13 { 14 public: 15 static QHash<QString, QString> Enumerate(); 16 17 public: 18 VolumeControlALSA(QString device); 19 virtual ~VolumeControlALSA(); 20 21 public: 22 int volume() const; 23 void setVolume(int volume); 24 void increaseVolume(); 25 void decreaseVolume(); 26 27 bool mute() const; 28 void setMute(bool mute); 29 30 protected: 31 virtual void run(); 32 33 static int event(snd_mixer_elem_t* elem, unsigned int mask); 34 35 private: 36 snd_mixer_t* m_MixerHandle; //< ALSA mixer handle 37 snd_mixer_elem_t* m_MixerElement; //< ALSA mixer element handle 38 int m_Range; //< Range of mixer element 39 int m_Exit[2]; //< Pipe file descriptors 40 QAtomicInt m_Volume; //< Volume state cache 41 QAtomicInt m_Mute; //< Mute state cache 42 }; 43 44 #endif // VOLUMECONTROLALSA -
mythtv/libs/libmyth/audiooutputpulse.cpp
306 306 return (int)latency * samplerate * output_bytes_per_frame / 1000000; 307 307 } 308 308 309 int AudioOutputPulseAudio::GetVolumeChannel(int channel) const310 {311 return (float)volume_control.values[channel] /312 (float)PA_VOLUME_NORM * 100.0f;313 }314 315 void AudioOutputPulseAudio::SetVolumeChannel(int channel, int volume)316 {317 QString fn_log_tag = "SetVolumeChannel, ";318 319 if (channel < 0 || channel > PULSE_MAX_CHANNELS || volume < 0)320 {321 VBERROR(fn_log_tag + QString("bad volume params, channel %1, volume %2")322 .arg(channel).arg(volume));323 return;324 }325 326 volume_control.values[channel] =327 (float)volume / 100.0f * (float)PA_VOLUME_NORM;328 329 volume = min(100, volume);330 volume = max(0, volume);331 332 uint32_t sink_index = pa_stream_get_device_index(pstream);333 pa_threaded_mainloop_lock(mainloop);334 pa_operation *op =335 pa_context_set_sink_volume_by_index(pcontext, sink_index,336 &volume_control,337 OpCompletionCallback, this);338 pa_threaded_mainloop_unlock(mainloop);339 if (op)340 pa_operation_unref(op);341 else342 VBERROR(fn_log_tag +343 QString("set sink volume operation failed, sink %1, error %2 ")344 .arg(sink_index).arg(pa_strerror(pa_context_errno(pcontext))));345 }346 347 309 void AudioOutputPulseAudio::Drain(void) 348 310 { 349 311 AudioOutputBase::Drain(); … … 487 449 pa_stream_set_overflow_callback(pstream, BufferFlowCallback, (char*)"over"); 488 450 pa_stream_set_underflow_callback(pstream, BufferFlowCallback, 489 451 (char*)"under"); 490 if (set_initial_vol) 491 { 492 int volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80); 493 pa_cvolume_set(&volume_control, channels, 494 (float)volume * (float)PA_VOLUME_NORM / 100.0f); 495 } 496 else 497 pa_cvolume_reset(&volume_control, channels); 452 pa_cvolume_reset(&volume_control, channels); 498 453 499 454 fragment_size = (samplerate * 25 * output_bytes_per_frame) / 1000; 500 455 -
mythtv/libs/libmyth/volumecontrolendpoint.cpp
1 #include "volumecontrolendpoint.h" 2 3 #include "mythverbose.h" 4 #include <algorithm> 5 #include <math.h> 6 7 typedef struct _BYTE_BLOB 8 { 9 unsigned long clSize; 10 byte abData[ 1 ]; 11 } BYTE_BLOB; 12 13 typedef struct _tagpropertykey 14 { 15 GUID fmtid; 16 DWORD pid; 17 } PROPERTYKEY; 18 19 #define REFPROPVARIANT const PROPVARIANT & 20 21 inline void PropVariantInit ( PROPVARIANT * pvar ) 22 { 23 memset ( pvar, 0, sizeof(PROPVARIANT) ); 24 } 25 WINOLEAPI PropVariantClear ( PROPVARIANT * pvar ); 26 27 EXTERN_C const CLSID CLSID_MMDeviceEnumerator = {0xBCDE0395,0xE52F,0x467C,{0x8E,0x3D,0xC4,0x57,0x92,0x91,0x69,0x2E}}; 28 EXTERN_C const IID IID_IMMDeviceEnumerator = {0xA95664D2,0x9614,0x4F35,{0xA7,0x46,0xDE,0x8D,0xB6,0x36,0x17,0xE6}}; 29 EXTERN_C const IID IID_IAudioEndpointVolume = {0x5CDF2C82,0x841E,0x4546,{0x97,0x22,0x0C,0xF7,0x40,0x78,0x22,0x9A}}; 30 EXTERN_C const IID IID_IAudioEndpointVolumeCallback = {0x657804FA,0xD6AD,0x4496,{0x8A,0x60,0x35,0x27,0x52,0xAF,0x4F,0x89}}; 31 EXTERN_C const IID IID_IUnknown = {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; 32 #define INITGUID 33 #include <Unknwn.h> 34 #include <mmdeviceapi.h> 35 #include <FunctionDiscoveryKeys_devpkey.h> 36 37 38 QHash<QString, QString> VolumeControlEndpoint::Enumerate() 39 { 40 QHash<QString, QString> result; 41 42 HRESULT hr = S_OK; 43 IMMDeviceEnumerator* pEnumerator = NULL; 44 IMMDeviceCollection* pCollection = NULL; 45 46 CoInitialize(NULL); 47 48 // Get enumerator for audio endpoint devices. 49 hr = CoCreateInstance(CLSID_MMDeviceEnumerator, 50 NULL, CLSCTX_INPROC_SERVER, 51 IID_IMMDeviceEnumerator, 52 (void**)&pEnumerator); 53 if (!SUCCEEDED(hr) || !pEnumerator) 54 { 55 CoUninitialize(); 56 return result; 57 } 58 59 result.insert("Endpoint:default", "Default End Point device"); 60 61 hr = pEnumerator->EnumAudioEndpoints(eRender, 62 DEVICE_STATE_ACTIVE, 63 &pCollection); 64 if (!SUCCEEDED(hr) || !pCollection) 65 { 66 pEnumerator->Release(); 67 CoUninitialize(); 68 return result; 69 } 70 71 UINT devices = 0; 72 hr = pCollection->GetCount(&devices); 73 if (!SUCCEEDED(hr)) 74 { 75 pCollection->Release(); 76 pEnumerator->Release(); 77 CoUninitialize(); 78 return result; 79 } 80 81 for (UINT device = 0; device < devices; ++device) 82 { 83 IMMDevice* pDevice = NULL; 84 hr = pCollection->Item(device, &pDevice); 85 if (!SUCCEEDED(hr) || !pDevice) 86 continue; 87 88 LPWSTR pwszID = NULL; 89 hr = pDevice->GetId(&pwszID); 90 if (!SUCCEEDED(hr)) 91 { 92 pDevice->Release(); 93 continue; 94 } 95 QString uid(reinterpret_cast<const QChar*>(pwszID), wcslen(pwszID)); 96 CoTaskMemFree(pwszID); 97 98 IPropertyStore *pProps = NULL; 99 hr = pDevice->OpenPropertyStore(STGM_READ, &pProps); 100 if (!SUCCEEDED(hr) || !pProps) 101 { 102 pDevice->Release(); 103 continue; 104 } 105 106 PROPVARIANT varName; 107 PropVariantInit(&varName); 108 109 hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName); 110 if (!SUCCEEDED(hr)) 111 { 112 PropVariantClear(&varName); 113 pProps->Release(); 114 pDevice->Release(); 115 continue; 116 } 117 QString name(reinterpret_cast<const QChar*>(varName.pwszVal), 118 wcslen(varName.pwszVal)); 119 PropVariantClear(&varName); 120 121 pProps->Release(); 122 pDevice->Release(); 123 124 result.insert(QString("Endpoint:") + uid, name); 125 } 126 127 pCollection->Release(); 128 pEnumerator->Release(); 129 130 CoUninitialize(); 131 132 return result; 133 } 134 135 VolumeControlEndpoint::VolumeControlEndpoint(QString device) : 136 m_EndpointVolume(NULL) 137 { 138 HRESULT hr = S_OK; 139 IMMDeviceEnumerator* pEnumerator = NULL; 140 IMMDevice* pDevice = NULL; 141 142 CoInitialize(NULL); 143 144 // Get enumerator for audio endpoint devices. 145 hr = CoCreateInstance(CLSID_MMDeviceEnumerator, 146 NULL, CLSCTX_INPROC_SERVER, 147 IID_IMMDeviceEnumerator, 148 (void**)&pEnumerator); 149 if (!SUCCEEDED(hr) || !pEnumerator) 150 return; 151 152 if (device == QString("default")) 153 hr = pEnumerator->GetDefaultAudioEndpoint(eRender, 154 eMultimedia, 155 &pDevice); 156 else 157 hr = pEnumerator->GetDevice((LPCWSTR)device.constData(), &pDevice); 158 159 if (!SUCCEEDED(hr) || !pDevice) 160 { 161 pEnumerator->Release(); 162 return; 163 } 164 165 hr = pDevice->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, 166 NULL, (void**)&m_EndpointVolume); 167 if (!SUCCEEDED(hr) || !m_EndpointVolume) 168 { 169 pDevice->Release(); 170 pEnumerator->Release(); 171 return; 172 } 173 174 pDevice->Release(); 175 pEnumerator->Release(); 176 177 hr = m_EndpointVolume->RegisterControlChangeNotify(this); 178 if (!SUCCEEDED(hr)) 179 return; 180 181 UINT step, count; 182 hr = m_EndpointVolume->GetVolumeStepInfo(&step, &count); 183 if (!SUCCEEDED(hr)) 184 return; 185 186 m_Range = std::min(std::max(1U, count - 1), 100U); 187 188 m_Volume = volume(); 189 m_Mute = mute(); 190 } 191 192 VolumeControlEndpoint::~VolumeControlEndpoint() 193 { 194 if (m_EndpointVolume) 195 { 196 m_EndpointVolume->UnregisterControlChangeNotify(this); 197 m_EndpointVolume->Release(); 198 } 199 200 CoUninitialize(); 201 } 202 203 int VolumeControlEndpoint::volume() const 204 { 205 int volume = 0; 206 207 if (!mute()) 208 { 209 if (m_EndpointVolume) 210 { 211 float level; 212 m_EndpointVolume->GetMasterVolumeLevelScalar(&level); 213 volume = static_cast<int>(round(level * 100.0f)); 214 } 215 } 216 else 217 volume = m_Volume; 218 219 VERBOSE(VB_AUDIO, 220 QString("VolumeControlEndpoint::volume() = %1") 221 .arg(volume)); 222 223 return volume; 224 } 225 226 void VolumeControlEndpoint::setVolume(int volume) 227 { 228 VERBOSE(VB_AUDIO, 229 QString("VolumeControlEndpoint::setVolume(%1)") 230 .arg(volume)); 231 232 volume = std::min(std::max(0, volume), 100); 233 234 if (mute() && volume > VolumeControlEndpoint::volume()) 235 setMute(false); 236 237 if (!mute() && m_EndpointVolume) 238 m_EndpointVolume->SetMasterVolumeLevelScalar( 239 round(static_cast<float>(volume * m_Range) / 100.0f) / 240 static_cast<float>(m_Range), NULL); 241 242 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 243 emit changedVolume(volume); 244 } 245 246 void VolumeControlEndpoint::increaseVolume() 247 { 248 int volume = VolumeControlEndpoint::volume(); 249 float level = (round(static_cast<float>(volume * m_Range) / 100.0f) + 1.0f) 250 / static_cast<float>(m_Range); 251 volume = static_cast<int>(round(level * 100.0f)); 252 setVolume(volume); 253 } 254 255 void VolumeControlEndpoint::decreaseVolume() 256 { 257 int volume = VolumeControlEndpoint::volume(); 258 float level = (round(static_cast<float>(volume * m_Range) / 100.0f) - 1.0f) 259 / static_cast<float>(m_Range); 260 volume = static_cast<int>(round(level * 100.0f)); 261 setVolume(volume); 262 } 263 264 bool VolumeControlEndpoint::mute() const 265 { 266 BOOL mute = FALSE; 267 268 if (m_EndpointVolume) 269 m_EndpointVolume->GetMute(&mute); 270 271 VERBOSE(VB_AUDIO, 272 QString("VolumeControlEndpoint::mute() = %1") 273 .arg(mute ? "mute" : "unmute")); 274 275 return mute; 276 } 277 278 void VolumeControlEndpoint::setMute(bool mute) 279 { 280 VERBOSE(VB_AUDIO, 281 QString("VolumeControlEndpoint::setMute(%1)") 282 .arg(mute ? "mute" : "unmute")); 283 284 if (m_EndpointVolume) 285 { 286 if (VolumeControlEndpoint::mute()) 287 m_EndpointVolume->SetMasterVolumeLevelScalar( 288 static_cast<float>(m_Volume) / 100.0f, NULL); 289 290 m_EndpointVolume->SetMute(mute, NULL); 291 } 292 293 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 294 emit changedMute(mute); 295 } 296 297 ULONG STDMETHODCALLTYPE VolumeControlEndpoint::AddRef() 298 { 299 return 1; 300 } 301 302 ULONG STDMETHODCALLTYPE VolumeControlEndpoint::Release() 303 { 304 return 0; 305 } 306 307 HRESULT STDMETHODCALLTYPE 308 VolumeControlEndpoint::QueryInterface(REFIID riid, VOID **ppvInterface) 309 { 310 if (IID_IUnknown == riid) 311 { 312 AddRef(); 313 *ppvInterface = (IUnknown*)this; 314 } 315 else if (IID_IAudioEndpointVolumeCallback == riid) 316 { 317 AddRef(); 318 *ppvInterface = (IAudioEndpointVolumeCallback*)this; 319 } 320 else 321 { 322 *ppvInterface = NULL; 323 return E_NOINTERFACE; 324 } 325 return S_OK; 326 } 327 328 HRESULT STDMETHODCALLTYPE 329 VolumeControlEndpoint::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) 330 { 331 HRESULT hr = E_INVALIDARG; 332 333 if (pNotify) 334 { 335 int volume = VolumeControlEndpoint::volume(); 336 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 337 emit changedVolume(volume); 338 339 bool mute = VolumeControlEndpoint::mute(); 340 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 341 emit changedMute(mute); 342 343 hr = S_OK; 344 } 345 346 return hr; 347 } -
mythtv/libs/libmyth/audiooutputjack.h
18 18 AudioOutputJACK(const AudioSettings &settings); 19 19 virtual ~AudioOutputJACK(); 20 20 21 // Volume control22 virtual int GetVolumeChannel(int channel) const; // Returns 0-10023 virtual void SetVolumeChannel(int channel, int volume); // range 0-10024 25 21 protected: 26 22 27 23 // You need to implement the following functions … … 37 33 38 34 private: 39 35 40 void VolumeInit(void);41 42 36 // Our various callback functions 43 37 inline int JackCallback(jack_nframes_t nframes); 44 38 static int _JackCallback(jack_nframes_t nframes, void *arg); -
mythtv/libs/libmyth/audiosettings.cpp
15 15 channels(-1), 16 16 codec(0), 17 17 samplerate(-1), 18 set_initial_vol(false),19 18 use_passthru(false), 20 19 source(AUDIOOUTPUT_UNKNOWN), 21 20 upmixer(0) … … 29 28 channels(other.channels), 30 29 codec(other.codec), 31 30 samplerate(other.samplerate), 32 set_initial_vol(other.set_initial_vol),33 31 use_passthru(other.use_passthru), 34 32 source(other.source), 35 33 upmixer(other.upmixer) … … 44 42 int codec, 45 43 int samplerate, 46 44 AudioOutputSource source, 47 bool set_initial_vol,48 45 bool use_passthru, 49 46 int upmixer_startup) : 50 47 main_device(main_device), … … 53 50 channels(channels), 54 51 codec(codec), 55 52 samplerate(samplerate), 56 set_initial_vol(set_initial_vol),57 53 use_passthru(use_passthru), 58 54 source(source), 59 55 upmixer(upmixer_startup) … … 73 69 channels(channels), 74 70 codec(codec), 75 71 samplerate(samplerate), 76 set_initial_vol(false),77 72 use_passthru(use_passthru), 78 73 source(AUDIOOUTPUT_UNKNOWN), 79 74 upmixer(upmixer_startup) -
mythtv/libs/libmyth/audiooutputca.cpp
304 304 return false; 305 305 } 306 306 307 if (internal_vol && set_initial_vol)308 {309 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");310 controlLabel += "MixerVolume";311 SetCurrentVolume(gCoreContext->GetNumSetting(controlLabel, 80));312 }313 314 307 return true; 315 308 } 316 309 … … 416 409 return noErr; 417 410 } 418 411 419 int AudioOutputCA::GetVolumeChannel(int channel) const420 {421 // FIXME: this only returns global volume422 (void)channel;423 Float32 volume;424 425 if (!AudioUnitGetParameter(d->mOutputUnit,426 kHALOutputParam_Volume,427 kAudioUnitScope_Global, 0, &volume))428 return (int)lroundf(volume * 100.0f);429 430 return 0; // error case431 }432 433 void AudioOutputCA::SetVolumeChannel(int channel, int volume)434 {435 // FIXME: this only sets global volume436 (void)channel;437 AudioUnitSetParameter(d->mOutputUnit, kHALOutputParam_Volume,438 kAudioUnitScope_Global, 0, (volume * 0.01f), 0);439 }440 441 412 // IOProc style callback for SPDIF audio output 442 413 static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice, 443 414 const AudioTimeStamp *inNow, -
mythtv/libs/libmyth/audiooutputwin.h
13 13 AudioOutputWin(const AudioSettings &settings); 14 14 virtual ~AudioOutputWin(); 15 15 16 // Volume control17 virtual int GetVolumeChannel(int channel) const;18 virtual void SetVolumeChannel(int channel, int volume);19 20 16 protected: 21 17 virtual bool OpenDevice(void); 22 18 virtual void CloseDevice(void); -
mythtv/libs/libmyth/audiooutputjack.cpp
406 406 407 407 return 0; 408 408 } 409 <<<<<<< .mine 410 ======= 409 411 410 412 411 413 /* Our Jack XRun callback. … … 485 487 chan_volumes[i] = volume; 486 488 } 487 489 488 int AudioOutputJACK::GetVolumeChannel(int channel) const489 {490 unsigned int vol = 0;491 492 if (!internal_vol)493 return 100;494 495 if (channel < JACK_CHANNELS_MAX)496 vol = chan_volumes[channel];497 498 return vol;499 }500 501 void AudioOutputJACK::SetVolumeChannel(int channel, int volume)502 {503 if (internal_vol && (channel < JACK_CHANNELS_MAX))504 {505 chan_volumes[channel] = volume;506 if (channel == 0)507 {508 // Left509 chan_volumes[2] = volume; // left rear510 }511 else if (channel == 1)512 {513 // Right514 chan_volumes[3] = volume; // right rear515 }516 517 // LFE and Center518 chan_volumes[4] = chan_volumes[5] =519 (chan_volumes[0] + chan_volumes[1]) / 2;520 }521 }522 523 524 490 /* We don't need an audio output thread for Jack 525 491 Everything handled by callbacks here 526 492 Therefore we can loose all the Start/StopOutputThread, WriteAudio, etc -
mythtv/libs/libmyth/audiooutputoss.h
12 12 AudioOutputOSS(const AudioSettings &settings); 13 13 virtual ~AudioOutputOSS(); 14 14 15 // Volume control16 virtual int GetVolumeChannel(int channel) const;17 virtual void SetVolumeChannel(int channel, int volume);18 19 15 protected: 20 16 // You need to implement the following functions 21 17 virtual bool OpenDevice(void); … … 25 21 AudioOutputSettings* GetOutputSettings(void); 26 22 27 23 private: 28 void VolumeInit(void);29 void VolumeCleanup(void);30 31 24 void SetFragSize(void); 32 25 33 26 int audiofd; 34 27 mutable int numbadioctls; 35 36 // Volume related37 int mixerfd;38 int control;39 28 }; 40 29 41 30 #endif -
mythtv/libs/libmyth/audiooutputbase.cpp
62 62 pauseaudio(false), actually_paused(false), 63 63 was_paused(false), unpause_when_ready(false), 64 64 65 set_initial_vol(settings.set_initial_vol),66 65 buffer_output_data_for_use(false), 67 66 68 67 // private … … 76 75 source_bytes_per_frame(0), 77 76 needs_upmix(false), needs_downmix(false), 78 77 surround_mode(QUALITY_LOW), old_stretchfactor(1.0f), 79 volume (80), volumeControl(NULL),78 volumeControl(NULL), 80 79 81 80 processing(false), 82 81 … … 122 121 AudioOutput::AudioSetup(max_channels, allow_ac3_passthru, 123 122 ignore, allow_multipcm, upmix_default); 124 123 124 if (gCoreContext->GetSetting("MixerDevice") == "Software:") 125 volume_control = VolumeControlManager::GetControl("Software:"); 126 125 127 if (settings.upmixer == 0) // Use general settings (video) 126 128 configured_channels = upmix_default ? max_channels : 2; 127 129 else if (settings.upmixer == 1) // music, upmixer off … … 325 327 326 328 killaudio = pauseaudio = false; 327 329 was_paused = true; 328 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);329 330 330 331 // Ask the subclass what we can send to the device 331 332 if (!output_settings) … … 405 406 406 407 // Turn on float conversion? 407 408 if (need_resampler || needs_upmix || needs_downmix || 408 stretchfactor != 1.0f || ( internal_vol && SWVolume()) ||409 stretchfactor != 1.0f || (volume_control) || 409 410 (enc && output_format != FORMAT_S16) || 410 411 !output_settings->IsSupportedFormat(output_format)) 411 412 { … … 444 445 return; 445 446 } 446 447 447 // Only used for software volume448 if (set_initial_vol && internal_vol && SWVolume())449 {450 VBAUDIO("Software volume enabled");451 volumeControl = gCoreContext->GetSetting("MixerControl", "PCM");452 volumeControl += "MixerVolume";453 volume = gCoreContext->GetNumSetting(volumeControl, 80);454 }455 456 VolumeBase::SetChannels(channels);457 VolumeBase::SyncVolume();458 VolumeBase::UpdateVolume();459 460 448 VBAUDIO(QString("Audio fragment size: %1").arg(fragment_size)); 461 449 462 450 audbuf_timecode = audiotime = frames_buffered = 0; … … 733 721 } 734 722 735 723 /** 736 * Set the volume for software volume control737 */738 void AudioOutputBase::SetSWVolume(int new_volume, bool save)739 {740 volume = new_volume;741 if (save && volumeControl != NULL)742 gCoreContext->SaveSetting(volumeControl, volume);743 }744 745 /**746 * Get the volume for software volume control747 */748 int AudioOutputBase::GetSWVolume()749 {750 return volume;751 }752 753 /**754 724 * Check that there's enough space in the audiobuffer to write the provided 755 725 * number of frames 756 726 * … … 998 968 org_waud += nFrames * bpf; 999 969 } 1000 970 1001 if ( internal_vol && SWVolume())971 if (volume_control) 1002 972 { 1003 973 org_waud = waud; 1004 974 int num = len; 975 int volume = volume_control->volume(); 1005 976 1006 977 if (bdiff <= num) 1007 978 { … … 1214 1185 raud += frag_size; 1215 1186 1216 1187 // Mute individual channels through mono->stereo duplication 1217 MuteState mute_state = GetMuteState(); 1218 if (written_size && channels > 1 && 1219 (mute_state == kMuteLeft || mute_state == kMuteRight)) 1188 bool mute = volume_control ? volume_control->mute() : false; 1189 if (written_size && channels > 1 && mute) 1220 1190 { 1221 AudioOutputUtil::MuteChannel(obytes << 3, channels, 1222 mute_state == kMuteLeft ? 0 : 1, 1191 AudioOutputUtil::MuteChannel(obytes << 3, channels, 1, 1223 1192 buffer, written_size); 1224 1193 } 1225 1194 -
mythtv/libs/libmyth/audiooutput.cpp
31 31 AudioOutput *AudioOutput::OpenAudio( 32 32 const QString &main_device, const QString &passthru_device, 33 33 AudioFormat format, int channels, int codec, int samplerate, 34 AudioOutputSource source, bool set_initial_vol, bool passthru, 35 int upmixer_startup) 34 AudioOutputSource source, bool passthru, int upmixer_startup) 36 35 { 37 36 AudioSettings settings( 38 37 main_device, passthru_device, format, channels, codec, samplerate, 39 source, set_initial_vol,passthru, upmixer_startup);38 source, passthru, upmixer_startup); 40 39 41 40 settings.FixPassThrough(); 42 41 -
mythtv/libs/libmyth/libmyth.pro
24 24 HEADERS += output.h 25 25 HEADERS += settings.h 26 26 HEADERS += uilistbtntype.h uitypes.h util.h mythuifilebrowser.h 27 HEADERS += volumebase.h visual.h xmlparse.h 27 HEADERS += volumecontrol.h volumecontrolmanager.h volumecontrolsoftware.h 28 HEADERS += visual.h xmlparse.h 28 29 HEADERS += mythhdd.h mythcdrom.h storagegroup.h dbutil.h 29 30 HEADERS += mythcommandlineparser.h mythterminal.h 30 31 HEADERS += mythhttppool.h mythhttphandler.h … … 51 52 SOURCES += output.cpp 52 53 SOURCES += settings.cpp 53 54 SOURCES += uilistbtntype.cpp uitypes.cpp util.cpp mythuifilebrowser.cpp 54 SOURCES += volumebase.cpp xmlparse.cpp 55 SOURCES += volumecontrolmanager.cpp volumecontrolsoftware.cpp 56 SOURCES += xmlparse.cpp 55 57 SOURCES += mythhdd.cpp mythcdrom.cpp storagegroup.cpp dbutil.cpp 56 58 SOURCES += mythcommandlineparser.cpp mythterminal.cpp 57 59 SOURCES += mythhttppool.cpp mythhttphandler.cpp … … 93 95 # Install headers so that plugins can compile independently 94 96 inc.path = $${PREFIX}/include/mythtv/ 95 97 inc.files = dialogbox.h mythcontext.h 96 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h98 inc.files += mythwidgets.h remotefile.h oldsettings.h 97 99 inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h 98 100 inc.files += audiooutput.h audiosettings.h audiooutputsettings.h util.h 99 101 inc.files += inetcomms.h mythmedia.h mythcdrom.h mythwizard.h schemawizard.h dbutil.h 100 102 inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h 101 inc.files += visual.h volume base.h output.h langsettings.h103 inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h 102 104 inc.files += mythexp.h mythpluginapi.h storagegroup.h 103 105 inc.files += mythconfigdialogs.h mythconfiggroups.h 104 106 inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h … … 117 119 118 120 using_oss { 119 121 DEFINES += USING_OSS 120 SOURCES += audiooutputoss.cpp 121 HEADERS += audiooutputoss.h 122 SOURCES += audiooutputoss.cpp volumecontroloss.cpp 123 HEADERS += audiooutputoss.h volumecontroloss.h 122 124 LIBS += $$OSS_LIBS 123 125 } 124 126 … … 146 148 147 149 mingw { 148 150 DEFINES += USING_MINGW 149 SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp 150 HEADERS += mediamonitor-windows.h audiooutputwin.h audiooutputdx.h 151 LIBS += -lpthread -lwinmm -lws2_32 151 SOURCES += mediamonitor-windows.cpp 152 HEADERS += mediamonitor-windows.h 153 SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp 154 HEADERS += audiooutputwin.h audiooutputdx.h volumecontrolendpoint.h 155 LIBS += -lpthread -lwinmm -lws2_32 -lole32 152 156 } 153 157 154 158 macx { 155 HEADERS += audiooutputca.h 156 SOURCES += audiooutputca.cpp 159 DEFINES += USE_COREAUDIO 160 HEADERS += audiooutputca.h volumecontrolcoreaudio.h 161 SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp 157 162 HEADERS += mythcdrom-darwin.h 158 163 SOURCES += mythcdrom-darwin.cpp 159 164 … … 193 198 194 199 using_alsa { 195 200 DEFINES += USE_ALSA 196 HEADERS += audiooutputalsa.h 197 SOURCES += audiooutputalsa.cpp 201 HEADERS += audiooutputalsa.h volumecontrolalsa.h 202 SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp 198 203 LIBS += $$ALSA_LIBS 199 204 } 200 205 -
mythtv/libs/libmyth/audiosettings.h
33 33 int codec, 34 34 int samplerate, 35 35 AudioOutputSource source, 36 bool set_initial_vol,37 36 bool use_passthru, 38 37 int upmixer_startup = 0); 39 38 … … 59 58 int channels; 60 59 int codec; 61 60 int samplerate; 62 bool set_initial_vol;63 61 bool use_passthru; 64 62 AudioOutputSource source; 65 63 int upmixer; -
mythtv/libs/libmyth/audiooutputca.h
26 26 bool RenderAudio(unsigned char *aubuf, int size, 27 27 unsigned long long timestamp); 28 28 29 // Volume control30 virtual int GetVolumeChannel(int channel) const;31 virtual void SetVolumeChannel(int channel, int volume);32 33 29 void Debug(QString msg) 34 30 { VERBOSE(VB_AUDIO, "AudioOutputCA::" + msg); } 35 31 … … 38 34 39 35 void Warn(QString msg) 40 36 { VERBOSE(VB_IMPORTANT, "AudioOutputCA Warning: " + msg); } 37 bool internal_vol; 41 38 42 39 protected: 43 40 -
mythtv/libs/libmyth/audiooutputoss.cpp
32 32 33 33 AudioOutputOSS::AudioOutputOSS(const AudioSettings &settings) : 34 34 AudioOutputBase(settings), 35 audiofd(-1), numbadioctls(0), 36 mixerfd(-1), control(SOUND_MIXER_VOLUME) 35 audiofd(-1), numbadioctls(0) 37 36 { 38 37 // Set everything up 39 38 Reconfigure(settings); … … 202 201 else 203 202 OERROR("Unable to get audio card capabilities"); 204 203 205 // Setup volume control206 if (internal_vol)207 VolumeInit();208 209 204 // Device opened successfully 210 205 return true; 211 206 } … … 216 211 close(audiofd); 217 212 218 213 audiofd = -1; 219 220 VolumeCleanup();221 214 } 222 215 223 216 … … 257 250 return soundcard_buffer; 258 251 } 259 252 260 void AudioOutputOSS::VolumeInit()261 {262 mixerfd = -1;263 int volume = 0;264 265 QString device = gCoreContext->GetSetting("MixerDevice", "/dev/mixer");266 if (device.toLower() == "software")267 return;268 269 QByteArray dev = device.toAscii();270 mixerfd = open(dev.constData(), O_RDONLY);271 272 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");273 274 if (controlLabel == "Master")275 control = SOUND_MIXER_VOLUME;276 else277 control = SOUND_MIXER_PCM;278 279 if (mixerfd < 0)280 {281 VBERROR(QString("Unable to open mixer: '%1'").arg(device));282 return;283 }284 285 if (set_initial_vol)286 {287 int tmpVol;288 volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);289 tmpVol = (volume << 8) + volume;290 int ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);291 if (ret < 0)292 VBERROR(QString("Error Setting initial Master Volume") + ENO);293 294 volume = gCoreContext->GetNumSetting("PCMMixerVolume", 80);295 tmpVol = (volume << 8) + volume;296 ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);297 if (ret < 0)298 VBERROR(QString("Error setting initial PCM Volume") + ENO);299 }300 }301 302 void AudioOutputOSS::VolumeCleanup()303 {304 if (mixerfd >= 0)305 {306 close(mixerfd);307 mixerfd = -1;308 }309 }310 311 int AudioOutputOSS::GetVolumeChannel(int channel) const312 {313 int volume=0;314 int tmpVol=0;315 316 if (mixerfd <= 0)317 return 100;318 319 int ret = ioctl(mixerfd, MIXER_READ(control), &tmpVol);320 if (ret < 0)321 {322 VBERROR(QString("Error reading volume for channel %1").arg(channel));323 return 0;324 }325 326 if (channel == 0)327 volume = tmpVol & 0xff; // left328 else if (channel == 1)329 volume = (tmpVol >> 8) & 0xff; // right330 else331 VBERROR("Invalid channel. Only stereo volume supported");332 333 return volume;334 }335 336 void AudioOutputOSS::SetVolumeChannel(int channel, int volume)337 {338 if (channel > 1)339 {340 // Don't support more than two channels!341 VBERROR(QString("Error setting channel %1. Only 2 ch volume supported")342 .arg(channel));343 return;344 }345 346 if (volume > 100)347 volume = 100;348 if (volume < 0)349 volume = 0;350 351 if (mixerfd >= 0)352 {353 int tmpVol = 0;354 if (channel == 0)355 tmpVol = (GetVolumeChannel(1) << 8) + volume;356 else357 tmpVol = (volume << 8) + GetVolumeChannel(0);358 359 int ret = ioctl(mixerfd, MIXER_WRITE(control), &tmpVol);360 if (ret < 0)361 VBERROR(QString("Error setting volume on channel %1").arg(channel));362 }363 }364 -
mythtv/libs/libmyth/audiooutputdx.cpp
476 476 | DSBCAPS_GLOBALFOCUS // Allows background playing 477 477 | DSBCAPS_LOCHARDWARE; // Needed for 5.1 on emu101k 478 478 479 if (!m_UseSPDIF)480 dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME; // Allow volume control481 482 479 dsbdesc.dwBufferBytes = soundcard_buffer_size; // buffer size 483 480 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf; 484 481 … … 549 546 return buffered; 550 547 } 551 548 552 int AudioOutputDX::GetVolumeChannel(int channel) const553 {554 HRESULT dsresult;555 long dxVolume = 0;556 int volume;557 558 if (m_UseSPDIF)559 return 100;560 561 dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);562 volume = (int)(pow(10,(float)dxVolume/20)*100);563 564 if (dsresult != DS_OK)565 {566 VBERROR(QString("Failed to get volume %1").arg(dxVolume));567 return volume;568 }569 570 VBAUDIO(QString("Got volume %1").arg(volume));571 return volume;572 }573 574 void AudioOutputDX::SetVolumeChannel(int channel, int volume)575 {576 HRESULT dsresult;577 float dbAtten = 20 * log10((float)volume/100);578 long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);579 580 if (m_UseSPDIF)581 return;582 583 // dxVolume is attenuation in 100ths of a decibel584 dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);585 586 if (dsresult != DS_OK)587 {588 VBERROR(QString("Failed to set volume %1").arg(dxVolume));589 return;590 }591 592 VBAUDIO(QString("Set volume %1").arg(dxVolume));593 }594 595 549 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
mythtv/libs/libmyth/audiooutputnull.h
27 27 28 28 virtual void Reset(void); 29 29 30 31 // Volume control32 virtual int GetVolumeChannel(int /* channel */) const { return 100; }33 virtual void SetVolumeChannel(int /* channel */, int /* volume */){return;}34 35 30 virtual int readOutputData(unsigned char *read_buffer, int max_length); 36 31 37 32 protected: -
mythtv/libs/libmyth/audiooutput.h
5 5 6 6 #include "audiosettings.h" 7 7 #include "mythcorecontext.h" 8 #include "volumebase.h"9 8 #include "output.h" 10 9 11 class MPUBLIC AudioOutput : public VolumeBase, publicOutputListeners10 class MPUBLIC AudioOutput : public OutputListeners 12 11 { 13 12 public: 14 13 static void AudioSetup(int &max_channels, bool &allow_ac3_passthru, … … 19 18 static AudioOutput *OpenAudio( 20 19 const QString &audiodevice, const QString &passthrudevice, 21 20 AudioFormat format, int channels, int codec, int samplerate, 22 AudioOutputSource source, bool set_initial_vol, bool passthru, 23 int upmixer_startup = 0); 21 AudioOutputSource source, bool passthru, int upmixer_startup = 0); 24 22 25 23 AudioOutput() : 26 VolumeBase(),OutputListeners(),24 OutputListeners(), 27 25 lastError(QString::null), lastWarn(QString::null) {} 28 26 29 27 virtual ~AudioOutput() { }; -
mythtv/libs/libmyth/volumecontrolmanager.h
1 #ifndef VOLUMECONTROLMANAGER 2 #define VOLUMECONTROLMANAGER 3 4 #include "volumecontrol.h" 5 6 #include "mythexp.h" 7 8 #include <QHash> 9 #include <QSharedPointer> 10 #include <QString> 11 12 class MPUBLIC VolumeControlManager 13 { 14 public: 15 static QHash<QString, QString> Enumerate(); 16 static QSharedPointer<VolumeControl> GetControl(QString device); 17 }; 18 19 #endif // VOLUMECONTROLMANAGER -
mythtv/libs/libmyth/volumecontrolendpoint.h
1 #ifndef VOLUMECONTROLENDPOINT 2 #define VOLUMECONTROLENDPOINT 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QAtomicInt> 8 9 #include <rpcsal.h> 10 #include <endpointvolume.h> 11 12 13 class VolumeControlEndpoint : public VolumeControl, 14 protected IAudioEndpointVolumeCallback 15 { 16 public: 17 static QHash<QString, QString> Enumerate(); 18 19 public: 20 VolumeControlEndpoint(QString device); 21 virtual ~VolumeControlEndpoint(); 22 23 public: 24 int volume() const; 25 void setVolume(int volume); 26 void increaseVolume(); 27 void decreaseVolume(); 28 29 bool mute() const; 30 void setMute(bool mute); 31 32 protected: 33 ULONG STDMETHODCALLTYPE AddRef(); 34 ULONG STDMETHODCALLTYPE Release(); 35 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface); 36 HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify); 37 38 private: 39 IAudioEndpointVolume* m_EndpointVolume; //< Endpoint volume interface 40 int m_Range; //< Range of mixer element 41 QAtomicInt m_Volume; //< Volume state cache 42 QAtomicInt m_Mute; //< Mute state cache 43 }; 44 45 #endif // VOLUMECONTROLWINDOWSENDPOINT -
mythtv/libs/libmyth/audiooutputdx.h
14 14 AudioOutputDX(const AudioSettings &settings); 15 15 virtual ~AudioOutputDX(); 16 16 17 virtual int GetVolumeChannel(int channel) const;18 virtual void SetVolumeChannel(int channel, int volume);19 20 17 protected: 21 18 virtual bool OpenDevice(void); 22 19 virtual void CloseDevice(void); -
mythtv/libs/libmyth/audiooutputalsa.h
17 17 AudioOutputALSA(const AudioSettings &settings); 18 18 virtual ~AudioOutputALSA(); 19 19 20 // Volume control21 virtual int GetVolumeChannel(int channel) const; // Returns 0-10022 virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol23 20 static QMap<QString, QString> *GetALSADevices(const char *type); 24 21 25 22 protected: … … 38 35 inline int SetParameters(snd_pcm_t *handle, snd_pcm_format_t format, 39 36 uint channels, uint rate, uint buffer_time, 40 37 uint period_time); 41 // Volume related42 bool OpenMixer(void);43 38 44 39 private: 45 40 snd_pcm_t *pcm_handle; … … 49 44 QMutex killAudioLock; 50 45 snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*, 51 46 snd_pcm_uframes_t); 52 struct {53 QString device;54 QString control;55 snd_mixer_t* handle;56 snd_mixer_elem_t* elem;57 long volmin;58 long volmax;59 long volrange;60 } m_mixer;61 62 47 }; 63 48 #endif -
mythtv/libs/libmyth/volumecontroloss.cpp
1 #include "volumecontroloss.h" 2 3 #include "mythverbose.h" 4 #include <algorithm> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <sys/ioctl.h> 8 #include <fcntl.h> 9 10 #include <QDir> 11 12 #include "mythconfig.h" 13 #ifdef HAVE_SYS_SOUNDCARD_H 14 #include <sys/soundcard.h> 15 #elif HAVE_SOUNDCARD_H 16 #include <soundcard.h> 17 #endif 18 19 static const unsigned long poll = 250; //< OSS control poll interval (ms) 20 21 // static 22 QHash<QString, QString> VolumeControlOSS::Enumerate() 23 { 24 QHash<QString, QString> result; 25 #if 1 26 int mixerfd = open("/dev/mixer", O_RDWR, 0); 27 28 if (mixerfd == -1) 29 { 30 VERBOSE(VB_IMPORTANT, 31 QString("VolumeControlOSS::Enumerate() - ERROR: " 32 "opening \"/dev/mixer\"")); 33 return result; 34 } 35 36 oss_sysinfo sysinfo; 37 if (ioctl(mixerfd, SNDCTL_SYSINFO, &sysinfo) == -1) 38 { 39 VERBOSE(VB_IMPORTANT, 40 QString("VolumeControlOSS::Enumerate() - ERROR: " 41 "obtaining system information")); 42 return result; 43 } 44 45 for (int mixer = 0; mixer < sysinfo.nummixers; ++mixer) 46 { 47 oss_mixerinfo info = { 48 dev: mixer 49 }; 50 51 if (ioctl(mixerfd, SNDCTL_MIXERINFO, &info) != -1) 52 result.insert(QString("OSS:%1").arg(info.devnode), info.name); 53 } 54 55 close(mixerfd); 56 57 #else 58 QDir devs("/dev", "mixer*", QDir::Name, QDir::System); 59 60 QFileInfoList files = devs.entryInfoList(); 61 QFileInfoList::Iterator file; 62 for (file = files.begin(); file != files.end(); ++file) 63 { 64 result.insert("OSS:" + file->absoluteFilePath(), 65 file->absoluteFilePath()); 66 } 67 68 devs.setPath("/dev/sound"); 69 files = devs.entryInfoList(); 70 for (file = files.begin(); file != files.end(); ++file) 71 { 72 result.insert("OSS:" + file->absoluteFilePath(), 73 file->absoluteFilePath()); 74 } 75 #endif 76 return result; 77 } 78 79 VolumeControlOSS::VolumeControlOSS(QString device) : 80 m_VolumeCtrl(-1), m_MuteCtrl(-1), m_Exit(false) 81 { 82 m_Mixer = open(device.toAscii().constData(), O_RDWR, 0); 83 84 if (m_Mixer == -1) 85 { 86 VERBOSE(VB_IMPORTANT, 87 QString("VolumeControlOSS::VolumeControlOSS() - ERROR: " 88 "opening \"%1\"").arg(device)); 89 return; 90 } 91 92 oss_sysinfo sysinfo; 93 if (ioctl(m_Mixer, SNDCTL_SYSINFO, &sysinfo) == -1) 94 { 95 VERBOSE(VB_IMPORTANT, 96 QString("VolumeControlOSS::VolumeControlOSS() - ERROR: " 97 "obtaining system information")); 98 return; 99 } 100 101 for (m_MixerDev = 0; m_MixerDev < sysinfo.nummixers; ++m_MixerDev) 102 { 103 oss_mixerinfo info = { 104 dev: m_MixerDev 105 }; 106 107 if (ioctl(m_Mixer, SNDCTL_MIXERINFO, &info) != -1) 108 if (QString(info.devnode) == device) 109 break; 110 } 111 112 int extensions = m_MixerDev; 113 if (ioctl(m_Mixer, SNDCTL_MIX_NREXT, &extensions) == -1) 114 { 115 VERBOSE(VB_IMPORTANT, 116 QString("VolumeControlOSS::VolumeControlOSS() - ERROR: " 117 "obtaining number of extensions")); 118 return; 119 } 120 121 for (int control = 0; control < extensions; ++control) 122 { 123 oss_mixext info = { 124 dev: m_MixerDev, 125 ctrl: control 126 }; 127 128 if (ioctl(m_Mixer, SNDCTL_MIX_EXTINFO, &info) == -1) 129 continue; 130 131 switch (info.type) 132 { 133 case MIXT_MONODB: 134 case MIXT_MONOSLIDER: 135 case MIXT_MONOSLIDER16: 136 case MIXT_SLIDER: 137 case MIXT_STEREOSLIDER: 138 case MIXT_STEREOSLIDER16: 139 if (m_VolumeCtrl == -1) 140 { 141 m_VolumeCtrl = info.ctrl; 142 m_VolumeMax = info.maxvalue; 143 m_VolumeType = info.type; 144 m_VolumeTimestamp = info.timestamp; 145 } 146 break; 147 148 case MIXT_ONOFF: 149 case MIXT_MUTE: 150 if (m_MuteCtrl == -1) 151 { 152 m_MuteCtrl = info.ctrl; 153 m_MuteTimestamp = info.timestamp; 154 } 155 break; 156 } 157 158 if (m_VolumeCtrl != -1 && m_MuteCtrl != -1) 159 break; 160 } 161 162 m_Range = std::min(std::max(1, m_VolumeMax), 100); 163 164 if (m_VolumeCtrl != -1) 165 start(); 166 } 167 168 VolumeControlOSS::~VolumeControlOSS() 169 { 170 m_Exit = true; 171 172 if (isRunning()) 173 wait(); 174 175 if (m_Mixer != -1) 176 close(m_Mixer); 177 } 178 179 int VolumeControlOSS::volume() const 180 { 181 int volume = 0; 182 183 if (m_VolumeCtrl != -1) 184 { 185 if (m_MuteCtrl != -1 || !mute()) 186 { 187 oss_mixer_value value; 188 memset(&value, 0, sizeof(value)); 189 190 value.dev = m_MixerDev; 191 value.ctrl = m_VolumeCtrl; 192 value.timestamp = m_VolumeTimestamp; 193 194 if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1) 195 { 196 switch (m_VolumeType) 197 { 198 case MIXT_MONODB: 199 case MIXT_MONOSLIDER: 200 volume = value.value & 0xFF; 201 break; 202 203 case MIXT_MONOSLIDER16: 204 volume = value.value & 0xFFFF; 205 break; 206 207 case MIXT_SLIDER: 208 volume = value.value & 0x7FFFFFFF; 209 break; 210 211 case MIXT_STEREOSLIDER: 212 volume = std::max(value.value & 0xFF, 213 (value.value >> 8) & 0xFF); 214 break; 215 216 case MIXT_STEREOSLIDER16: 217 volume = std::max(value.value & 0xFFFF, 218 (value.value >> 16) & 0xFFFF); 219 break; 220 } 221 222 volume = ((200 * volume) + m_VolumeMax) / (2 * m_VolumeMax); 223 } 224 } 225 else 226 volume = m_Volume; 227 } 228 229 VERBOSE(VB_AUDIO, 230 QString("VolumeControlOSS::volume() = %1") 231 .arg(volume)); 232 233 return volume; 234 } 235 236 void VolumeControlOSS::setVolume(int volume) 237 { 238 VERBOSE(VB_AUDIO, 239 QString("VolumeControlOSS::setVolume(%1)") 240 .arg(volume)); 241 242 volume = std::min(std::max(0, volume), 100); 243 244 if (mute() && volume > VolumeControlOSS::volume()) 245 setMute(false); 246 247 if (m_VolumeCtrl != -1 && (m_MuteCtrl != -1 || !mute())) 248 { 249 oss_mixer_value value; 250 memset(&value, 0, sizeof(value)); 251 252 value.dev = m_MixerDev; 253 value.ctrl = m_VolumeCtrl; 254 value.timestamp = m_VolumeTimestamp; 255 value.value = (m_VolumeMax * volume) / 100; 256 257 switch (m_VolumeType) 258 { 259 case MIXT_STEREOSLIDER: 260 value.value = value.value | (value.value << 8); 261 break; 262 263 case MIXT_STEREOSLIDER16: 264 value.value = value.value | (value.value << 16); 265 break; 266 } 267 268 ioctl(m_Mixer, SNDCTL_MIX_WRITE, &value); 269 } 270 271 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 272 emit changedVolume(volume); 273 } 274 275 void VolumeControlOSS::increaseVolume() 276 { 277 setVolume((volume() * m_Range + 100) / m_Range); 278 } 279 280 void VolumeControlOSS::decreaseVolume() 281 { 282 setVolume((volume() * m_Range - 100) / m_Range); 283 } 284 285 bool VolumeControlOSS::mute() const 286 { 287 bool mute = false; 288 289 if (m_VolumeCtrl != -1) 290 { 291 oss_mixer_value value; 292 memset(&value, 0, sizeof(value)); 293 294 value.dev = m_MixerDev; 295 296 if (m_MuteCtrl != -1) 297 { 298 value.ctrl = m_MuteCtrl; 299 value.timestamp = m_MuteTimestamp; 300 301 if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1) 302 mute = value.value; 303 } 304 else 305 { 306 value.ctrl = m_VolumeCtrl; 307 value.timestamp = m_VolumeTimestamp; 308 309 if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1) 310 mute = !value.value; 311 } 312 } 313 314 VERBOSE(VB_AUDIO, 315 QString("VolumeControlOSS::mute() = %1") 316 .arg(mute ? "mute" : "unmute")); 317 318 return mute; 319 } 320 321 void VolumeControlOSS::setMute(bool mute) 322 { 323 VERBOSE(VB_AUDIO, 324 QString("VolumeControlOSS::setMute(%1)") 325 .arg(mute ? "mute" : "unmute")); 326 327 if (m_VolumeCtrl != -1) 328 { 329 oss_mixer_value value; 330 memset(&value, 0, sizeof(value)); 331 332 value.dev = m_MixerDev; 333 334 if (m_MuteCtrl != -1) 335 { 336 value.ctrl = m_MuteCtrl; 337 value.timestamp = m_MuteTimestamp; 338 value.value = mute; 339 } 340 else 341 { 342 value.ctrl = m_VolumeCtrl; 343 value.timestamp = m_VolumeTimestamp; 344 value.value = mute ? 0 : (m_VolumeMax * m_Volume) / 100; 345 346 switch (m_VolumeType) 347 { 348 case MIXT_STEREOSLIDER: 349 value.value = value.value | (value.value << 8); 350 break; 351 352 case MIXT_STEREOSLIDER16: 353 value.value = value.value | (value.value << 16); 354 break; 355 } 356 } 357 358 ioctl(m_Mixer, SNDCTL_MIX_WRITE, &value); 359 } 360 361 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 362 emit changedMute(mute); 363 } 364 365 void VolumeControlOSS::run() 366 { 367 VERBOSE(VB_AUDIO, 368 QString("VolumeControlOSS::run() - begin")); 369 370 m_Volume = volume(); 371 m_Mute = mute(); 372 373 while(!m_Exit) 374 { 375 msleep(poll); 376 377 int pollvolume = volume(); 378 if (m_Volume.fetchAndStoreRelaxed(pollvolume) != pollvolume) 379 emit changedVolume(pollvolume); 380 381 bool pollmute = mute(); 382 if (m_Mute.fetchAndStoreRelaxed(pollmute) != pollmute) 383 emit changedMute(pollmute); 384 } 385 386 VERBOSE(VB_AUDIO, 387 QString("VolumeControlOSS::run() - end")); 388 } 389 -
mythtv/programs/mythfrontend/globalsettings.cpp
32 32 #include "iso639.h" 33 33 #include "playbackbox.h" 34 34 #include "globalsettings.h" 35 #include "libmyth/volumecontrolmanager.h" 35 36 #include "recordingprofile.h" 36 37 #include "mythxdisplay.h" 37 38 #include "DisplayRes.h" … … 207 208 return gc; 208 209 } 209 210 210 static HostCheckBox *MythControlsVolume()211 {212 HostCheckBox *gc = new HostCheckBox("MythControlsVolume");213 gc->setLabel(QObject::tr("Use internal volume controls"));214 gc->setValue(true);215 gc->setHelpText(QObject::tr("MythTV can control the PCM and master "216 "mixer volume. If you prefer to control the volume externally "217 "(like your amplifier) or use an external mixer "218 "program, disable this option."));219 return gc;220 }221 222 211 static HostComboBox *MixerDevice() 223 212 { 224 213 HostComboBox *gc = new HostComboBox("MixerDevice", true); 225 214 gc->setLabel(QObject::tr("Mixer Device")); 215 gc->addSelection(QObject::tr("Disabled"), QString()); 226 216 227 #ifdef USING_OSS 228 QDir dev("/dev", "mixer*", QDir::Name, QDir::System); 229 gc->fillSelectionsFromDir(dev); 217 QHash<QString, QString> controls = VolumeControlManager::Enumerate(); 230 218 231 dev.setPath("/dev/sound");232 if (dev.exists())219 for (QHash<QString, QString>::const_iterator control = controls.begin(); 220 control != controls.end(); ++control) 233 221 { 234 gc-> fillSelectionsFromDir(dev);222 gc->addSelection(control.value(), control.key()); 235 223 } 236 #endif237 #ifdef USING_ALSA238 gc->addSelection("ALSA:default", "ALSA:default");239 #endif240 #ifdef USING_MINGW241 gc->addSelection("DirectX:", "DirectX:");242 gc->addSelection("Windows:", "Windows:");243 #endif244 #if !defined(USING_MINGW)245 gc->addSelection("software", "software");246 gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" lets MythTV control "247 "the volume of all audio at the expense of a slight quality loss."));248 #endif249 224 250 225 return gc; 251 226 } 252 227 253 static const char* MixerControlControls[] = { "PCM",254 "Master" };255 256 static HostComboBox *MixerControl()257 {258 HostComboBox *gc = new HostComboBox("MixerControl", true);259 gc->setLabel(QObject::tr("Mixer Controls"));260 for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);261 ++i)262 {263 gc->addSelection(QObject::tr(MixerControlControls[i]),264 MixerControlControls[i]);265 }266 267 gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));268 return gc;269 }270 271 static HostSlider *MixerVolume()272 {273 HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);274 gs->setLabel(QObject::tr("Master Mixer Volume"));275 gs->setValue(70);276 gs->setHelpText(QObject::tr("Initial volume for the Master Mixer. "277 "This affects all sound created by the sound card. "278 "Note: Do not set this too low."));279 return gs;280 }281 282 static HostSlider *PCMVolume()283 {284 HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);285 gs->setLabel(QObject::tr("PCM Mixer Volume"));286 gs->setValue(70);287 gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "288 "volume keys in MythTV will adjust this parameter."));289 return gs;290 }291 292 228 static HostCheckBox *AC3PassThrough() 293 229 { 294 230 HostCheckBox *gc = new HostCheckBox("AC3PassThru"); … … 3495 3431 group2->addChild(settings4); 3496 3432 3497 3433 return vcg; 3498 3499 3434 } 3500 3435 3501 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup 3436 static ConfigurationGroup *AudioMixerSettingsGroup() 3502 3437 { 3503 public: 3504 AudioMixerSettingsGroup() : 3505 TriggeredConfigurationGroup(false, true, false, false) 3506 { 3507 setLabel(QObject::tr("Audio Mixer")); 3508 setUseLabel(false); 3438 ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false); 3439 3440 vcg->setLabel(QObject::tr("Audio Mixer")); 3441 vcg->setUseLabel(false); 3509 3442 3510 Setting *volumeControl = MythControlsVolume(); 3511 addChild(volumeControl); 3443 vcg->addChild(MixerDevice()); 3512 3444 3513 // Mixer settings 3514 ConfigurationGroup *settings = 3515 new VerticalConfigurationGroup(false, true, false, false); 3516 settings->addChild(MixerDevice()); 3517 settings->addChild(MixerControl()); 3518 settings->addChild(MixerVolume()); 3519 settings->addChild(PCMVolume()); 3445 return vcg; 3446 } 3520 3447 3521 ConfigurationGroup *dummy =3522 new VerticalConfigurationGroup(false, true, false, false);3523 3524 // Show Mixer config only if internal volume controls enabled3525 setTrigger(volumeControl);3526 addTarget("0", dummy);3527 addTarget("1", settings);3528 }3529 };3530 3531 3448 static HostComboBox *MythLanguage() 3532 3449 { 3533 3450 HostComboBox *gc = new HostComboBox("Language"); … … 4211 4128 4212 4129 addChild(AudioSystemSettingsGroup()); 4213 4130 4214 addChild( newAudioMixerSettingsGroup());4131 addChild(AudioMixerSettingsGroup()); 4215 4132 4216 4133 VerticalConfigurationGroup *general = 4217 4134 new VerticalConfigurationGroup(false, true, false, false); -
mythtv/programs/mythtranscode/transcode.cpp
137 137 return last_audiotime; 138 138 } 139 139 140 virtual int GetVolumeChannel(int) const141 {142 // Do nothing143 return 100;144 }145 virtual void SetVolumeChannel(int, int)146 {147 // Do nothing148 }149 virtual void SetVolumeAll(int)150 {151 // Do nothing152 }153 virtual uint GetCurrentVolume(void) const154 {155 // Do nothing156 return 100;157 }158 virtual void SetCurrentVolume(int)159 {160 // Do nothing161 }162 virtual void AdjustCurrentVolume(int)163 {164 // Do nothing165 }166 virtual void SetMute(bool)167 {168 // Do nothing169 }170 virtual void ToggleMute(void)171 {172 // Do nothing173 }174 virtual MuteState GetMuteState(void) const175 {176 // Do nothing177 return kMuteOff;178 }179 virtual MuteState IterateMutedChannels(void)180 {181 // Do nothing182 return kMuteOff;183 }184 140 virtual bool ToggleUpmix(void) 185 141 { 186 142 // Do nothing 187 143 return false; 188 144 } 189 145 190 virtual void SetSWVolume(int new_volume, bool save)191 {192 // Do nothing193 return;194 }195 virtual int GetSWVolume(void)196 {197 // Do nothing198 return 100;199 }200 201 146 // These are pure virtual in AudioOutput, but we don't need them here 202 147 virtual void bufferOutputData(bool){ return; } 203 148 virtual int readOutputData(unsigned char*, int ){ return 0; }
