Ticket #7517: volume_control_trunk_r24763.patch
| File volume_control_trunk_r24763.patch, 139.3 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 } … … 1240 1244 { 1241 1245 if (on_or_off) 1242 1246 { 1243 volume_status->SetUsed(gPlayer->get Output()->GetCurrentVolume());1247 volume_status->SetUsed(gPlayer->getVolume()); 1244 1248 volume_status->SetOrder(0); 1245 1249 volume_status->refresh(); 1246 1250 volume_display_timer->setSingleShot(true); … … 2452 2456 2453 2457 return time_string; 2454 2458 } 2459 2460 void PlaybackBoxMusic::VolumeChanged(int) 2461 { 2462 showVolume(true); 2463 } 2464 2465 void PlaybackBoxMusic::MuteChanged(bool) 2466 { 2467 showVolume(true); 2468 } -
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 … … 378 380 379 381 // TODO: Error checking that device is opened correctly! 380 382 m_output = AudioOutput::OpenAudio(adevice, pdevice, 16, 2, 0, 44100, 381 AUDIOOUTPUT_MUSIC, true,false,383 AUDIOOUTPUT_MUSIC, false, 382 384 gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1); 383 385 m_output->setBufferSize(256 * 1024); 384 386 m_output->SetBlocking(false); … … 944 946 945 947 void MusicPlayer::incVolume() 946 948 { 947 if ( getOutput())949 if (volume_control) 948 950 { 949 getOutput()->AdjustCurrentVolume(2);951 volume_control->increaseVolume(); 950 952 sendVolumeChangedEvent(); 951 953 } 952 954 } 953 955 954 956 void MusicPlayer::decVolume() 955 957 { 956 if ( getOutput())958 if (volume_control) 957 959 { 958 getOutput()->AdjustCurrentVolume(-2);960 volume_control->decreaseVolume(); 959 961 sendVolumeChangedEvent(); 960 962 } 961 963 } 962 964 963 965 void MusicPlayer::setVolume(int volume) 964 966 { 965 if ( getOutput())967 if (volume_control) 966 968 { 967 getOutput()->SetCurrentVolume(volume);969 volume_control->setVolume(volume); 968 970 sendVolumeChangedEvent(); 969 971 } 970 972 } 971 973 972 974 uint MusicPlayer::getVolume(void) const 973 975 { 974 if ( m_output)975 return m_output->GetCurrentVolume();976 if (volume_control) 977 return volume_control->volume(); 976 978 return 0; 977 979 } 978 980 979 981 void MusicPlayer::toggleMute(void) 980 982 { 981 if ( m_output)983 if (volume_control) 982 984 { 983 m_output->ToggleMute();985 volume_control->setMute(!volume_control->mute()); 984 986 sendVolumeChangedEvent(); 985 987 } 986 988 } 987 989 988 MuteState MusicPlayer::getMuteState(void) const990 bool MusicPlayer::isMuted(void) const 989 991 { 990 if ( m_output)991 return m_output->GetMuteState();992 return kMuteAll;992 if (volume_control) 993 return volume_control->mute(); 994 return true; 993 995 } 994 996 995 997 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
627 627 eval "$var=\"\$$var $*\"" 628 628 } 629 629 630 prepend(){ 631 var=$1 632 shift 633 flags_saved && eval "SAVE_$var=\"$* \$SAVE_$var\"" 634 eval "$var=\"$* \$$var\"" 635 } 636 630 637 append_uniq(){ 631 638 log append_uniq "$@" 632 639 var=$1 … … 3630 3637 { { ! enabled audio_alsa || die "ERROR: Alsa >= 1.0.16 required"; } && 3631 3638 disable audio_alsa; } 3632 3639 3640 # OSS probe 3641 if ! disabled audio_oss ; then 3642 if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h && 3643 check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3644 disable soundcard_h 3645 enable sys_soundcard_h 3646 prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include" 3647 elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h && 3648 check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3649 disable soundcard_h 3650 enable sys_soundcard_h 3651 prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include" 3652 else 3653 if enabled soundcard_h ; then 3654 check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" && 3655 enable audio_oss || 3656 disable audio_oss 3657 elif enabled sys_soundcard_h ; then 3658 check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" && 3659 enable audio_oss || 3660 disable audio_oss 3661 fi 3662 fi 3663 fi 3633 3664 3634 3665 # JACK probe 3635 3666 ! 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_bits(-1), 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(); … … 861 796 862 797 if (!audioOutput && !using_null_videoout && player_ctx->IsAudioNeeded()) 863 798 { 864 bool setVolume = gCoreContext->GetNumSetting("MythControlsVolume", 1);865 799 audioOutput = AudioOutput::OpenAudio(audio_main_device, 866 800 audio_passthru_device, 867 801 audio_bits, audio_channels, 868 802 audio_codec, audio_samplerate, 869 803 AUDIOOUTPUT_VIDEO, 870 setVolume,audio_passthru);804 audio_passthru); 871 805 if (!audioOutput) 872 806 errMsg = QObject::tr("Unable to create AudioOutput."); 873 807 else … … 889 823 VERBOSE(VB_IMPORTANT, LOC + "Enabling Audio"); 890 824 no_audio_out = false; 891 825 } 892 if (audio_muted_on_creation)893 {894 SetMuteState(kMuteAll);895 audio_muted_on_creation = false;896 }897 826 } 898 827 899 828 if (audioOutput) -
mythtv/libs/libmythtv/avformatdecoder.cpp
496 496 audioSamples(NULL), audioSamplesResampled(NULL), 497 497 reformat_ctx(NULL), audio_src_fmt(SAMPLE_FMT_NONE), 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), … … 520 519 max_channels = (uint) gCoreContext->GetNumSetting("MaxChannels", 2); 521 520 allow_ac3_passthru = (max_channels > 2) ? gCoreContext->GetNumSetting("AC3PassThru", false) : false; 522 521 allow_dts_passthru = (max_channels > 2) ? gCoreContext->GetNumSetting("DTSPassThru", false) : false; 523 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);524 522 525 523 audioIn.sample_size = -32; // force SetupAudioStream to run once 526 524 itv = GetNVP()->GetInteractiveTV(); … … 4701 4699 4702 4700 if (ctx->codec_id == CODEC_ID_AC3) 4703 4701 passthru = allow_ac3_passthru && 4704 ctx->channels >= (int)max_channels && 4705 !internal_vol; 4702 ctx->channels >= (int)max_channels; 4706 4703 else if (ctx->codec_id == CODEC_ID_DTS) 4707 passthru = allow_dts_passthru && !internal_vol;4704 passthru = allow_dts_passthru; 4708 4705 4709 4706 passthru &= !transcoding && !disable_passthru; 4710 4707 // 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 … … 299 299 void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*); 300 300 void ClearUDPNotifyEvents(void); 301 301 302 void VolumeChanged(int volume); 303 void MuteChanged(bool mute); 304 302 305 protected: 303 306 void TreeMenuEntered(OSDListTreeItemEnteredEvent *e); 304 307 void TreeMenuSelected(OSDListTreeItemSelectedEvent *e); … … 308 311 virtual void run(void); 309 312 void TVEventThreadChecks(void); 310 313 311 void SetMuteTimer(PlayerContext*, int timeout);312 bool MuteChannelChange(PlayerContext *ctx);313 314 314 bool eventFilter(QObject *o, QEvent *e); 315 315 static QStringList lastProgramStringList; 316 316 static EMBEDRETURNVOID RunPlaybackBoxPtr; … … 508 508 509 509 vector<long long> TeardownAllNVPs(PlayerContext*); 510 510 void RestartAllNVPs(PlayerContext *lctx, 511 const vector<long long> &pos, 512 MuteState mctx_mute); 511 const vector<long long> &pos); 513 512 void RestartMainNVP(PlayerContext *mctx); 514 513 515 514 void PxPToggleView( PlayerContext *actx, bool wantPBP); … … 669 668 /// Picture attribute to modify (on arrow left or right) 670 669 PictureAttribute adjustingPictureAttribute; 671 670 671 QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface 672 672 673 // Ask Allow state 673 674 AskAllowType askAllowType; 674 675 QMap<QString,AskProgramInfo> askAllowPrograms; … … 828 829 TimerContextMap stateChangeTimerId; 829 830 TimerContextMap signalMonitorTimerId; 830 831 TimerContextMap tvchainUpdateTimerId; 831 TimerContextMap unmuteTimerId;832 832 833 833 /// Condition to signal that the Event thread is up and running 834 834 QWaitCondition mainLoopCond; … … 849 849 850 850 ///< Timeout for entry modes in msec 851 851 static const uint kInputModeTimeout; 852 /// Channel changing mute timeout in msec853 static const uint kMuteTimeout;854 852 /// Timeout for updating LCD info in msec 855 853 static const uint kLCDTimeout; 856 854 /// Timeout for browse mode exit in msec -
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(); … … 494 493 VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg); 495 494 } 496 495 } 497 else if (pipState == kPBPRight)498 nvp->SetMuted(true);499 496 500 497 int maxWait = -1; 501 498 //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 "RingBuffer.h" 9 8 #include "osd.h" 10 9 #include "jitterometer.h" … … 89 88 friend class PlayerContext; 90 89 91 90 public: 92 NuppelVideoPlayer( bool muted = false);91 NuppelVideoPlayer(); 93 92 ~NuppelVideoPlayer(); 94 93 95 94 // Initialization … … 112 111 void SetAudioInfo(const QString &main, const QString &passthru, uint rate); 113 112 void SetAudioParams(int bits, int channels, int codec, int samplerate, bool passthru); 114 113 void SetEffDsp(int dsprate); 115 uint AdjustVolume(int change);116 bool SetMuted(bool mute);117 MuteState SetMuteState(MuteState);118 MuteState IncrMuteState(void);119 114 void SetAudioCodec(void *ac); 120 115 121 116 // Sets … … 172 167 float GetVideoAspect(void) const { return video_aspect; } 173 168 float GetFrameRate(void) const { return video_frame_rate; } 174 169 175 uint GetVolume(void);176 170 int GetSecondsBehind(void) const; 177 171 AspectOverrideMode GetAspectOverride(void) const; 178 172 AdjustFillMode GetAdjustFill(void) const; 179 MuteState GetMuteState(void);180 173 CommSkipMode GetAutoCommercialSkip(void) const; 181 174 182 175 int GetFFRewSkip(void) const { return ffrew_skip; } … … 211 204 bool HasAudioOut(void) const { return !no_audio_out; } 212 205 bool IsPIPActive(void) const { return pip_active; } 213 206 bool IsPIPVisible(void) const { return pip_visible; } 214 bool IsMuted(void) { return GetMuteState() == kMuteAll; }215 207 bool UsingNullVideo(void) const { return using_null_videoout; } 216 208 bool HasTVChainNext(void) const; 217 209 … … 719 711 float audio_stretchfactor; 720 712 bool audio_passthru; 721 713 QMutex audio_lock; 722 bool audio_muted_on_creation;723 714 724 715 // Picture-in-Picture 725 716 mutable QMutex pip_players_lock; -
mythtv/libs/libmythtv/tv_play.cpp
85 85 86 86 87 87 const uint TV::kInputModeTimeout = 5000; 88 const uint TV::kMuteTimeout = 800;89 88 const uint TV::kLCDTimeout = 1000; 90 89 const uint TV::kBrowseTimeout = 30000; 91 90 const uint TV::kKeyRepeatTimeout = 300; … … 1013 1012 player.push_back(new PlayerContext(kPlayerInUseID)); 1014 1013 playerActive = 0; 1015 1014 playerLock.unlock(); 1015 1016 volumeControl = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 1017 if (volumeControl) 1018 { 1019 connect(volumeControl.data(), SIGNAL(changedVolume(int)), 1020 this, SLOT(VolumeChanged(int)), Qt::QueuedConnection); 1021 connect(volumeControl.data(), SIGNAL(changedMute(bool)), 1022 this, SLOT(MuteChanged(bool)), Qt::QueuedConnection); 1023 } 1024 1016 1025 VERBOSE(VB_PLAYBACK, LOC + "ctor -- end"); 1017 1026 } 1018 1027 … … 2881 2890 if (handled) 2882 2891 return; 2883 2892 2884 // Check unmute..2885 ctx = NULL;2886 {2887 QMutexLocker locker(&timerIdLock);2888 TimerContextMap::iterator it = unmuteTimerId.find(timer_id);2889 if (it != unmuteTimerId.end())2890 {2891 KillTimer(timer_id);2892 ctx = *it;2893 unmuteTimerId.erase(it);2894 }2895 }2896 2897 if (ctx)2898 {2899 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__);2900 if (find_player_index(ctx) >= 0)2901 {2902 ctx->LockDeleteNVP(__FILE__, __LINE__);2903 if (ctx->nvp && ctx->nvp->IsMuted())2904 ctx->nvp->SetMuted(false);2905 ctx->UnlockDeleteNVP(__FILE__, __LINE__);2906 }2907 ReturnPlayerLock(mctx);2908 handled = true;2909 }2910 2911 2893 if (handled) 2912 2894 return; 2913 2895 … … 5450 5432 } 5451 5433 } 5452 5434 5453 MuteState mctx_mute = kMuteOff;5454 mctx->LockDeleteNVP(__FILE__, __LINE__);5455 if (mctx->nvp)5456 mctx_mute = mctx->nvp->GetMuteState();5457 mctx->UnlockDeleteNVP(__FILE__, __LINE__);5458 5459 5435 vector<long long> pos = TeardownAllNVPs(mctx); 5460 5436 5461 5437 if (wantPBP) … … 5473 5449 } 5474 5450 } 5475 5451 5476 RestartAllNVPs(mctx, pos , mctx_mute);5452 RestartAllNVPs(mctx, pos); 5477 5453 5478 5454 VERBOSE(VB_PLAYBACK, LOC + 5479 5455 QString("PxPToggleType() converting from %1 to %2 -- end") … … 5617 5593 * \brief Recreate Main and PIP windows. Could be either PIP or PBP views. 5618 5594 */ 5619 5595 void TV::RestartAllNVPs(PlayerContext *lctx, 5620 const vector<long long> &pos, 5621 MuteState mctx_mute) 5596 const vector<long long> &pos) 5622 5597 { 5623 5598 QString loc = LOC + QString("RestartAllNVPs(): "); 5624 5599 … … 5665 5640 pipctx->LockDeleteNVP(__FILE__, __LINE__); 5666 5641 if (pipctx->nvp) 5667 5642 { 5668 pipctx->nvp->SetMuted(true);5669 5643 pipctx->nvp->JumpToFrame(pos[i]); 5670 5644 } 5671 5645 pipctx->UnlockDeleteNVP(__FILE__, __LINE__); … … 5677 5651 ForceNextStateNone(pipctx); 5678 5652 } 5679 5653 } 5680 5681 // If old main player had a kMuteAll | kMuteOff setting,5682 // apply old main player's mute setting to new main player.5683 mctx->LockDeleteNVP(__FILE__, __LINE__);5684 if (mctx->nvp && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))5685 mctx->nvp->SetMuteState(mctx_mute);5686 mctx->UnlockDeleteNVP(__FILE__, __LINE__);5687 5654 } 5688 5655 5689 5656 void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx) … … 5711 5678 return; 5712 5679 } 5713 5680 5714 MuteState mctx_mute = mctx->nvp->GetMuteState();5715 5681 mctx->deleteNVPLock.unlock(); 5716 5682 pipctx->deleteNVPLock.unlock(); 5717 5683 … … 5725 5691 playerActive = (ctx_index == playerActive) ? 5726 5692 0 : ((ctx_index == 0) ? ctx_index : playerActive); 5727 5693 5728 RestartAllNVPs(mctx, pos , mctx_mute);5694 RestartAllNVPs(mctx, pos); 5729 5695 5730 5696 SetActive(mctx, playerActive, false); 5731 5697 … … 5746 5712 mctx->deleteNVPLock.unlock(); 5747 5713 return; 5748 5714 } 5749 5750 MuteState mctx_mute = mctx->nvp->GetMuteState();5751 5752 // HACK - FIXME5753 // workaround muted audio when NVP is re-created5754 mctx_mute = kMuteOff;5755 // FIXME - end5756 5715 mctx->deleteNVPLock.unlock(); 5757 5716 5758 5717 vector<long long> pos = TeardownAllNVPs(mctx); 5759 RestartAllNVPs(mctx, pos , mctx_mute);5718 RestartAllNVPs(mctx, pos); 5760 5719 SetActive(mctx, playerActive, false); 5761 5720 5762 5721 VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end"); … … 5881 5840 5882 5841 VERBOSE(VB_PLAYBACK, LOC + "DoNVPSeek() -- begin"); 5883 5842 5884 bool muted = false;5885 5886 5843 ctx->LockDeleteNVP(__FILE__, __LINE__); 5887 5844 if (!ctx->nvp) 5888 5845 { … … 5890 5847 return false; 5891 5848 } 5892 5849 5893 if (ctx == GetPlayer(ctx, 0))5894 muted = MuteChannelChange(ctx);5895 5896 5850 bool res = false; 5897 5851 5898 5852 if (LONG_LONG_MIN != audiosyncBaseline) … … 5913 5867 } 5914 5868 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 5915 5869 5916 if (muted)5917 SetMuteTimer(ctx, kMuteTimeout);5918 5919 5870 VERBOSE(VB_PLAYBACK, LOC + "DoNVPSeek() -- end"); 5920 5871 5921 5872 return res; … … 6281 6232 NormalSpeed(ctx); 6282 6233 StopFFRew(ctx); 6283 6234 6284 ctx->LockDeleteNVP(__FILE__, __LINE__);6285 bool muted = MuteChannelChange(ctx);6286 ctx->UnlockDeleteNVP(__FILE__, __LINE__);6287 6288 6235 struct StatusPosInfo posInfo; 6289 6236 ctx->CalcNVPSliderPosition(posInfo); 6290 6237 … … 6303 6250 if (ctx->nvp) 6304 6251 ctx->nvp->JumpChapter(chapter); 6305 6252 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 6306 6307 if (muted)6308 SetMuteTimer(ctx, kMuteTimeout);6309 6253 } 6310 6254 6311 6255 void TV::DoSkipCommercials(PlayerContext *ctx, int direction) … … 6316 6260 if (StateIsLiveTV(GetState(ctx))) 6317 6261 return; 6318 6262 6319 ctx->LockDeleteNVP(__FILE__, __LINE__);6320 bool muted = MuteChannelChange(ctx);6321 ctx->UnlockDeleteNVP(__FILE__, __LINE__);6322 6323 6263 struct StatusPosInfo posInfo; 6324 6264 ctx->CalcNVPSliderPosition(posInfo); 6325 6265 … … 6338 6278 if (ctx->nvp) 6339 6279 ctx->nvp->SkipCommercials(direction); 6340 6280 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 6341 6342 if (muted)6343 SetMuteTimer(ctx, kMuteTimeout);6344 6281 } 6345 6282 6346 6283 void TV::SwitchSource(PlayerContext *ctx, uint source_direction) … … 6501 6438 if (mctx != ctx) 6502 6439 PIPRemovePlayer(mctx, ctx); 6503 6440 6504 bool muted = false;6505 ctx->LockDeleteNVP(__FILE__, __LINE__);6506 if (ctx->nvp && ctx->nvp->IsMuted())6507 muted = true;6508 ctx->UnlockDeleteNVP(__FILE__, __LINE__);6509 6510 6441 // pause the decoder first, so we're not reading too close to the end. 6511 6442 ctx->buffer->IgnoreLiveEOF(true); 6512 6443 ctx->buffer->StopReads(); … … 6558 6489 6559 6490 if (ctx->CreateNVP( 6560 6491 this, GetMythMainWindow(), ctx->GetState(), 6561 mctx->embedWinID, &mctx->embedBounds , muted))6492 mctx->embedWinID, &mctx->embedBounds)) 6562 6493 { 6563 6494 ScheduleStateChange(ctx); 6564 6495 ok = true; … … 6915 6846 6916 6847 void TV::ChangeChannel(PlayerContext *ctx, int direction) 6917 6848 { 6918 bool muted = false;6919 6920 6849 if ((browse_changrp || (direction == CHANNEL_DIRECTION_FAVORITE)) && 6921 6850 (channel_group_id > -1)) 6922 6851 { … … 6947 6876 6948 6877 QString oldinputname = ctx->recorder->GetInput(); 6949 6878 6950 muted = MuteChannelChange(ctx);6951 6952 6879 if (ctx->paused) 6953 6880 { 6954 6881 OSD *osd = GetOSDLock(ctx); … … 6976 6903 ctx->recorder->ChangeChannel(direction); 6977 6904 ClearInputQueues(ctx, false); 6978 6905 6979 if (muted)6980 SetMuteTimer(ctx, kMuteTimeout * 2);6981 6982 6906 UnpauseLiveTV(ctx); 6983 6907 6984 6908 if (oldinputname != ctx->recorder->GetInput()) … … 6995 6919 6996 6920 QString channum = chan; 6997 6921 QStringList reclist; 6998 bool muted = false;6999 6922 7000 6923 QString oldinputname = ctx->recorder->GetInput(); 7001 6924 … … 7065 6988 if (getit || !ctx->recorder || !ctx->recorder->CheckChannel(channum)) 7066 6989 return; 7067 6990 7068 muted = MuteChannelChange(ctx);7069 7070 6991 OSD *osd = GetOSDLock(ctx); 7071 6992 if (osd && ctx->paused) 7072 6993 { … … 7092 7013 7093 7014 ctx->recorder->SetChannel(channum); 7094 7015 7095 if (muted)7096 SetMuteTimer(ctx, kMuteTimeout * 2);7097 7098 7016 UnpauseLiveTV(ctx); 7099 7017 7100 7018 if (oldinputname != ctx->recorder->GetInput()) … … 8202 8120 8203 8121 void TV::ChangeVolume(PlayerContext *ctx, bool up) 8204 8122 { 8205 ctx->LockDeleteNVP(__FILE__, __LINE__); 8206 if (!ctx->nvp) 8123 if (volumeControl) 8207 8124 { 8208 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8209 return; 8125 if (up) 8126 volumeControl->increaseVolume(); 8127 else 8128 volumeControl->decreaseVolume(); 8210 8129 } 8211 uint curvol = ctx->nvp->AdjustVolume((up) ? +2 : -2);8212 ctx->UnlockDeleteNVP(__FILE__, __LINE__);8213 8214 QString text = tr("Volume %1 %").arg(curvol);8215 8216 OSD *osd = GetOSDLock(ctx);8217 if (osd && !browsemode)8218 {8219 osd->ShowStatus(curvol * 10, true, tr("Adjust Volume"), text, 5,8220 kOSDFunctionalType_PictureAdjust);8221 SetUpdateOSDPosition(false);8222 }8223 ReturnOSDLock(ctx, osd);8224 8130 } 8225 8131 8226 8132 void TV::ToggleTimeStretch(PlayerContext *ctx) … … 8369 8275 8370 8276 void TV::ToggleMute(PlayerContext *ctx) 8371 8277 { 8372 ctx->LockDeleteNVP(__FILE__, __LINE__); 8373 if (!ctx->nvp || !ctx->nvp->HasAudioOut()) 8374 { 8375 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8376 return; 8377 } 8378 8379 MuteState mute_status; 8380 8381 if (!MuteIndividualChannels) 8382 { 8383 ctx->nvp->SetMuted(!ctx->nvp->IsMuted()); 8384 mute_status = (ctx->nvp->IsMuted()) ? kMuteAll : kMuteOff; 8385 } 8386 else 8387 { 8388 mute_status = ctx->nvp->IncrMuteState(); 8389 } 8390 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8391 8392 QString text; 8393 8394 switch (mute_status) 8395 { 8396 case kMuteOff: text = tr("Mute Off"); break; 8397 case kMuteAll: text = tr("Mute On"); break; 8398 case kMuteLeft: text = tr("Left Channel Muted"); break; 8399 case kMuteRight: text = tr("Right Channel Muted"); break; 8400 } 8401 8402 OSD *osd = GetOSDLock(ctx); 8403 if (osd && !browsemode) 8404 osd->SetSettingsText(text, 5); 8405 ReturnOSDLock(ctx, osd); 8278 if (volumeControl) 8279 volumeControl->setMute(!volumeControl->mute()); 8406 8280 } 8407 8281 8408 8282 void TV::ToggleSleepTimer(const PlayerContext *ctx) … … 8562 8436 ReturnOSDLock(ctx, osd); 8563 8437 } 8564 8438 8565 void TV::SetMuteTimer(PlayerContext *ctx, int timeout)8566 {8567 // message to set the timer will be posted to the main UI thread8568 // where it will be caught in eventFilter and processed as CustomEvent8569 // this will properly set the mute timer8570 // otherwise it never fires on Win328571 QString message = QString("UNMUTE %1 %2").arg((long long)ctx).arg(timeout);8572 qApp->postEvent(GetMythMainWindow(), new MythEvent(message));8573 }8574 8575 bool TV::MuteChannelChange(PlayerContext *ctx)8576 {8577 if (!ctx)8578 return false;8579 8580 bool muted = false;8581 ctx->LockDeleteNVP(__FILE__, __LINE__);8582 if (ctx->nvp && !ctx->nvp->IsMuted())8583 muted = ctx->nvp->SetMuted(true);8584 ctx->UnlockDeleteNVP(__FILE__, __LINE__);8585 8586 return muted;8587 }8588 8589 8439 void TV::customEvent(QEvent *e) 8590 8440 { 8591 8441 if (e->type() == OSDCloseEvent::kEventType) … … 8860 8710 } 8861 8711 } 8862 8712 8863 if (message.left(6) == "UNMUTE")8864 {8865 if (tokens.size() >= 3)8866 {8867 long long target = tokens[1].toLongLong();8868 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__);8869 for (uint i = 0; i < player.size(); i++)8870 {8871 PlayerContext *ctx = GetPlayer(mctx, i);8872 if (((long long)ctx) == target)8873 {8874 QMutexLocker locker(&timerIdLock);8875 unmuteTimerId[StartTimer(tokens[2].toUInt(), __LINE__)] = ctx;8876 }8877 }8878 ReturnPlayerLock(mctx);8879 }8880 }8881 8882 8713 if (message.left(9) == "START_EPG") 8883 8714 { 8884 8715 int editType = tokens[1].toInt(); … … 9372 9203 { 9373 9204 value = ctx->nvp->getVideoOutput()->GetPictureAttribute(attr); 9374 9205 } 9375 else if (ctx->nvp->HasAudioOut() )9206 else if (ctx->nvp->HasAudioOut() && volumeControl) 9376 9207 { 9377 value = ctx->nvp->GetVolume();9208 value = volumeControl->volume(); 9378 9209 title = tr("Adjust Volume"); 9379 9210 } 9380 9211 } … … 11975 11806 ReturnPlayerLock(mctx); 11976 11807 } 11977 11808 11809 void TV::VolumeChanged(int volume) 11810 { 11811 OSD *osd = GetOSDL(__FILE__, __LINE__); 11812 if (osd && !browsemode) 11813 { 11814 osd->ShowStatus(volume * 10, true, tr("Adjust Volume"), 11815 tr("Volume %1 %").arg(volume), 5, 11816 kOSDFunctionalType_PictureAdjust); 11817 SetUpdateOSDPosition(false); 11818 } 11819 ReturnOSDLock(osd); 11820 } 11821 11822 void TV::MuteChanged(bool mute) 11823 { 11824 OSD *osd = GetOSDL(__FILE__, __LINE__); 11825 if (osd && !browsemode) 11826 osd->SetSettingsText(mute ? tr("Mute On") : tr("Mute Off"), 5); 11827 ReturnOSDLock(osd); 11828 } 11829 11830 11978 11831 OSD *TV::GetOSDL(const char *file, int location) 11979 11832 { 11980 11833 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
305 305 306 306 bool allow_ac3_passthru; 307 307 bool allow_dts_passthru; 308 bool internal_vol;309 308 bool disable_passthru; 310 309 uint max_channels; 311 310 uint last_ac3_channels; -
mythtv/libs/libmyth/audiooutputwin.cpp
263 263 { 264 264 return m_nPkts * fragment_size; 265 265 } 266 267 int AudioOutputWin::GetVolumeChannel(int channel) const268 {269 DWORD dwVolume = 0xffffffff;270 int Volume = 100;271 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))272 {273 Volume = (channel == 0) ?274 (LOWORD(dwVolume) / (0xffff / 100)) :275 (HIWORD(dwVolume) / (0xffff / 100));276 }277 278 VERBOSE(VB_AUDIO, "GetVolume(" << channel << ") "279 << Volume << "(" << dwVolume << ")");280 281 return Volume;282 }283 284 void AudioOutputWin::SetVolumeChannel(int channel, int volume)285 {286 if (channel > 1)287 {288 Error(QString("Error setting channel: %1. "289 "Only stereo volume supported").arg(channel));290 return;291 }292 293 DWORD dwVolume = 0xffffffff;294 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))295 {296 if (channel == 0)297 dwVolume = dwVolume & 0xffff0000 | volume * (0xffff / 100);298 else299 dwVolume = dwVolume & 0xffff | ((volume * (0xffff / 100)) << 16);300 }301 else302 {303 dwVolume = volume * (0xffff / 100);304 dwVolume |= (dwVolume << 16);305 }306 307 VERBOSE(VB_AUDIO, QString("SetVolume(%1) %2(%3)")308 .arg(channel).arg(volume).arg(dwVolume));309 waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, dwVolume);310 } -
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
18 18 #include "audiooutput.h" 19 19 #include "samplerate.h" 20 20 #include "mythverbose.h" 21 #include "volumecontrolmanager.h" 21 22 22 23 namespace soundtouch { 23 24 class SoundTouch; … … 47 48 48 49 virtual void Reset(void); 49 50 50 void SetSWVolume(int new_volume, bool save);51 int GetSWVolume(void);52 53 51 // timecode is in milliseconds. 54 52 virtual bool AddSamples(char *buffer, int samples, long long timecode); 55 53 virtual bool AddSamples(char *buffers[], int samples, long long timecode); … … 113 111 int audiolen(bool use_lock); // number of valid bytes in audio buffer 114 112 int audiofree(bool use_lock); // number of free bytes in audio buffer 115 113 116 void UpdateVolume(void);117 118 114 void SetStretchFactorLocked(float factor); 119 115 120 116 int GetBaseAudioTime() const { return audiotime; } … … 148 144 bool killaudio; 149 145 150 146 bool pauseaudio, audio_actually_paused, was_paused; 151 bool set_initial_vol;152 147 bool buffer_output_data_for_use; // used by AudioOutputNULL 153 148 154 149 int configured_audio_channels; … … 181 176 int surround_mode; 182 177 bool allow_ac3_passthru; 183 178 float old_audio_stretchfactor; 184 int volume;179 QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface 185 180 186 181 bool blocking; // do AddSamples calls block? 187 182 -
mythtv/libs/libmyth/audiooutputalsa.cpp
1 #include "audiooutputalsa.h" 2 1 3 #include <cstdio> 2 4 #include <cstdlib> 3 5 #include <sys/time.h> … … 7 9 using namespace std; 8 10 9 11 #include "mythcorecontext.h" 10 #include "audiooutputalsa.h"11 12 12 13 #define LOC QString("ALSA: ") 13 14 #define LOC_WARN QString("ALSA, Warning: ") … … 18 19 #undef assert 19 20 #define assert(x) 20 21 22 // static 23 QHash<QString, QString> AudioOutputALSA::Enumerate() 24 { 25 QHash<QString, QString> result; 26 27 result.insert("ALSA:default", "Default ALSA device"); 28 29 int card = -1; 30 while (snd_card_next(&card) >= 0 && card >= 0) 31 { 32 snd_ctl_t* handle; 33 if (!snd_ctl_open(&handle, 34 QString("hw:%1").arg(card).toAscii().constData(), 0)) 35 { 36 snd_ctl_card_info_t* info; 37 snd_ctl_card_info_alloca(&info); 38 39 if (!snd_ctl_card_info(handle, info)) 40 { 41 int devices = 0; 42 43 for (int device = -1; 44 !snd_ctl_pcm_next_device(handle, &device) && device >= 0;) 45 { 46 snd_pcm_info_t* pcminfo; 47 snd_pcm_info_alloca(&pcminfo); 48 49 snd_pcm_info_set_device(pcminfo, device); 50 snd_pcm_info_set_subdevice(pcminfo, 0); 51 snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); 52 53 if (!snd_ctl_pcm_info(handle, pcminfo) && devices++) 54 break; 55 } 56 57 for (int device = -1; 58 !snd_ctl_pcm_next_device(handle, &device) && device >= 0;) 59 { 60 snd_pcm_info_t* pcminfo; 61 snd_pcm_info_alloca(&pcminfo); 62 63 snd_pcm_info_set_device(pcminfo, device); 64 snd_pcm_info_set_subdevice(pcminfo, 0); 65 snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); 66 67 if (!snd_ctl_pcm_info(handle, pcminfo)) 68 { 69 if (devices > 1) 70 { 71 result.insert(QString("ALSA:plughw:%1,%2") 72 .arg(snd_ctl_card_info_get_id(info)) 73 .arg(device), 74 QString("%1 %2") 75 .arg(snd_ctl_card_info_get_name(info)) 76 .arg(snd_pcm_info_get_name(pcminfo))); 77 } 78 else 79 { 80 result.insert(QString("ALSA:plughw:%1,%2") 81 .arg(snd_ctl_card_info_get_id(info)) 82 .arg(device), 83 snd_ctl_card_info_get_name(info)); 84 } 85 } 86 } 87 } 88 snd_ctl_close(handle); 89 } 90 } 91 92 return result; 93 } 94 21 95 AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) : 22 96 AudioOutputBase(settings), 23 97 pcm_handle(NULL), 24 numbadioctls(0), 25 mixer_handle(NULL), 26 mixer_control(QString::null) 98 numbadioctls(0) 27 99 { 28 100 // Set everything up 29 101 Reconfigure(settings); … … 253 325 // it really is 254 326 audio_buffer_unused = soundcard_buffer_size - (fragment_size * 4); 255 327 256 if (internal_vol)257 OpenMixer(set_initial_vol);258 259 328 // Device opened successfully 260 329 return true; 261 330 } 262 331 263 332 void AudioOutputALSA::CloseDevice() 264 333 { 265 CloseMixer();266 334 if (pcm_handle != NULL) 267 335 { 268 336 snd_pcm_close(pcm_handle); … … 622 690 return 0; 623 691 } 624 692 625 626 int AudioOutputALSA::GetVolumeChannel(int channel) const627 {628 long actual_volume;629 630 if (mixer_handle == NULL)631 return 100;632 633 QByteArray mix_ctl = mixer_control.toAscii();634 snd_mixer_selem_id_t *sid;635 snd_mixer_selem_id_alloca(&sid);636 snd_mixer_selem_id_set_index(sid, 0);637 snd_mixer_selem_id_set_name(sid, mix_ctl.constData());638 639 snd_mixer_elem_t *elem = snd_mixer_find_selem(mixer_handle, sid);640 if (!elem)641 {642 VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1")643 .arg(mixer_control));644 return 100;645 }646 647 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;648 if (!snd_mixer_selem_has_playback_channel(elem, chan))649 {650 snd_mixer_selem_id_set_index(sid, channel);651 if ((elem = snd_mixer_find_selem(mixer_handle, sid)) == NULL)652 {653 VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1 %2")654 .arg(mixer_control).arg(channel));655 return 100;656 }657 }658 659 ALSAVolumeInfo vinfo = GetVolumeRange(elem);660 661 snd_mixer_selem_get_playback_volume(662 elem, (snd_mixer_selem_channel_id_t)channel, &actual_volume);663 664 return vinfo.ToMythRange(actual_volume);665 }666 667 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)668 {669 SetCurrentVolume(mixer_control, channel, volume);670 }671 672 void AudioOutputALSA::SetCurrentVolume(QString control, int channel, int volume)673 {674 VERBOSE(VB_AUDIO, QString("Setting %1 volume to %2")675 .arg(control).arg(volume));676 677 if (!mixer_handle)678 return; // no mixer, nothing to do679 680 QByteArray ctl = control.toAscii();681 snd_mixer_selem_id_t *sid;682 snd_mixer_selem_id_alloca(&sid);683 snd_mixer_selem_id_set_index(sid, 0);684 snd_mixer_selem_id_set_name(sid, ctl.constData());685 686 snd_mixer_elem_t *elem = snd_mixer_find_selem(mixer_handle, sid);687 if (!elem)688 {689 VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1")690 .arg(control));691 return;692 }693 694 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;695 if (!snd_mixer_selem_has_playback_channel(elem, chan))696 {697 snd_mixer_selem_id_set_index(sid, channel);698 if ((elem = snd_mixer_find_selem(mixer_handle, sid)) == NULL)699 {700 VERBOSE(VB_IMPORTANT,701 QString("mixer unable to find control %1 %2")702 .arg(control).arg(channel));703 return;704 }705 }706 707 ALSAVolumeInfo vinfo = GetVolumeRange(elem);708 709 long set_vol = vinfo.ToALSARange(volume);710 711 int err = snd_mixer_selem_set_playback_volume(elem, chan, set_vol);712 if (err < 0)713 {714 VERBOSE(VB_IMPORTANT, QString("mixer set channel %1 err %2: %3")715 .arg(channel).arg(err).arg(snd_strerror(err)));716 }717 else718 {719 VERBOSE(VB_AUDIO, QString("channel %1 vol set to %2")720 .arg(channel).arg(set_vol));721 }722 723 if (snd_mixer_selem_has_playback_switch(elem))724 {725 int unmute = (0 != set_vol);726 if (snd_mixer_selem_has_playback_switch_joined(elem))727 {728 // Only mute if all the channels should be muted.729 for (int i = 0; i < audio_channels; i++)730 {731 if (0 != GetVolumeChannel(i))732 unmute = 1;733 }734 }735 736 err = snd_mixer_selem_set_playback_switch(elem, chan, unmute);737 if (err < 0)738 {739 VERBOSE(VB_IMPORTANT, LOC_ERR +740 QString("Mixer set playback switch %1 err %2: %3")741 .arg(channel).arg(err).arg(snd_strerror(err)));742 }743 else744 {745 VERBOSE(VB_AUDIO, LOC +746 QString("channel %1 playback switch set to %2")747 .arg(channel).arg(unmute));748 }749 }750 }751 752 void AudioOutputALSA::OpenMixer(bool setstartingvolume)753 {754 int volume;755 756 mixer_control = gCoreContext->GetSetting("MixerControl", "PCM");757 758 SetupMixer();759 760 if (mixer_handle != NULL && setstartingvolume)761 {762 volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);763 SetCurrentVolume("Master", 0, volume);764 SetCurrentVolume("Master", 1, volume);765 766 volume = gCoreContext->GetNumSetting("PCMMixerVolume", 80);767 SetCurrentVolume("PCM", 0, volume);768 SetCurrentVolume("PCM", 1, volume);769 }770 }771 772 void AudioOutputALSA::CloseMixer(void)773 {774 if (mixer_handle != NULL)775 snd_mixer_close(mixer_handle);776 mixer_handle = NULL;777 }778 779 void AudioOutputALSA::SetupMixer(void)780 {781 int err;782 783 QString alsadevice = gCoreContext->GetSetting("MixerDevice", "default");784 QString device = alsadevice.remove(QString("ALSA:"));785 786 if (mixer_handle != NULL)787 CloseMixer();788 789 if (alsadevice.toLower() == "software")790 return;791 792 VERBOSE(VB_AUDIO, QString("Opening mixer %1").arg(device));793 794 // TODO: This is opening card 0. Fix for case of multiple soundcards795 if ((err = snd_mixer_open(&mixer_handle, 0)) < 0)796 {797 Warn(QString("Mixer device open error %1: %2")798 .arg(err).arg(snd_strerror(err)));799 mixer_handle = NULL;800 return;801 }802 803 QByteArray dev = device.toAscii();804 if ((err = snd_mixer_attach(mixer_handle, dev.constData())) < 0)805 {806 Warn(QString("Mixer attach error %1: %2"807 "\n\t\t\tCheck Mixer Name in Setup: '%3'")808 .arg(err).arg(snd_strerror(err)).arg(device));809 CloseMixer();810 return;811 }812 813 if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0)814 {815 Warn(QString("Mixer register error %1: %2")816 .arg(err).arg(snd_strerror(err)));817 CloseMixer();818 return;819 }820 821 if ((err = snd_mixer_load(mixer_handle)) < 0)822 {823 Warn(QString("Mixer load error %1: %2")824 .arg(err).arg(snd_strerror(err)));825 CloseMixer();826 return;827 }828 }829 830 ALSAVolumeInfo AudioOutputALSA::GetVolumeRange(snd_mixer_elem_t *elem) const831 {832 long volume_min, volume_max;833 834 int err = snd_mixer_selem_get_playback_volume_range(835 elem, &volume_min, &volume_max);836 837 if (err < 0)838 {839 static bool first_time = true;840 if (first_time)841 {842 VERBOSE(VB_IMPORTANT,843 "snd_mixer_selem_get_playback_volume_range()" + ENO);844 first_time = false;845 }846 }847 848 ALSAVolumeInfo vinfo(volume_min, volume_max);849 850 VERBOSE(VB_AUDIO, QString("Volume range is %1 to %2, mult=%3")851 .arg(vinfo.volume_min).arg(vinfo.volume_max)852 .arg(vinfo.range_multiplier));853 854 return vinfo;855 }856 857 693 QMap<QString, QString> GetALSADevices(const char *type) 858 694 { 859 695 QMap<QString, QString> alsadevs; -
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 // TODO: Avoid assumption that there are 2 channels!110 for (int i = 0; i < 2; i++)111 {112 SetVolumeChannel(i, new_volume);113 }114 115 // Individual channel muting is handled in GetAudioData,116 // this code demonstrates the old method.117 // if (current_mute_state == kMuteLeft)118 // {119 // SetVolumeChannel(0, 0);120 // }121 // else if (current_mute_state == kMuteRight)122 // {123 // SetVolumeChannel(1, 0);124 // }125 }126 127 void VolumeBase::SyncVolume(void)128 {129 // Read the volume from the audio driver and setup our internal state to match130 if (swvol)131 volume = GetSWVolume();132 else133 volume = GetVolumeChannel(0);134 }135 -
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 41 bool internal_vol;42 43 private:44 45 int volume;46 MuteState current_mute_state;47 bool swvol;48 bool swvol_setting;49 50 };51 52 #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 Pause(bool paused); 36 34 void Reset(void); 37 35 void Drain(void); -
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
268 268 return writable; 269 269 } 270 270 271 int AudioOutputPulseAudio::GetVolumeChannel(int channel) const272 {273 return (float)volume_control.values[channel]274 / (float)PA_VOLUME_NORM * 100.0f;275 }276 277 void AudioOutputPulseAudio::SetVolumeChannel(int channel, int volume)278 {279 QString fn_log_tag = "SetVolumeChannel, ";280 if (channel < 0 || channel > PULSE_MAX_CHANNELS || volume < 0)281 {282 VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +283 QString("bad volume params, channel %1, volume %2")284 .arg(channel).arg(volume));285 return;286 }287 volume_control.values[channel] =288 (float)volume / 100.0f * (float)PA_VOLUME_NORM;289 volume = min(100, volume);290 volume = max(0, volume);291 uint32_t sink_index = pa_stream_get_device_index(pstream);292 pa_threaded_mainloop_lock(mainloop);293 pa_operation *op =294 pa_context_set_sink_volume_by_index(pcontext, sink_index,295 &volume_control,296 OpCompletionCallback, this);297 pa_threaded_mainloop_unlock(mainloop);298 if (op)299 pa_operation_unref(op);300 else301 VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +302 QString("set sink volume operation failed, sink: %1, "303 "error: %2 ")304 .arg(sink_index)305 .arg(pa_strerror(pa_context_errno(pcontext))));306 }307 308 271 void AudioOutputPulseAudio::Pause(bool paused) 309 272 { 310 273 pa_operation *op; … … 545 508 pa_stream_set_overflow_callback(pstream, BufferFlowCallback, (char*)"over"); 546 509 pa_stream_set_underflow_callback(pstream, BufferFlowCallback, 547 510 (char*)"under"); 548 if (set_initial_vol) 549 { 550 int volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80); 551 pa_cvolume_set(&volume_control, audio_channels, 552 (float)volume * (float)PA_VOLUME_NORM / 100.0f); 553 } 554 else 555 pa_cvolume_reset(&volume_control, audio_channels); 511 pa_cvolume_reset(&volume_control, audio_channels); 556 512 557 513 // set myth sizes and pa buffer metrics (20 ms) 558 514 // Note: The 20 is an unsigned long (at least 32 bits). -
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
11 11 AudioOutputJACK(const AudioSettings &settings); 12 12 virtual ~AudioOutputJACK(); 13 13 14 // Volume control15 virtual int GetVolumeChannel(int channel) const; // Returns 0-10016 virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol17 18 14 protected: 19 15 20 16 // You need to implement the following functions … … 27 23 28 24 private: 29 25 30 void VolumeInit(void);31 32 26 int audioid; 33 27 34 28 }; -
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 audio_codec, 45 43 int audio_samplerate, 46 44 AudioOutputSource audio_source, 47 bool audio_set_initial_vol,48 45 bool audio_use_passthru, 49 46 int upmixer_startup) : 50 47 main_device(audio_main_device), … … 53 50 channels(audio_channels), 54 51 codec(audio_codec), 55 52 samplerate(audio_samplerate), 56 set_initial_vol(audio_set_initial_vol),57 53 use_passthru(audio_use_passthru), 58 54 source(audio_source), 59 55 upmixer(upmixer_startup) … … 73 69 channels(audio_channels), 74 70 codec(audio_codec), 75 71 samplerate(audio_samplerate), 76 set_initial_vol(false),77 72 use_passthru(audio_use_passthru), 78 73 source(AUDIOOUTPUT_UNKNOWN), 79 74 upmixer(upmixer_startup) -
mythtv/libs/libmyth/audiooutputca.cpp
244 244 return false; 245 245 } 246 246 247 if (internal_vol && set_initial_vol)248 {249 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");250 controlLabel += "MixerVolume";251 SetCurrentVolume(gCoreContext->GetNumSetting(controlLabel, 80));252 }253 254 247 return true; 255 248 } 256 249 … … 399 392 return noErr; 400 393 } 401 394 402 int AudioOutputCA::GetVolumeChannel(int channel) const403 {404 // FIXME: this only returns global volume405 (void)channel;406 Float32 volume;407 408 if (!AudioUnitGetParameter(d->mOutputUnit,409 kHALOutputParam_Volume,410 kAudioUnitScope_Global, 0, &volume))411 return (int)lroundf(volume * 100.0);412 413 return 0; // error case414 }415 416 void AudioOutputCA::SetVolumeChannel(int channel, int volume)417 {418 // FIXME: this only sets global volume419 (void)channel;420 AudioUnitSetParameter(d->mOutputUnit, kHALOutputParam_Volume,421 kAudioUnitScope_Global, 0, (volume * 0.01), 0);422 }423 424 395 // IOProc style callback for SPDIF audio output 425 396 static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice, 426 397 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
150 150 audio_buffer_unused = JACK_GetBytesFreeSpace(audioid); 151 151 JACK_SetPosition(audioid, BYTES, 0); 152 152 153 // Setup volume control154 if (internal_vol)155 VolumeInit();156 157 153 // Device opened successfully 158 154 return true; 159 155 } … … 208 204 209 205 return space; 210 206 } 211 212 void AudioOutputJACK::VolumeInit(void)213 {214 int volume = 100;215 if (set_initial_vol)216 volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);217 218 JACK_SetAllVolume(audioid, volume);219 }220 221 int AudioOutputJACK::GetVolumeChannel(int channel) const222 {223 unsigned int vol = 0;224 225 if (!internal_vol)226 return 100;227 228 JACK_GetVolumeForChannel(audioid, channel, &vol);229 return vol;230 }231 232 void AudioOutputJACK::SetVolumeChannel(int channel, int volume)233 {234 if (internal_vol)235 JACK_SetVolumeForChannel(audioid, channel, volume);236 }237 -
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); … … 26 22 vector<int> GetSupportedRates(void); 27 23 28 24 private: 29 void VolumeInit(void);30 void VolumeCleanup(void);31 32 25 void SetFragSize(void); 33 26 34 27 int audiofd; 35 28 mutable int numbadioctls; 36 37 // Volume related38 int mixerfd;39 int control;40 29 }; 41 30 42 31 #endif -
mythtv/libs/libmyth/audiooutputbase.cpp
37 37 pauseaudio(false), audio_actually_paused(false), 38 38 was_paused(false), 39 39 40 set_initial_vol(settings.set_initial_vol),41 40 buffer_output_data_for_use(false), 42 41 43 42 // private … … 54 53 needs_upmix(false), 55 54 surround_mode(FreeSurround::SurroundModePassive), 56 55 old_audio_stretchfactor(1.0), 57 volume(80),58 56 59 57 blocking(false), 60 58 … … 109 107 110 108 allow_ac3_passthru = (orig_config_channels > 2) ? gCoreContext->GetNumSetting("AC3PassThru", false) : false; 111 109 110 if (gCoreContext->GetSetting("MixerDevice") == "Software:") 111 volume_control = VolumeControlManager::GetControl("Software:"); 112 112 113 // You need to call Reconfigure from your concrete class. 113 114 // Reconfigure(laudio_bits, laudio_channels, 114 115 // laudio_samplerate, laudio_passthru); … … 278 279 killaudio = false; 279 280 pauseaudio = false; 280 281 was_paused = true; 281 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);282 282 283 283 numlowbuffer = 0; 284 284 … … 375 375 return; 376 376 } 377 377 378 // Only used for software volume379 if (set_initial_vol && internal_vol)380 {381 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");382 controlLabel += "MixerVolume";383 volume = gCoreContext->GetNumSetting(controlLabel, 80);384 }385 386 SyncVolume();387 VolumeBase::UpdateVolume();388 389 378 VERBOSE(VB_AUDIO, LOC + QString("Audio fragment size: %1") 390 379 .arg(fragment_size)); 391 380 … … 679 668 return audbuf_timecode - GetAudiotime(); 680 669 } 681 670 682 void AudioOutputBase::SetSWVolume(int new_volume, bool save)683 {684 volume = new_volume;685 if (save)686 {687 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");688 controlLabel += "MixerVolume";689 gCoreContext->SaveSetting(controlLabel, volume);690 }691 }692 693 int AudioOutputBase::GetSWVolume()694 {695 return volume;696 }697 698 671 void AudioOutputBase::AdjustVolume(void *buffer, int len, bool music) 699 672 { 700 673 if (audio_bits == 8) … … 706 679 template <class AudioDataType> 707 680 void AudioOutputBase::_AdjustVolume(AudioDataType *buffer, int len, bool music) 708 681 { 682 int volume = volume_control->mute() ? 0 : volume_control->volume(); 683 709 684 float g = volume / 100.0; 710 685 711 686 // Should probably be exponential - this'll do … … 1114 1089 } 1115 1090 } 1116 1091 1117 if ( internal_vol && SWVolume())1092 if (volume_control) 1118 1093 { 1119 1094 int bdiff = kAudioRingBufferSize - waud; 1120 1095 bool music = (timecode < 1); … … 1378 1353 audio_buflock.unlock(); 1379 1354 1380 1355 // Mute individual channels through mono->stereo duplication 1381 MuteState mute_state = GetMuteState();1356 // MuteState mute_state = GetMuteState(); 1382 1357 if (written_size && 1383 audio_channels > 1 && 1384 (mute_state == kMuteLeft || mute_state == kMuteRight)) 1358 audio_channels > 1 //&& 1359 // (mute_state == kMuteLeft || mute_state == kMuteRight) 1360 ) 1385 1361 { 1386 1362 int offset_src = 0; 1387 1363 int offset_dst = 0; 1388 1364 1389 if (mute_state == kMuteLeft)1390 offset_src = audio_bits / 8; // copy channel 1 to channel 01391 else if (mute_state == kMuteRight)1392 offset_dst = audio_bits / 8; // copy channel 0 to channel 11365 // if (mute_state == kMuteLeft) 1366 // offset_src = audio_bits / 8; // copy channel 1 to channel 0 1367 // else if (mute_state == kMuteRight) 1368 // offset_dst = audio_bits / 8; // copy channel 0 to channel 1 1393 1369 1394 1370 for (int i = 0; i < written_size; i += audio_bytes_per_sample) 1395 1371 { -
mythtv/libs/libmyth/audiooutput.cpp
34 34 int audio_bits, int audio_channels, 35 35 int audio_codec, int audio_samplerate, 36 36 AudioOutputSource source, 37 bool set_initial_vol, boolaudio_passthru,37 bool audio_passthru, 38 38 int upmixer_startup) 39 39 { 40 40 AudioSettings settings( 41 41 main_device, passthru_device, audio_bits, 42 42 audio_channels, audio_codec, audio_samplerate, source, 43 set_initial_vol,audio_passthru, upmixer_startup);43 audio_passthru, upmixer_startup); 44 44 45 45 settings.FixPassThrough(); 46 46 -
mythtv/libs/libmyth/libmyth.pro
23 23 HEADERS += output.h 24 24 HEADERS += settings.h 25 25 HEADERS += uilistbtntype.h uitypes.h util.h mythuifilebrowser.h 26 HEADERS += volumebase.h visual.h xmlparse.h 26 HEADERS += volumecontrol.h volumecontrolmanager.h volumecontrolsoftware.h 27 HEADERS += visual.h xmlparse.h 27 28 HEADERS += mythhdd.h mythcdrom.h storagegroup.h dbutil.h 28 29 HEADERS += mythcommandlineparser.h mythterminal.h 29 30 HEADERS += mythhttppool.h mythhttphandler.h … … 47 48 SOURCES += output.cpp 48 49 SOURCES += settings.cpp 49 50 SOURCES += uilistbtntype.cpp uitypes.cpp util.cpp mythuifilebrowser.cpp 50 SOURCES += volumebase.cpp xmlparse.cpp 51 SOURCES += volumecontrolmanager.cpp volumecontrolsoftware.cpp 52 SOURCES += xmlparse.cpp 51 53 SOURCES += mythhdd.cpp mythcdrom.cpp storagegroup.cpp dbutil.cpp 52 54 SOURCES += mythcommandlineparser.cpp mythterminal.cpp 53 55 SOURCES += mythhttppool.cpp mythhttphandler.cpp … … 87 89 # Install headers so that plugins can compile independently 88 90 inc.path = $${PREFIX}/include/mythtv/ 89 91 inc.files = dialogbox.h mythcontext.h 90 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h92 inc.files += mythwidgets.h remotefile.h oldsettings.h 91 93 inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h 92 94 inc.files += audiooutput.h audiosettings.h util.h 93 95 inc.files += inetcomms.h mythmedia.h mythcdrom.h mythwizard.h schemawizard.h dbutil.h 94 96 inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h 95 inc.files += visual.h volume base.h output.h langsettings.h97 inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h 96 98 inc.files += mythexp.h mythpluginapi.h storagegroup.h 97 99 inc.files += mythconfigdialogs.h mythconfiggroups.h 98 100 inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h … … 109 111 110 112 using_oss { 111 113 DEFINES += USING_OSS 112 SOURCES += audiooutputoss.cpp 113 HEADERS += audiooutputoss.h 114 SOURCES += audiooutputoss.cpp volumecontroloss.cpp 115 HEADERS += audiooutputoss.h volumecontroloss.h 114 116 LIBS += $$OSS_LIBS 115 117 } 116 118 … … 138 140 139 141 mingw { 140 142 DEFINES += USING_MINGW 141 SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp 142 HEADERS += mediamonitor-windows.h audiooutputwin.h audiooutputdx.h 143 LIBS += -lpthread -lwinmm -lws2_32 143 SOURCES += mediamonitor-windows.cpp 144 HEADERS += mediamonitor-windows.h 145 SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp 146 HEADERS += audiooutputwin.h audiooutputdx.h volumecontrolendpoint.h 147 LIBS += -lpthread -lwinmm -lws2_32 -lole32 144 148 } 145 149 146 150 macx { 147 HEADERS += audiooutputca.h 148 SOURCES += audiooutputca.cpp 151 DEFINES += USE_COREAUDIO 152 HEADERS += audiooutputca.h volumecontrolcoreaudio.h 153 SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp 149 154 HEADERS += mythcdrom-darwin.h 150 155 SOURCES += mythcdrom-darwin.cpp 151 156 … … 185 190 186 191 using_alsa { 187 192 DEFINES += USE_ALSA 188 HEADERS += audiooutputalsa.h 189 SOURCES += audiooutputalsa.cpp 193 HEADERS += audiooutputalsa.h volumecontrolalsa.h 194 SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp 190 195 LIBS += $$ALSA_LIBS 191 196 } 192 197 -
mythtv/libs/libmyth/audiosettings.h
32 32 int audio_codec, 33 33 int audio_samplerate, 34 34 AudioOutputSource audio_source, 35 bool audio_set_initial_vol,36 35 bool audio_use_passthru, 37 36 int upmixer_startup = 0); 38 37 … … 58 57 int channels; 59 58 int codec; 60 59 int samplerate; 61 bool set_initial_vol;62 60 bool use_passthru; 63 61 AudioOutputSource source; 64 62 int upmixer; -
mythtv/libs/libmyth/audiooutputca.h
25 25 bool RenderAudio(unsigned char *aubuf, int size, 26 26 unsigned long long timestamp); 27 27 28 // Volume control29 virtual int GetVolumeChannel(int channel) const;30 virtual void SetVolumeChannel(int channel, int volume);31 32 28 void Debug(QString msg) 33 29 { VERBOSE(VB_AUDIO, "AudioOutputCA::" + msg); } 34 30 … … 37 33 38 34 void Warn(QString msg) 39 35 { VERBOSE(VB_IMPORTANT, "AudioOutputCA Warning: " + msg); } 36 bool internal_vol; 40 37 41 38 protected: 42 39 -
mythtv/libs/libmyth/audiooutputoss.cpp
30 30 31 31 AudioOutputOSS::AudioOutputOSS(const AudioSettings &settings) : 32 32 AudioOutputBase(settings), 33 audiofd(-1), numbadioctls(0), 34 mixerfd(-1), control(SOUND_MIXER_VOLUME) 33 audiofd(-1), numbadioctls(0) 35 34 { 36 35 // Set everything up 37 36 Reconfigure(settings); … … 194 193 " the error was: %1").arg(strerror(errno))); 195 194 } 196 195 197 // Setup volume control198 if (internal_vol)199 VolumeInit();200 201 196 // Device opened successfully 202 197 return true; 203 198 } … … 242 237 close(audiofd); 243 238 244 239 audiofd = -1; 245 246 VolumeCleanup();247 240 } 248 241 249 242 … … 310 303 311 304 return space; 312 305 } 313 314 void AudioOutputOSS::VolumeInit()315 {316 mixerfd = -1;317 int volume = 0;318 319 QString device = gCoreContext->GetSetting("MixerDevice", "/dev/mixer");320 if (device.toLower() == "software")321 return;322 323 QByteArray dev = device.toAscii();324 mixerfd = open(dev.constData(), O_RDONLY);325 326 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");327 328 if (controlLabel == "Master")329 {330 control = SOUND_MIXER_VOLUME;331 }332 else333 {334 control = SOUND_MIXER_PCM;335 }336 337 if (mixerfd < 0)338 {339 VERBOSE(VB_IMPORTANT, LOC +340 QString("Unable to open mixer: '%1'").arg(device));341 return;342 }343 344 if (set_initial_vol)345 {346 int tmpVol;347 volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);348 tmpVol = (volume << 8) + volume;349 int ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);350 if (ret < 0)351 {352 VERBOSE(VB_IMPORTANT, LOC_ERR +353 QString("Error Setting initial Master Volume") + ENO);354 }355 356 volume = gCoreContext->GetNumSetting("PCMMixerVolume", 80);357 tmpVol = (volume << 8) + volume;358 ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);359 if (ret < 0)360 {361 VERBOSE(VB_IMPORTANT, LOC_ERR +362 QString("Error setting initial PCM Volume") + ENO);363 }364 }365 }366 367 void AudioOutputOSS::VolumeCleanup()368 {369 if (mixerfd >= 0)370 {371 close(mixerfd);372 mixerfd = -1;373 }374 }375 376 int AudioOutputOSS::GetVolumeChannel(int channel) const377 {378 int volume=0;379 int tmpVol=0;380 381 if (mixerfd <= 0)382 return 100;383 384 int ret = ioctl(mixerfd, MIXER_READ(control), &tmpVol);385 if (ret < 0) {386 VERBOSE(VB_IMPORTANT, QString("Error reading volume for channel %1")387 .arg(channel));388 perror("Reading PCM volume: ");389 return 0;390 }391 392 if (channel == 0) {393 volume = tmpVol & 0xff; // left394 } else if (channel == 1) {395 volume = (tmpVol >> 8) & 0xff; // right396 } else {397 VERBOSE(VB_IMPORTANT, QString("Invalid channel. Only stereo volume supported"));398 }399 400 return volume;401 }402 403 void AudioOutputOSS::SetVolumeChannel(int channel, int volume)404 {405 if (channel > 1) {406 // Don't support more than two channels!407 VERBOSE(VB_IMPORTANT, QString("Error setting channel: %1. Only stereo volume supported")408 .arg(channel));409 return;410 }411 412 if (volume > 100)413 volume = 100;414 if (volume < 0)415 volume = 0;416 417 if (mixerfd >= 0)418 {419 int tmpVol = 0;420 if (channel == 0)421 tmpVol = (GetVolumeChannel(1) << 8) + volume;422 else423 tmpVol = (volume << 8) + GetVolumeChannel(0);424 425 int ret = ioctl(mixerfd, MIXER_WRITE(control), &tmpVol);426 if (ret < 0)427 {428 VERBOSE(VB_IMPORTANT, QString("Error setting volume on channel: %1").arg(channel));429 perror("Setting volume: ");430 }431 }432 }433 -
mythtv/libs/libmyth/audiooutputdx.cpp
465 465 dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */ 466 466 | DSBCAPS_GLOBALFOCUS /* Allows background playing */ 467 467 | DSBCAPS_LOCHARDWARE; /* Needed for 5.1 on emu101k */ 468 if (!m_UseSPDIF)469 dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME; /* Allow volume control */470 468 dsbdesc.dwBufferBytes = soundcard_buffer_size; /* buffer size */ 471 469 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf; 472 470 … … 601 599 return buffered; 602 600 } 603 601 604 int AudioOutputDX::GetVolumeChannel(int channel) const605 {606 HRESULT dsresult;607 long dxVolume = 0;608 int volume;609 610 if (m_UseSPDIF)611 return 100;612 613 dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);614 volume = (int)(pow(10,(float)dxVolume/20)*100);615 616 if (dsresult != DS_OK)617 {618 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Failed to get volume %1")619 .arg(dxVolume));620 return volume;621 }622 623 VERBOSE(VB_AUDIO, LOC + QString("Got volume %1").arg(volume));624 return volume;625 }626 627 void AudioOutputDX::SetVolumeChannel(int channel, int volume)628 {629 HRESULT dsresult;630 float dbAtten = 20 * log10((float)volume/100);631 long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);632 633 if (m_UseSPDIF)634 return;635 636 // dxVolume is attenuation in 100ths of a decibel637 dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);638 639 if (dsresult != DS_OK)640 {641 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Failed to set volume %1")642 .arg(dxVolume));643 return;644 }645 646 VERBOSE(VB_AUDIO, LOC + QString("Set volume %1").arg(dxVolume));647 }648 649 602 /* 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 "mythcontext.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 // opens one of the concrete subclasses … … 18 17 int audio_bits, int audio_channels, 19 18 int audio_codec, int audio_samplerate, 20 19 AudioOutputSource source, 21 bool set_initial_vol, boolaudio_passthru,20 bool audio_passthru, 22 21 int upmixer_startup = 0); 23 22 24 23 AudioOutput() : 25 VolumeBase(),OutputListeners(),24 OutputListeners(), 26 25 lastError(QString::null), lastWarn(QString::null) {} 27 26 28 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
13 13 AudioOutputDX(const AudioSettings &settings); 14 14 virtual ~AudioOutputDX(); 15 15 16 virtual int GetVolumeChannel(int channel) const;17 virtual void SetVolumeChannel(int channel, int volume);18 19 16 protected: 20 17 virtual bool OpenDevice(void); 21 18 virtual void CloseDevice(void); -
mythtv/libs/libmyth/audiooutputalsa.h
1 1 #ifndef AUDIOOUTPUTALSA 2 2 #define AUDIOOUTPUTALSA 3 3 4 #include <QHash> 5 #include <QString> 6 4 7 #define ALSA_PCM_NEW_HW_PARAMS_API 5 8 #define ALSA_PCM_NEW_SW_PARAMS_API 6 9 #include <alsa/asoundlib.h> … … 11 14 12 15 using namespace std; 13 16 14 class A LSAVolumeInfo17 class AudioOutputALSA : public AudioOutputBase 15 18 { 16 19 public: 17 ALSAVolumeInfo(long playback_vol_min, 18 long playback_vol_max) : 19 range_multiplier(1.0f), 20 volume_min(playback_vol_min), volume_max(playback_vol_max) 21 { 22 float range = (float) (volume_max - volume_min); 23 if (range > 0.0f) 24 range_multiplier = 100.0f / range; 25 range_multiplier_inv = 1.0f / range_multiplier; 26 } 20 static QHash<QString, QString> Enumerate(); 27 21 28 int ToMythRange(long alsa_volume)29 {30 long toz = alsa_volume - volume_min;31 int val = (int) (toz * range_multiplier);32 val = (val < 0) ? 0 : val;33 val = (val > 100) ? 100 : val;34 return val;35 }36 37 long ToALSARange(int myth_volume)38 {39 float tos = myth_volume * range_multiplier_inv;40 long val = (long) (tos + volume_min + 0.5);41 val = (val < volume_min) ? volume_min : val;42 val = (val > volume_max) ? volume_max : val;43 return val;44 }45 46 float range_multiplier;47 float range_multiplier_inv;48 long volume_min;49 long volume_max;50 };51 52 class AudioOutputALSA : public AudioOutputBase53 {54 22 public: 55 23 AudioOutputALSA(const AudioSettings &settings); 56 24 virtual ~AudioOutputALSA(); 57 25 58 // Volume control59 virtual int GetVolumeChannel(int channel) const; // Returns 0-10060 virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol61 62 63 26 protected: 64 27 // You need to implement the following functions 65 28 virtual bool OpenDevice(void); … … 79 42 void ReorderSmpteToAlsa6ch(void *buf, int frames); 80 43 template <class AudioDataType> 81 44 void _ReorderSmpteToAlsa6ch(AudioDataType *buf, int frames); 82 // Volume related83 void SetCurrentVolume(QString control, int channel, int volume);84 void OpenMixer(bool setstartingvolume);85 void CloseMixer(void);86 void SetupMixer(void);87 ALSAVolumeInfo GetVolumeRange(snd_mixer_elem_t *elem) const;88 45 89 46 private: 90 47 snd_pcm_t *pcm_handle; 91 48 int numbadioctls; 92 49 QMutex killAudioLock; 93 snd_mixer_t *mixer_handle;94 QString mixer_control; // e.g. "PCM"95 50 snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*, 96 51 snd_pcm_uframes_t); 97 52 }; -
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" … … 196 197 return gc; 197 198 } 198 199 199 static HostCheckBox *MythControlsVolume()200 {201 HostCheckBox *gc = new HostCheckBox("MythControlsVolume");202 gc->setLabel(QObject::tr("Use internal volume controls"));203 gc->setValue(true);204 gc->setHelpText(QObject::tr("MythTV can control the PCM and master "205 "mixer volume. If you prefer to control the volume externally "206 "(like your amplifier) or use an external mixer "207 "program, disable this option."));208 return gc;209 }210 211 200 static HostComboBox *MixerDevice() 212 201 { 213 202 HostComboBox *gc = new HostComboBox("MixerDevice", true); 214 203 gc->setLabel(QObject::tr("Mixer Device")); 204 gc->addSelection(QObject::tr("Disabled"), QString()); 215 205 216 #ifdef USING_OSS 217 QDir dev("/dev", "mixer*", QDir::Name, QDir::System); 218 gc->fillSelectionsFromDir(dev); 206 QHash<QString, QString> controls = VolumeControlManager::Enumerate(); 219 207 220 dev.setPath("/dev/sound");221 if (dev.exists())208 for (QHash<QString, QString>::const_iterator control = controls.begin(); 209 control != controls.end(); ++control) 222 210 { 223 gc-> fillSelectionsFromDir(dev);211 gc->addSelection(control.value(), control.key()); 224 212 } 225 #endif226 #ifdef USING_ALSA227 gc->addSelection("ALSA:default", "ALSA:default");228 #endif229 #ifdef USING_MINGW230 gc->addSelection("DirectX:", "DirectX:");231 gc->addSelection("Windows:", "Windows:");232 #endif233 #if !defined(USING_MINGW)234 gc->addSelection("software", "software");235 gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" lets MythTV control "236 "the volume of all audio at the expense of a slight quality loss."));237 #endif238 213 239 214 return gc; 240 215 } 241 216 242 static const char* MixerControlControls[] = { "PCM",243 "Master" };244 245 static HostComboBox *MixerControl()246 {247 HostComboBox *gc = new HostComboBox("MixerControl", true);248 gc->setLabel(QObject::tr("Mixer Controls"));249 for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);250 ++i)251 {252 gc->addSelection(QObject::tr(MixerControlControls[i]),253 MixerControlControls[i]);254 }255 256 gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));257 return gc;258 }259 260 static HostSlider *MixerVolume()261 {262 HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);263 gs->setLabel(QObject::tr("Master Mixer Volume"));264 gs->setValue(70);265 gs->setHelpText(QObject::tr("Initial volume for the Master Mixer. "266 "This affects all sound created by the sound card. "267 "Note: Do not set this too low."));268 return gs;269 }270 271 static HostSlider *PCMVolume()272 {273 HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);274 gs->setLabel(QObject::tr("PCM Mixer Volume"));275 gs->setValue(70);276 gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "277 "volume keys in MythTV will adjust this parameter."));278 return gs;279 }280 281 217 static HostCheckBox *IndividualMuteControl() 282 218 { 283 219 HostCheckBox *gc = new HostCheckBox("IndividualMuteControl"); … … 3490 3426 group2->addChild(AggressiveBuffer()); 3491 3427 3492 3428 return vcg; 3493 3494 3429 } 3495 3430 3496 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup 3431 static ConfigurationGroup *AudioMixerSettingsGroup() 3497 3432 { 3498 public: 3499 AudioMixerSettingsGroup() : 3500 TriggeredConfigurationGroup(false, true, false, false) 3501 { 3502 setLabel(QObject::tr("Audio Mixer")); 3503 setUseLabel(false); 3433 ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false); 3434 3435 vcg->setLabel(QObject::tr("Audio Mixer")); 3436 vcg->setUseLabel(false); 3504 3437 3505 Setting *volumeControl = MythControlsVolume(); 3506 addChild(volumeControl); 3438 vcg->addChild(MixerDevice()); 3507 3439 3508 // Mixer settings 3509 ConfigurationGroup *settings = 3510 new VerticalConfigurationGroup(false, true, false, false); 3511 settings->addChild(MixerDevice()); 3512 settings->addChild(MixerControl()); 3513 settings->addChild(MixerVolume()); 3514 settings->addChild(PCMVolume()); 3515 settings->addChild(IndividualMuteControl()); 3440 return vcg; 3441 } 3516 3442 3517 ConfigurationGroup *dummy =3518 new VerticalConfigurationGroup(false, true, false, false);3519 3520 // Show Mixer config only if internal volume controls enabled3521 setTrigger(volumeControl);3522 addTarget("0", dummy);3523 addTarget("1", settings);3524 }3525 };3526 3527 3443 static HostComboBox *MythLanguage() 3528 3444 { 3529 3445 HostComboBox *gc = new HostComboBox("Language"); … … 4207 4123 4208 4124 addChild(AudioSystemSettingsGroup()); 4209 4125 4210 addChild( newAudioMixerSettingsGroup());4126 addChild(AudioMixerSettingsGroup()); 4211 4127 4212 4128 VerticalConfigurationGroup *general = 4213 4129 new VerticalConfigurationGroup(false, true, false, false); -
mythtv/programs/mythtranscode/transcode.cpp
168 168 return last_audiotime; 169 169 } 170 170 171 virtual int GetVolumeChannel(int) const172 {173 // Do nothing174 return 100;175 }176 virtual void SetVolumeChannel(int, int)177 {178 // Do nothing179 }180 virtual void SetVolumeAll(int)181 {182 // Do nothing183 }184 virtual uint GetCurrentVolume(void) const185 {186 // Do nothing187 return 100;188 }189 virtual void SetCurrentVolume(int)190 {191 // Do nothing192 }193 virtual void AdjustCurrentVolume(int)194 {195 // Do nothing196 }197 virtual void SetMute(bool)198 {199 // Do nothing200 }201 virtual void ToggleMute(void)202 {203 // Do nothing204 }205 virtual MuteState GetMuteState(void) const206 {207 // Do nothing208 return kMuteOff;209 }210 virtual MuteState IterateMutedChannels(void)211 {212 // Do nothing213 return kMuteOff;214 }215 171 virtual bool ToggleUpmix(void) 216 172 { 217 173 // Do nothing 218 174 return false; 219 175 } 220 176 221 virtual void SetSWVolume(int new_volume, bool save)222 {223 // Do nothing224 return;225 }226 virtual int GetSWVolume(void)227 {228 // Do nothing229 return 100;230 }231 232 177 // These are pure virtual in AudioOutput, but we don't need them here 233 178 virtual void bufferOutputData(bool){ return; } 234 179 virtual int readOutputData(unsigned char*, int ){ return 0; }
