Ticket #7517: volume_control_trunk_r25745.patch
| File volume_control_trunk_r25745.patch, 134.9 KB (added by , 15 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()), … … 1180 1184 if (volume_control && gPlayer->getOutput()) 1181 1185 { 1182 1186 if (up_or_down) 1183 gPlayer-> getOutput()->AdjustCurrentVolume(2);1187 gPlayer->incVolume(); 1184 1188 else 1185 gPlayer-> getOutput()->AdjustCurrentVolume(-2);1189 gPlayer->decVolume(); 1186 1190 showVolume(true); 1187 1191 } 1188 1192 } … … 1203 1207 { 1204 1208 if (volume_control && gPlayer->getOutput()) 1205 1209 { 1206 gPlayer-> getOutput()->ToggleMute();1210 gPlayer->toggleMute(); 1207 1211 showVolume(true); 1208 1212 } 1209 1213 } … … 1245 1249 { 1246 1250 if (on_or_off) 1247 1251 { 1248 volume_status->SetUsed(gPlayer->get Output()->GetCurrentVolume());1252 volume_status->SetUsed(gPlayer->getVolume()); 1249 1253 volume_status->SetOrder(0); 1250 1254 volume_status->refresh(); 1251 1255 volume_display_timer->setSingleShot(true); … … 2463 2467 2464 2468 return time_string; 2465 2469 } 2470 2471 void PlaybackBoxMusic::VolumeChanged(int) 2472 { 2473 showVolume(true); 2474 } 2475 2476 void PlaybackBoxMusic::MuteChanged(bool) 2477 { 2478 showVolume(true); 2479 } -
mythplugins/mythmusic/mythmusic/musicplayer.h
4 4 // mythtv 5 5 #include <mythdialogs.h> 6 6 #include <audiooutput.h> 7 #include <libmyth/volumecontrolmanager.h> 7 8 #include <mythobservable.h> 8 9 9 10 // mythmusic … … 56 57 57 58 void setCDDevice(const QString &dev) { m_CDdevice = dev; } 58 59 59 void toggleMute(void); 60 MuteState getMuteState(void) const; 61 bool isMuted(void) const { return getMuteState() == kMuteAll; } 60 void toggleMute(void); 61 bool isMuted(void) const; 62 62 63 63 void setVolume(int volume); 64 64 void incVolume(void); … … 182 182 183 183 Metadata m_displayMetadata; 184 184 185 QSharedPointer<VolumeControl> volume_control; ///< Volume control interface 186 185 187 AudioOutput *m_output; 186 188 DecoderHandler *m_decoderHandler; 187 189 -
mythplugins/mythmusic/mythmusic/musicplayer.cpp
90 90 91 91 m_autoShowPlayer = (gCoreContext->GetNumSetting("MusicAutoShowPlayer", 1) > 0); 92 92 93 volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 94 93 95 gCoreContext->addListener(this); 94 96 } 95 97 … … 308 310 // TODO: Error checking that device is opened correctly! 309 311 m_output = AudioOutput::OpenAudio( 310 312 adevice, pdevice, FORMAT_S16, 2, 0, 44100, 311 AUDIOOUTPUT_MUSIC, true,false,313 AUDIOOUTPUT_MUSIC, false, 312 314 gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1); 313 315 314 316 m_output->setBufferSize(256 * 1024); … … 891 893 892 894 void MusicPlayer::incVolume() 893 895 { 894 if ( getOutput())896 if (volume_control) 895 897 { 896 getOutput()->AdjustCurrentVolume(2);898 volume_control->increaseVolume(); 897 899 sendVolumeChangedEvent(); 898 900 } 899 901 } 900 902 901 903 void MusicPlayer::decVolume() 902 904 { 903 if ( getOutput())905 if (volume_control) 904 906 { 905 getOutput()->AdjustCurrentVolume(-2);907 volume_control->decreaseVolume(); 906 908 sendVolumeChangedEvent(); 907 909 } 908 910 } 909 911 910 912 void MusicPlayer::setVolume(int volume) 911 913 { 912 if ( getOutput())914 if (volume_control) 913 915 { 914 getOutput()->SetCurrentVolume(volume);916 volume_control->setVolume(volume); 915 917 sendVolumeChangedEvent(); 916 918 } 917 919 } 918 920 919 921 uint MusicPlayer::getVolume(void) const 920 922 { 921 if ( m_output)922 return m_output->GetCurrentVolume();923 if (volume_control) 924 return volume_control->volume(); 923 925 return 0; 924 926 } 925 927 926 928 void MusicPlayer::toggleMute(void) 927 929 { 928 if ( m_output)930 if (volume_control) 929 931 { 930 m_output->ToggleMute();932 volume_control->setMute(!volume_control->mute()); 931 933 sendVolumeChangedEvent(); 932 934 } 933 935 } 934 936 935 MuteState MusicPlayer::getMuteState(void) const937 bool MusicPlayer::isMuted(void) const 936 938 { 937 if ( m_output)938 return m_output->GetMuteState();939 return kMuteAll;939 if (volume_control) 940 return volume_control->mute(); 941 return true; 940 942 } 941 943 942 944 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 … … 174 178 bool show_album_art; 175 179 bool show_whole_tree; 176 180 bool keyboard_accelerators; 177 bool volume_control;181 QSharedPointer<VolumeControl> volume_control; ///< Volume control interface 178 182 179 183 QString exit_action; 180 184 -
mythtv/configure
639 639 eval "$var=\"\$$var $*\"" 640 640 } 641 641 642 prepend(){ 643 var=$1 644 shift 645 flags_saved && eval "SAVE_$var=\"$* \$SAVE_$var\"" 646 eval "$var=\"$* \$$var\"" 647 } 648 642 649 append_uniq(){ 643 650 log append_uniq "$@" 644 651 var=$1 … … 3663 3670 { { ! enabled audio_alsa || die "ERROR: Alsa >= 1.0.16 required"; } && 3664 3671 disable audio_alsa; } 3665 3672 3673 # OSS probe 3674 if ! disabled audio_oss ; then 3675 if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h && 3676 check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3677 disable soundcard_h 3678 enable sys_soundcard_h 3679 prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include" 3680 elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h && 3681 check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3682 disable soundcard_h 3683 enable sys_soundcard_h 3684 prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include" 3685 else 3686 if enabled soundcard_h ; then 3687 check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" && 3688 enable audio_oss || 3689 disable audio_oss 3690 elif enabled sys_soundcard_h ; then 3691 check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" && 3692 enable audio_oss || 3693 disable audio_oss 3694 fi 3695 fi 3696 fi 3666 3697 3667 3698 # JACK probe 3668 3699 ! disabled audio_jack && -
mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
153 153 return 0; 154 154 } 155 155 156 NuppelVideoPlayer::NuppelVideoPlayer( bool muted)156 NuppelVideoPlayer::NuppelVideoPlayer() 157 157 : decoder(NULL), decoder_change_lock(QMutex::Recursive), 158 158 videoOutput(NULL), player_ctx(NULL), 159 159 decoderThread(NULL), playerThread(NULL), … … 213 213 // OSD stuff 214 214 osd(NULL), reinit_osd(false), 215 215 // Audio 216 audio(this , muted),216 audio(this), 217 217 // Picture-in-Picture stuff 218 218 pip_active(false), pip_visible(true), 219 219 // Filters -
mythtv/libs/libmythtv/avformatdecoder.cpp
273 273 itv(NULL), 274 274 // Audio 275 275 audioSamples(NULL), 276 internal_vol(false),277 276 disable_passthru(false), 278 277 dummy_frame(NULL), 279 278 // DVD … … 294 293 av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR); 295 294 av_log_set_callback(myth_av_log); 296 295 297 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);298 296 299 297 audioIn.sample_size = -32; // force SetupAudioStream to run once 300 298 itv = GetPlayer()->GetInteractiveTV(); … … 4436 4434 bool passthru = false; 4437 4435 4438 4436 if (ctx->codec_id == CODEC_ID_AC3) 4439 passthru = m_audio->CanAC3() && 4440 ctx->channels >= (int)m_audio->GetMaxChannels() && 4441 !internal_vol; 4437 passthru = m_audio->CanAC3(); 4442 4438 else if (ctx->codec_id == CODEC_ID_DTS) 4443 passthru = m_audio->CanDTS() && !internal_vol;4439 passthru = m_audio->CanDTS(); 4444 4440 4445 4441 passthru &= m_audio->CanPassthrough(); 4446 4442 passthru &= !transcoding && !disable_passthru; -
mythtv/libs/libmythtv/mythbdplayer.h
6 6 class MythBDPlayer : public MythPlayer 7 7 { 8 8 public: 9 MythBDPlayer(bool muted = false);10 9 virtual int GetNumChapters(void); 11 10 virtual int GetCurrentChapter(void); 12 11 virtual void GetChapterTimes(QList<long long> ×); -
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 #include "osd.h" … … 293 293 void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*); 294 294 void ClearUDPNotifyEvents(void); 295 295 296 void VolumeChanged(int volume); 297 void MuteChanged(bool mute); 298 296 299 protected: 297 300 void OSDDialogEvent(int result, QString text, QString action); 298 301 … … 495 498 496 499 vector<long long> TeardownAllPlayers(PlayerContext*); 497 500 void RestartAllPlayers(PlayerContext *lctx, 498 const vector<long long> &pos, 499 MuteState mctx_mute); 501 const vector<long long> &pos); 500 502 void RestartMainPlayer(PlayerContext *mctx); 501 503 502 504 void PxPToggleView( PlayerContext *actx, bool wantPBP); … … 708 710 /// Picture attribute to modify (on arrow left or right) 709 711 PictureAttribute adjustingPictureAttribute; 710 712 713 QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface 714 711 715 // Ask Allow state 712 716 QMap<QString,AskProgramInfo> askAllowPrograms; 713 717 QMutex askAllowLock; -
mythtv/libs/libmythtv/mythdvdplayer.h
6 6 class MythDVDPlayer : public MythPlayer 7 7 { 8 8 public: 9 MythDVDPlayer( bool muted = false);9 MythDVDPlayer(); 10 10 virtual int OpenFile(uint retries = 4, bool allow_libmpeg2 = true); 11 11 virtual void ReleaseNextVideoFrame(VideoFrame *buffer, long long timecode, 12 12 bool wrap = true); -
mythtv/libs/libmythtv/mythbdplayer.cpp
4 4 #define LOC QString("BDPlayer: ") 5 5 #define LOC_ERR QString("BDPlayer error: ") 6 6 7 MythBDPlayer::MythBDPlayer(bool muted) : MythPlayer(muted)8 {9 }10 7 11 8 int MythBDPlayer::GetNumChapters(void) 12 9 { -
mythtv/libs/libmythtv/mythplayer.h
7 7 #include <QEvent> 8 8 9 9 #include "playercontext.h" 10 #include "volumebase.h"11 10 #include "audiooutputsettings.h" 12 11 #include "RingBuffer.h" 13 12 #include "osd.h" … … 120 119 friend class DecoderThread; 121 120 122 121 public: 123 MythPlayer( bool muted = false);122 MythPlayer(); 124 123 ~MythPlayer(); 125 124 126 125 // Initialization … … 135 134 bool IsEmbedding(void); 136 135 void WindowResized(const QSize &new_size); 137 136 138 // Audio Sets139 uint AdjustVolume(int change) { return audio.AdjustVolume(change); }140 bool SetMuted(bool mute) { return audio.SetMuted(mute); }141 MuteState SetMuteState(MuteState state) { return audio.SetMuteState(state); }142 MuteState IncrMuteState(void) { return audio.IncrMuteState(); }143 144 137 // Sets 145 138 void SetPlayerInfo(TV *tv, 146 139 QWidget *widget, … … 189 182 float GetFrameRate(void) const { return video_frame_rate; } 190 183 191 184 bool IsAudioNeeded(void) { return !using_null_videoout && player_ctx->IsAudioNeeded(); } 192 uint GetVolume(void) { return audio.GetVolume(); }193 185 int GetSecondsBehind(void) const; 194 186 AspectOverrideMode GetAspectOverride(void) const; 195 187 AdjustFillMode GetAdjustFill(void) const; 196 MuteState GetMuteState(void) { return audio.GetMuteState(); }197 188 198 189 int GetFFRewSkip(void) const { return ffrew_skip; } 199 190 AudioPlayer* GetAudio(void) { return &audio; } … … 224 215 bool HasAudioOut(void) const { return audio.HasAudioOut(); } 225 216 bool IsPIPActive(void) const { return pip_active; } 226 217 bool IsPIPVisible(void) const { return pip_visible; } 227 bool IsMuted(void) { return audio.IsMuted(); }228 218 bool UsingNullVideo(void) const { return using_null_videoout; } 229 219 bool HasTVChainNext(void) const; 230 220 -
mythtv/libs/libmythtv/audioplayer.cpp
4 4 5 5 #define LOC QString("AudioPlayer: ") 6 6 7 AudioPlayer::AudioPlayer(MythPlayer *parent , bool muted)7 AudioPlayer::AudioPlayer(MythPlayer *parent) 8 8 : m_parent(parent), m_audioOutput(NULL), 9 9 m_channels(2), m_codec(0), m_format(FORMAT_NONE), 10 10 m_samplerate(44100), m_stretchfactor(1.0f), m_lock(QMutex::Recursive), 11 m_m uted_on_creation(muted), m_main_device(QString::null),11 m_main_device(QString::null), 12 12 m_passthru_device(QString::null), 13 13 no_audio_in(false), no_audio_out(false) 14 14 { … … 88 88 VERBOSE(VB_IMPORTANT, LOC + "Enabling Audio"); 89 89 no_audio_out = false; 90 90 } 91 if (m_muted_on_creation)92 {93 SetMuteState(kMuteAll);94 m_muted_on_creation = false;95 }96 91 } 97 92 98 93 if (m_audioOutput) … … 153 148 m_lock.unlock(); 154 149 } 155 150 156 uint AudioPlayer::GetVolume(void)157 {158 uint res = 0;159 m_lock.lock();160 if (m_audioOutput)161 res = m_audioOutput->GetCurrentVolume();162 m_lock.unlock();163 return res;164 }165 166 151 void AudioPlayer::SetAudioInfo(const QString &main_device, 167 152 const QString &passthru_device, 168 153 uint samplerate) … … 199 184 m_lock.unlock(); 200 185 } 201 186 202 bool AudioPlayer::SetMuted(bool mute)203 {204 QMutexLocker lock(&m_lock);205 bool is_muted = IsMuted();206 207 if (m_audioOutput && !is_muted && mute &&208 (kMuteAll == SetMuteState(kMuteAll)))209 {210 VERBOSE(VB_AUDIO, "muting sound " <<IsMuted());211 return true;212 }213 else if (m_audioOutput && is_muted && !mute &&214 (kMuteOff == SetMuteState(kMuteOff)))215 {216 VERBOSE(VB_AUDIO, "unmuting sound "<<IsMuted());217 return true;218 }219 220 VERBOSE(VB_AUDIO, "not changing sound mute state "<<IsMuted());221 222 return false;223 }224 225 MuteState AudioPlayer::SetMuteState(MuteState mstate)226 {227 QMutexLocker lock(&m_lock);228 if (m_audioOutput)229 return m_audioOutput->SetMuteState(mstate);230 return kMuteAll;231 }232 233 MuteState AudioPlayer::IncrMuteState(void)234 {235 QMutexLocker lock(&m_lock);236 MuteState mstate = kMuteAll;237 if (m_audioOutput)238 mstate = SetMuteState(VolumeBase::NextMuteState(GetMuteState()));239 return mstate;240 }241 242 MuteState AudioPlayer::GetMuteState(void)243 {244 QMutexLocker lock(&m_lock);245 if (m_audioOutput)246 return m_audioOutput->GetMuteState();247 return kMuteAll;248 }249 250 uint AudioPlayer::AdjustVolume(int change)251 {252 QMutexLocker lock(&m_lock);253 if (m_audioOutput)254 m_audioOutput->AdjustCurrentVolume(change);255 return GetVolume();256 }257 258 187 long long AudioPlayer::GetAudioTime(void) 259 188 { 260 189 long long time = 0; -
mythtv/libs/libmythtv/mythdvdplayer.cpp
8 8 #define LOC_WARN QString("DVDPlayer, Warning: ") 9 9 #define LOC_ERR QString("DVDPlayer, Error: ") 10 10 11 MythDVDPlayer::MythDVDPlayer( bool muted)12 : MythPlayer(muted),hidedvdbutton(true),11 MythDVDPlayer::MythDVDPlayer() 12 : hidedvdbutton(true), 13 13 dvd_stillframe_showing(false), need_change_dvd_track(0) 14 14 { 15 15 } -
mythtv/libs/libmythtv/playercontext.cpp
402 402 403 403 bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget, 404 404 TVState desiredState, 405 WId embedwinid, const QRect *embedbounds, 406 bool muted) 405 WId embedwinid, const QRect *embedbounds) 407 406 { 408 407 int exact_seeking = gCoreContext->GetNumSetting("ExactSeeking", 0); 409 408 … … 416 415 417 416 MythPlayer *player = NULL; 418 417 if (kState_WatchingBD == desiredState) 419 player = new MythBDPlayer( muted);418 player = new MythBDPlayer(); 420 419 else if (kState_WatchingDVD == desiredState) 421 player = new MythDVDPlayer( muted);420 player = new MythDVDPlayer(); 422 421 else 423 player = new MythPlayer( muted);422 player = new MythPlayer(); 424 423 425 424 if (nohardwaredecoders) 426 425 player->DisableHardwareDecoders(); … … 472 471 VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg); 473 472 } 474 473 } 475 else if (pipState == kPBPRight)476 player->SetMuted(true);477 474 478 475 return StartPlaying(-1); 479 476 } -
mythtv/libs/libmythtv/NuppelVideoPlayer.h
7 7 #include <QTimer> 8 8 9 9 #include "playercontext.h" 10 #include "volumebase.h"11 10 #include "audiooutputsettings.h" 12 11 #include "RingBuffer.h" 13 12 #include "osd.h" … … 121 120 friend class DecoderThread; 122 121 123 122 public: 124 NuppelVideoPlayer( bool muted = false);123 NuppelVideoPlayer(); 125 124 ~NuppelVideoPlayer(); 126 125 127 126 // Initialization … … 136 135 bool IsEmbedding(void); 137 136 void WindowResized(const QSize &new_size); 138 137 139 // Audio Sets140 uint AdjustVolume(int change) { return audio.AdjustVolume(change); }141 bool SetMuted(bool mute) { return audio.SetMuted(mute); }142 MuteState SetMuteState(MuteState state) { return audio.SetMuteState(state); }143 MuteState IncrMuteState(void) { return audio.IncrMuteState(); }144 145 138 // Sets 146 139 void SetPlayerInfo(TV *tv, 147 140 QWidget *widget, … … 190 183 float GetFrameRate(void) const { return video_frame_rate; } 191 184 192 185 bool IsAudioNeeded(void) { return !using_null_videoout && player_ctx->IsAudioNeeded(); } 193 uint GetVolume(void) { return audio.GetVolume(); }194 186 int GetSecondsBehind(void) const; 195 187 AspectOverrideMode GetAspectOverride(void) const; 196 188 AdjustFillMode GetAdjustFill(void) const; 197 MuteState GetMuteState(void) { return audio.GetMuteState(); }198 189 199 190 int GetFFRewSkip(void) const { return ffrew_skip; } 200 191 AudioPlayer* GetAudio(void) { return &audio; } … … 225 216 bool HasAudioOut(void) const { return audio.HasAudioOut(); } 226 217 bool IsPIPActive(void) const { return pip_active; } 227 218 bool IsPIPVisible(void) const { return pip_visible; } 228 bool IsMuted(void) { return audio.IsMuted(); }229 219 bool UsingNullVideo(void) const { return using_null_videoout; } 230 220 bool HasTVChainNext(void) const; 231 221 -
mythtv/libs/libmythtv/tv_play.cpp
1050 1050 1051 1051 gCoreContext->addListener(this); 1052 1052 1053 volumeControl = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 1054 if (volumeControl) 1055 { 1056 connect(volumeControl.data(), SIGNAL(changedVolume(int)), 1057 this, SLOT(VolumeChanged(int)), Qt::QueuedConnection); 1058 connect(volumeControl.data(), SIGNAL(changedMute(bool)), 1059 this, SLOT(MuteChanged(bool)), Qt::QueuedConnection); 1060 } 1061 1062 VERBOSE(VB_PLAYBACK, LOC + "ctor -- end"); 1063 1053 1064 QMutexLocker lock(&initFromDBLock); 1054 1065 initFromDBDone = true; 1055 1066 initFromDBWait.wakeAll(); … … 4645 4656 if (!ok) 4646 4657 return; 4647 4658 4648 if ( 0 <= vol && vol <= 100 )4659 if ( 0 <= vol && vol <= 100 && volumeControl) 4649 4660 { 4650 ctx->LockDeletePlayer(__FILE__, __LINE__); 4651 if (!ctx->player) 4652 { 4653 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 4654 return; 4655 } 4656 4657 vol -= ctx->player->GetVolume(); 4658 vol = ctx->player->AdjustVolume(vol); 4659 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 4660 4661 if (!browsemode && !editmode) 4662 { 4663 UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"), 4664 QString::number(vol), 4665 kOSDFunctionalType_PictureAdjust, "%", vol * 10, 4666 kOSDTimeout_Med); 4667 SetUpdateOSDPosition(false); 4668 } 4661 volumeControl->setVolume(vol); 4669 4662 } 4670 4663 } 4671 4664 } … … 4758 4751 } 4759 4752 else if (tokens[2] == "VOLUME") 4760 4753 { 4761 QString infoStr = QString("%1%").arg(ctx->player->GetVolume()); 4754 QString infoStr = QString("%1%") 4755 .arg(volumeControl ? volumeControl->volume() : 0); 4762 4756 4763 4757 QString message = QString("NETWORK_CONTROL ANSWER %1") 4764 4758 .arg(infoStr); … … 5189 5183 } 5190 5184 } 5191 5185 5192 MuteState mctx_mute = kMuteOff;5193 mctx->LockDeletePlayer(__FILE__, __LINE__);5194 if (mctx->player)5195 mctx_mute = mctx->player->GetMuteState();5196 mctx->UnlockDeletePlayer(__FILE__, __LINE__);5197 5198 5186 vector<long long> pos = TeardownAllPlayers(mctx); 5199 5187 5200 5188 if (wantPBP) … … 5212 5200 } 5213 5201 } 5214 5202 5215 RestartAllPlayers(mctx, pos , mctx_mute);5203 RestartAllPlayers(mctx, pos); 5216 5204 5217 5205 VERBOSE(VB_PLAYBACK, LOC + 5218 5206 QString("PxPToggleType() converting from %1 to %2 -- end") … … 5356 5344 * \brief Recreate Main and PIP windows. Could be either PIP or PBP views. 5357 5345 */ 5358 5346 void TV::RestartAllPlayers(PlayerContext *lctx, 5359 const vector<long long> &pos, 5360 MuteState mctx_mute) 5347 const vector<long long> &pos) 5361 5348 { 5362 5349 QString loc = LOC + QString("RestartAllPlayers(): "); 5363 5350 … … 5404 5391 pipctx->LockDeletePlayer(__FILE__, __LINE__); 5405 5392 if (pipctx->player) 5406 5393 { 5407 pipctx->player->SetMuted(true);5408 5394 pipctx->player->JumpToFrame(pos[i]); 5409 5395 } 5410 5396 pipctx->UnlockDeletePlayer(__FILE__, __LINE__); … … 5416 5402 ForceNextStateNone(pipctx); 5417 5403 } 5418 5404 } 5419 5420 // If old main player had a kMuteAll | kMuteOff setting,5421 // apply old main player's mute setting to new main player.5422 mctx->LockDeletePlayer(__FILE__, __LINE__);5423 if (mctx->player && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))5424 mctx->player->SetMuteState(mctx_mute);5425 mctx->UnlockDeletePlayer(__FILE__, __LINE__);5426 5405 } 5427 5406 5428 5407 void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx) … … 5450 5429 return; 5451 5430 } 5452 5431 5453 MuteState mctx_mute = mctx->player->GetMuteState();5454 5432 mctx->deletePlayerLock.unlock(); 5455 5433 pipctx->deletePlayerLock.unlock(); 5456 5434 … … 5464 5442 playerActive = (ctx_index == playerActive) ? 5465 5443 0 : ((ctx_index == 0) ? ctx_index : playerActive); 5466 5444 5467 RestartAllPlayers(mctx, pos , mctx_mute);5445 RestartAllPlayers(mctx, pos); 5468 5446 5469 5447 SetActive(mctx, playerActive, false); 5470 5448 … … 5485 5463 mctx->deletePlayerLock.unlock(); 5486 5464 return; 5487 5465 } 5488 5489 MuteState mctx_mute = mctx->player->GetMuteState();5490 5491 // HACK - FIXME5492 // workaround muted audio when Player is re-created5493 mctx_mute = kMuteOff;5494 // FIXME - end5495 5466 mctx->deletePlayerLock.unlock(); 5496 5467 5497 5468 vector<long long> pos = TeardownAllPlayers(mctx); 5498 RestartAllPlayers(mctx, pos , mctx_mute);5469 RestartAllPlayers(mctx, pos); 5499 5470 SetActive(mctx, playerActive, false); 5500 5471 5501 5472 VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end"); … … 6316 6287 if (mctx != ctx) 6317 6288 PIPRemovePlayer(mctx, ctx); 6318 6289 6319 bool muted = false;6320 ctx->LockDeletePlayer(__FILE__, __LINE__);6321 if (ctx->player && ctx->player->IsMuted())6322 muted = true;6323 ctx->UnlockDeletePlayer(__FILE__, __LINE__);6324 6325 6290 // pause the decoder first, so we're not reading too close to the end. 6326 6291 ctx->buffer->IgnoreLiveEOF(true); 6327 6292 ctx->buffer->StopReads(); … … 6373 6338 6374 6339 if (ctx->CreatePlayer( 6375 6340 this, GetMythMainWindow(), ctx->GetState(), 6376 mctx->embedWinID, &mctx->embedBounds , muted))6341 mctx->embedWinID, &mctx->embedBounds)) 6377 6342 { 6378 6343 ScheduleStateChange(ctx); 6379 6344 ok = true; … … 7935 7900 7936 7901 void TV::ChangeVolume(PlayerContext *ctx, bool up) 7937 7902 { 7938 ctx->LockDeletePlayer(__FILE__, __LINE__); 7939 if (!ctx->player) 7903 if (volumeControl) 7940 7904 { 7941 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 7942 return; 7905 if (up) 7906 volumeControl->increaseVolume(); 7907 else 7908 volumeControl->decreaseVolume(); 7943 7909 } 7944 uint curvol = ctx->player->AdjustVolume((up) ? +2 : -2);7945 ctx->UnlockDeletePlayer(__FILE__, __LINE__);7946 7947 if (!browsemode)7948 {7949 UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"),7950 QString::number(curvol),7951 kOSDFunctionalType_PictureAdjust, "%", curvol * 10,7952 kOSDTimeout_Med);7953 SetUpdateOSDPosition(false);7954 }7955 7910 } 7956 7911 7957 7912 void TV::ToggleTimeStretch(PlayerContext *ctx) … … 8094 8049 8095 8050 void TV::ToggleMute(PlayerContext *ctx, const bool muteIndividualChannels) 8096 8051 { 8097 ctx->LockDeletePlayer(__FILE__, __LINE__); 8098 if (!ctx->player || !ctx->player->HasAudioOut()) 8099 { 8100 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 8101 return; 8102 } 8103 8104 MuteState mute_status; 8105 8106 if (!muteIndividualChannels) 8107 { 8108 ctx->player->SetMuted(!ctx->player->IsMuted()); 8109 mute_status = (ctx->player->IsMuted()) ? kMuteAll : kMuteOff; 8110 } 8111 else 8112 { 8113 mute_status = ctx->player->IncrMuteState(); 8114 } 8115 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 8116 8117 QString text; 8118 8119 switch (mute_status) 8120 { 8121 case kMuteOff: text = tr("Mute Off"); break; 8122 case kMuteAll: text = tr("Mute On"); break; 8123 case kMuteLeft: text = tr("Left Channel Muted"); break; 8124 case kMuteRight: text = tr("Right Channel Muted"); break; 8125 } 8126 8127 SetOSDMessage(ctx, text); 8052 if (volumeControl) 8053 volumeControl->setMute(!volumeControl->mute()); 8128 8054 } 8129 8055 8130 8056 void TV::ToggleSleepTimer(const PlayerContext *ctx) … … 9084 9010 { 9085 9011 value = ctx->player->getVideoOutput()->GetPictureAttribute(attr); 9086 9012 } 9087 else if (ctx->player->HasAudioOut() )9013 else if (ctx->player->HasAudioOut() && volumeControl) 9088 9014 { 9089 value = ctx->player->GetVolume();9015 value = volumeControl->volume(); 9090 9016 title = tr("Adjust Volume"); 9091 9017 } 9092 9018 } … … 11964 11890 ReturnPlayerLock(mctx); 11965 11891 } 11966 11892 11893 void TV::VolumeChanged(int volume) 11894 { 11895 if (!browsemode) 11896 { 11897 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 11898 UpdateOSDStatus(actx, tr("Adjust Volume"), tr("Volume"), 11899 QString::number(volume), 11900 kOSDFunctionalType_PictureAdjust, "%", 10 * volume); 11901 SetUpdateOSDPosition(false); 11902 ReturnPlayerLock(actx); 11903 } 11904 } 11905 11906 void TV::MuteChanged(bool mute) 11907 { 11908 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 11909 SetOSDMessage(actx, mute ? tr("Mute On") : tr("Mute Off")); 11910 ReturnPlayerLock(actx); 11911 } 11912 11913 11967 11914 OSD *TV::GetOSDL(const char *file, int location) 11968 11915 { 11969 11916 PlayerContext *actx = GetPlayerReadLock(-1, file, location); -
mythtv/libs/libmythtv/playercontext.h
68 68 // Actions 69 69 bool CreatePlayer(TV *tv, QWidget *widget, 70 70 TVState desiredState, 71 WId embedwinid, const QRect *embedBounds, 72 bool muted = false); 71 WId embedwinid, const QRect *embedBounds); 73 72 void TeardownPlayer(void); 74 73 bool StartPlaying(int maxWait = -1); 75 74 void StopPlaying(void); -
mythtv/libs/libmythtv/mythplayer.cpp
157 157 return 0; 158 158 } 159 159 160 MythPlayer::MythPlayer( bool muted)160 MythPlayer::MythPlayer() 161 161 : decoder(NULL), decoder_change_lock(QMutex::Recursive), 162 162 videoOutput(NULL), player_ctx(NULL), 163 163 decoderThread(NULL), playerThread(NULL), … … 217 217 // OSD stuff 218 218 osd(NULL), reinit_osd(false), 219 219 // Audio 220 audio(this , muted),220 audio(this), 221 221 // Picture-in-Picture stuff 222 222 pip_active(false), pip_visible(true), 223 223 // Filters -
mythtv/libs/libmythtv/avformatdecoder.h
303 303 304 304 // Audio 305 305 short int *audioSamples; 306 bool internal_vol;307 306 bool disable_passthru; 308 307 309 308 VideoFrame *dummy_frame; -
mythtv/libs/libmythtv/mythcommflagplayer.h
6 6 class MPUBLIC MythCommFlagPlayer : public MythPlayer 7 7 { 8 8 public: 9 MythCommFlagPlayer(bool muted = false) : MythPlayer(muted) { }10 9 bool RebuildSeekTable(bool showPercentage = true, StatusCallback cb = NULL, 11 10 void* cbData = NULL); 12 11 }; -
mythtv/libs/libmythtv/audioplayer.h
7 7 class MPUBLIC AudioPlayer 8 8 { 9 9 public: 10 AudioPlayer(MythPlayer *parent , bool muted);10 AudioPlayer(MythPlayer *parent); 11 11 ~AudioPlayer(); 12 12 13 13 void Reset(void); … … 29 29 bool Pause(bool pause); 30 30 bool IsPaused(void); 31 31 void PauseAudioUntilBuffered(void); 32 uint GetVolume(void);33 uint AdjustVolume(int change);34 32 float GetStretchFactor(void) { return m_stretchfactor; } 35 33 void SetStretchFactor(float factor); 36 34 bool ToggleUpmix(void); … … 40 38 uint GetMaxChannels(void); 41 39 long long GetAudioTime(void); 42 40 43 bool IsMuted(void) { return GetMuteState() == kMuteAll; }44 bool SetMuted(bool mute);45 MuteState GetMuteState(void);46 MuteState SetMuteState(MuteState);47 MuteState IncrMuteState(void);48 49 41 void AddAudioData(char *buffer, int len, long long timecode); 50 42 bool GetBufferStatus(uint &fill, uint &total); 51 43 … … 59 51 float m_stretchfactor; 60 52 bool m_passthru; 61 53 QMutex m_lock; 62 bool m_muted_on_creation;63 54 QString m_main_device; 64 55 QString m_passthru_device; 65 56 bool no_audio_in; -
mythtv/libs/libmyth/audiooutputwin.cpp
278 278 return m_nPkts * fragment_size; 279 279 } 280 280 281 int AudioOutputWin::GetVolumeChannel(int channel) const282 {283 DWORD dwVolume = 0xffffffff;284 int Volume = 100;285 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))286 {287 Volume = (channel == 0) ?288 (LOWORD(dwVolume) / (0xffff / 100)) :289 (HIWORD(dwVolume) / (0xffff / 100));290 }291 292 VERBOSE(VB_AUDIO, QString("GetVolume(%1) %2 (%3)")293 .arg(channel).arg(Volume).arg(dwVolume));294 295 return Volume;296 }297 298 void AudioOutputWin::SetVolumeChannel(int channel, int volume)299 {300 if (channel > 1)301 VBERROR("Windows volume only supports stereo!");302 303 DWORD dwVolume = 0xffffffff;304 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))305 {306 if (channel == 0)307 dwVolume = dwVolume & 0xffff0000 | volume * (0xffff / 100);308 else309 dwVolume = dwVolume & 0xffff | ((volume * (0xffff / 100)) << 16);310 }311 else312 {313 dwVolume = volume * (0xffff / 100);314 dwVolume |= (dwVolume << 16);315 }316 317 VBAUDIO(QString("SetVolume(%1) %2(%3)")318 .arg(channel).arg(volume).arg(dwVolume));319 320 waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, dwVolume);321 } -
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 #define VBAUDIO(str) VERBOSE(VB_AUDIO, LOC + str) 23 24 #define VBAUDIOTS(str) VERBOSE(VB_AUDIO+VB_TIMESTAMP, LOC + str) … … 55 56 56 57 virtual void Reset(void); 57 58 58 void SetSWVolume(int new_volume, bool save);59 int GetSWVolume(void);60 61 59 // timecode is in milliseconds. 62 60 virtual bool AddFrames(void *buffer, int frames, long long timecode); 63 61 … … 147 145 bool killaudio; 148 146 149 147 bool pauseaudio, actually_paused, was_paused, unpause_when_ready; 150 bool set_initial_vol;151 148 bool buffer_output_data_for_use; // used by AudioOutputNULL 152 149 153 150 int configured_channels; … … 172 169 bool needs_downmix; 173 170 int surround_mode; 174 171 float old_stretchfactor; 175 int volume;172 QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface 176 173 QString volumeControl; 177 174 178 175 bool processing; -
mythtv/libs/libmyth/audiooutputalsa.cpp
1 #include "audiooutputalsa.h" 2 1 3 #include <cstdio> 2 4 #include <cstdlib> 3 5 #include <sys/time.h> … … 8 10 9 11 #include <QFile> 10 12 #include "mythcorecontext.h" 11 #include "audiooutputalsa.h"12 13 13 14 #define LOC QString("ALSA: ") 14 15 #define LOC_WARN QString("ALSA, Warning: ") … … 40 41 m_device(-1), 41 42 m_subdevice(-1) 42 43 { 43 m_mixer.handle = NULL;44 m_mixer.elem = NULL;45 46 44 // Set everything up 47 45 InitSettings(settings); 48 46 if (settings.init) … … 432 430 return OpenDevice(); 433 431 } 434 432 435 if (internal_vol && !OpenMixer())436 VBERROR("Unable to open audio mixer. Volume control disabled");437 438 433 // Device opened successfully 439 434 return true; 440 435 } 441 436 442 437 void AudioOutputALSA::CloseDevice() 443 438 { 444 if (m_mixer.handle)445 snd_mixer_close(m_mixer.handle);446 m_mixer.handle = NULL;447 439 if (pcm_handle) 448 440 { 449 441 snd_pcm_close(pcm_handle); … … 711 703 return 0; 712 704 } 713 705 714 int AudioOutputALSA::GetVolumeChannel(int channel) const715 {716 int retvol = 0;717 718 if (!m_mixer.elem)719 return retvol;720 721 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;722 if (!snd_mixer_selem_has_playback_channel(m_mixer.elem, chan))723 return retvol;724 725 long mixervol;726 int chk;727 if ((chk = snd_mixer_selem_get_playback_volume(m_mixer.elem,728 chan,729 &mixervol)) < 0)730 {731 VBERROR(QString("failed to get channel %1 volume, mixer %2/%3: %4")732 .arg(channel).arg(m_mixer.device)733 .arg(m_mixer.control)734 .arg(snd_strerror(chk)));735 }736 else737 {738 retvol = (m_mixer.volrange != 0L) ? (mixervol - m_mixer.volmin) *739 100.0f / m_mixer.volrange + 0.5f740 : 0;741 retvol = max(retvol, 0);742 retvol = min(retvol, 100);743 VBAUDIO(QString("get volume channel %1: %2")744 .arg(channel).arg(retvol));745 }746 return retvol;747 }748 749 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)750 {751 if (!(internal_vol && m_mixer.elem))752 return;753 754 long mixervol = volume * m_mixer.volrange / 100.0f - m_mixer.volmin + 0.5f;755 mixervol = max(mixervol, m_mixer.volmin);756 mixervol = min(mixervol, m_mixer.volmax);757 758 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;759 if (snd_mixer_selem_set_playback_volume(m_mixer.elem, chan, mixervol) < 0)760 VBERROR(QString("failed to set channel %1 volume").arg(channel));761 else762 VBAUDIO(QString("channel %1 volume set %2 => %3")763 .arg(channel).arg(volume).arg(mixervol));764 }765 766 bool AudioOutputALSA::OpenMixer(void)767 {768 if (!pcm_handle)769 {770 VBERROR("mixer setup without a pcm");771 return false;772 }773 m_mixer.device = gCoreContext->GetSetting("MixerDevice", "default");774 m_mixer.device = m_mixer.device.remove(QString("ALSA:"));775 if (m_mixer.device.toLower() == "software")776 return true;777 778 m_mixer.control = gCoreContext->GetSetting("MixerControl", "PCM");779 780 QString mixer_device_tag = QString("mixer device %1").arg(m_mixer.device);781 782 int chk;783 if ((chk = snd_mixer_open(&m_mixer.handle, 0)) < 0)784 {785 VBERROR(QString("failed to open mixer device %1: %2")786 .arg(mixer_device_tag).arg(snd_strerror(chk)));787 return false;788 }789 790 QByteArray dev_ba = m_mixer.device.toAscii();791 struct snd_mixer_selem_regopt regopts =792 {1, SND_MIXER_SABSTRACT_NONE, dev_ba.constData(), NULL, NULL};793 794 if ((chk = snd_mixer_selem_register(m_mixer.handle, ®opts, NULL)) < 0)795 {796 snd_mixer_close(m_mixer.handle);797 m_mixer.handle = NULL;798 VBERROR(QString("failed to register %1: %2")799 .arg(mixer_device_tag).arg(snd_strerror(chk)));800 return false;801 }802 803 if ((chk = snd_mixer_load(m_mixer.handle)) < 0)804 {805 snd_mixer_close(m_mixer.handle);806 m_mixer.handle = NULL;807 VBERROR(QString("failed to load %1: %2")808 .arg(mixer_device_tag).arg(snd_strerror(chk)));809 return false;810 }811 812 m_mixer.elem = NULL;813 uint elcount = snd_mixer_get_count(m_mixer.handle);814 snd_mixer_elem_t* elx = snd_mixer_first_elem(m_mixer.handle);815 816 for (uint ctr = 0; elx != NULL && ctr < elcount; ctr++)817 {818 QString tmp = QString(snd_mixer_selem_get_name(elx));819 if (m_mixer.control == tmp &&820 !snd_mixer_selem_is_enumerated(elx) &&821 snd_mixer_selem_has_playback_volume(elx) &&822 snd_mixer_selem_is_active(elx))823 {824 m_mixer.elem = elx;825 VBAUDIO(QString("found playback control %1 on %2")826 .arg(m_mixer.control)827 .arg(mixer_device_tag));828 break;829 }830 elx = snd_mixer_elem_next(elx);831 }832 if (!m_mixer.elem)833 {834 snd_mixer_close(m_mixer.handle);835 m_mixer.handle = NULL;836 VBERROR(QString("no playback control %1 found on %2")837 .arg(m_mixer.control).arg(mixer_device_tag));838 return false;839 }840 if ((snd_mixer_selem_get_playback_volume_range(m_mixer.elem,841 &m_mixer.volmin,842 &m_mixer.volmax) < 0))843 {844 snd_mixer_close(m_mixer.handle);845 m_mixer.handle = NULL;846 VBERROR(QString("failed to get volume range on %1/%2")847 .arg(mixer_device_tag).arg(m_mixer.control));848 return false;849 }850 851 m_mixer.volrange = m_mixer.volmax - m_mixer.volmin;852 VBAUDIO(QString("mixer volume range on %1/%2 - min %3, max %4, range %5")853 .arg(mixer_device_tag).arg(m_mixer.control)854 .arg(m_mixer.volmin).arg(m_mixer.volmax).arg(m_mixer.volrange));855 VBAUDIO(QString("%1/%2 set up successfully")856 .arg(mixer_device_tag)857 .arg(m_mixer.control));858 859 if (set_initial_vol)860 {861 int initial_vol;862 if (m_mixer.control == "PCM")863 initial_vol = gCoreContext->GetNumSetting("PCMMixerVolume", 80);864 else865 initial_vol = gCoreContext->GetNumSetting("MasterMixerVolume", 80);866 for (int ch = 0; ch < channels; ++ch)867 SetVolumeChannel(ch, initial_vol);868 }869 870 return true;871 }872 873 706 QMap<QString, QString> *AudioOutputALSA::GetALSADevices(const char *type) 874 707 { 875 708 QMap<QString, QString> *alsadevs = new QMap<QString, QString>(); -
mythtv/libs/libmyth/volumebase.cpp
1 #include <cstdio>2 #include <cstdlib>3 4 #include <algorithm>5 using namespace std;6 7 #include <QString>8 9 #include "volumebase.h"10 #include "mythcorecontext.h"11 12 VolumeBase::VolumeBase() :13 internal_vol(false), volume(80),14 current_mute_state(kMuteOff)15 {16 swvol = swvol_setting =17 (gCoreContext->GetSetting("MixerDevice", "default").toLower() == "software");18 }19 20 bool VolumeBase::SWVolume(void)21 {22 return swvol;23 }24 25 void VolumeBase::SWVolume(bool set)26 {27 if (swvol_setting)28 return;29 swvol = set;30 }31 32 uint VolumeBase::GetCurrentVolume(void) const33 {34 return volume;35 }36 37 void VolumeBase::SetCurrentVolume(int value)38 {39 volume = max(min(value, 100), 0);40 UpdateVolume();41 42 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");43 controlLabel += "MixerVolume";44 gCoreContext->SaveSetting(controlLabel, volume);45 }46 47 void VolumeBase::AdjustCurrentVolume(int change)48 {49 SetCurrentVolume(volume + change);50 }51 52 MuteState VolumeBase::SetMuteState(MuteState mstate)53 {54 current_mute_state = mstate;55 UpdateVolume();56 return current_mute_state;57 }58 59 void VolumeBase::ToggleMute(void)60 {61 bool is_muted = GetMuteState() == kMuteAll;62 SetMuteState((is_muted) ? kMuteOff : kMuteAll);63 }64 65 MuteState VolumeBase::GetMuteState(void) const66 {67 return current_mute_state;68 }69 70 MuteState VolumeBase::NextMuteState(MuteState cur)71 {72 MuteState next = cur;73 74 switch (cur)75 {76 case kMuteOff:77 next = kMuteLeft;78 break;79 case kMuteLeft:80 next = kMuteRight;81 break;82 case kMuteRight:83 next = kMuteAll;84 break;85 case kMuteAll:86 next = kMuteOff;87 break;88 }89 90 return (next);91 }92 93 void VolumeBase::UpdateVolume(void)94 {95 int new_volume = volume;96 bool save = true;97 if (current_mute_state == kMuteAll)98 {99 new_volume = 0;100 save = false;101 }102 103 if (swvol)104 {105 SetSWVolume(new_volume, save);106 return;107 }108 109 for (int i = 0; i < channels; i++)110 {111 SetVolumeChannel(i, new_volume);112 }113 114 // Individual channel muting is handled in GetAudioData,115 // this code demonstrates the old method.116 // if (current_mute_state == kMuteLeft)117 // {118 // SetVolumeChannel(0, 0);119 // }120 // else if (current_mute_state == kMuteRight)121 // {122 // SetVolumeChannel(1, 0);123 // }124 }125 126 void VolumeBase::SyncVolume(void)127 {128 // Read the volume from the audio driver and setup our internal state to match129 if (swvol)130 volume = GetSWVolume();131 else132 volume = GetVolumeChannel(0);133 }134 135 void VolumeBase::SetChannels(int new_channels)136 {137 channels = new_channels;138 } -
mythtv/libs/libmyth/volumecontrolcoreaudio.h
1 #ifndef VOLUMECONTROLCOREAUDIO 2 #define VOLUMECONTROLCOREAUDIO 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QAtomicInt> 8 #include <CoreAudio/CoreAudio.h> 9 10 11 class VolumeControlCoreAudio : public VolumeControl 12 { 13 public: 14 static QHash<QString, QString> Enumerate(); 15 16 public: 17 VolumeControlCoreAudio(QString device); 18 virtual ~VolumeControlCoreAudio(); 19 20 public: 21 int volume() const; 22 void setVolume(int volume); 23 void increaseVolume(); 24 void decreaseVolume(); 25 26 bool mute() const; 27 void setMute(bool mute); 28 29 protected: 30 static OSStatus event(AudioDeviceID deviceId, UInt32 channel, 31 Boolean input, AudioDevicePropertyID property, 32 void* context); 33 34 private: 35 AudioDeviceID m_DeviceId; //< Core Audio device ID 36 QAtomicInt m_Volume; //< Volume state cache 37 QAtomicInt m_Mute; //< Mute state cache 38 }; 39 40 #endif // VOLUMECONTROLCOREAUDIO -
mythtv/libs/libmyth/volumecontrolsoftware.h
1 #ifndef VOLUMECONTROLSOFTWARE 2 #define VOLUMECONTROLSOFTWARE 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QAtomicInt> 8 9 10 class VolumeControlSoftware : public VolumeControl 11 { 12 public: 13 static QHash<QString, QString> Enumerate(); 14 15 public: 16 VolumeControlSoftware(QString device); 17 virtual ~VolumeControlSoftware(); 18 19 public: 20 int volume() const; 21 void setVolume(int volume); 22 void increaseVolume(); 23 void decreaseVolume(); 24 25 bool mute() const; 26 void setMute(bool mute); 27 28 private: 29 static QAtomicInt m_Volume; //< Volume state cache 30 static QAtomicInt m_Mute; //< Mute state cache 31 }; 32 33 #endif // VOLUMECONTROLSOFTWARE -
mythtv/libs/libmyth/volumecontrolcoreaudio.cpp
1 #include "volumecontrolcoreaudio.h" 2 3 #include <CoreServices/CoreServices.h> 4 #include <CoreAudio/CoreAudio.h> 5 6 #include "mythverbose.h" 7 #include <algorithm> 8 9 // static 10 QHash<QString, QString> VolumeControlCoreAudio::Enumerate() 11 { 12 QHash<QString, QString> result; 13 14 result.insert("CoreAudio:default", "Default Core Audio device"); 15 16 UInt32 size; 17 AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, 18 &size, NULL); 19 UInt32 count = size / sizeof(AudioDeviceID); 20 21 AudioDeviceID* devices = new AudioDeviceID[count]; 22 AudioHardwareGetProperty(kAudioHardwarePropertyDevices, 23 &size, devices); 24 25 for (unsigned int index = 0; index < count; ++index) 26 { 27 bool output = false; 28 29 AudioDeviceGetPropertyInfo(devices[index], 0, 0, 30 kAudioDevicePropertyStreamConfiguration, 31 &size, NULL); 32 if (!size) 33 continue; 34 35 AudioBufferList* buffers = static_cast<AudioBufferList*>(malloc(size)); 36 AudioDeviceGetProperty(devices[index], 0, 0, 37 kAudioDevicePropertyStreamConfiguration, 38 &size, buffers); 39 for (UInt32 buffer = 0; buffer < buffers->mNumberBuffers; ++buffer) 40 { 41 if (buffers->mBuffers[buffer].mNumberChannels) 42 { 43 output = true; 44 break; 45 } 46 } 47 48 free(buffers); 49 50 if (!output) 51 continue; 52 53 QString uid; 54 CFStringRef uidcf; 55 size = sizeof(CFStringRef); 56 AudioDeviceGetProperty(devices[index], 0, 0, 57 kAudioDevicePropertyDeviceUID, 58 &size, &uidcf); 59 if (uidcf) 60 { 61 char buffer[256]; 62 CFStringGetCString(uidcf, buffer, 256, 63 CFStringGetFastestEncoding(uidcf)); 64 uid = QString(buffer); 65 CFRelease(uidcf); 66 } 67 68 AudioDeviceGetPropertyInfo(devices[index], 0, 0, 69 kAudioDevicePropertyDeviceName, 70 &size, NULL); 71 if (!size) 72 continue; 73 74 char* name = static_cast<char*>(malloc(size)); 75 AudioDeviceGetProperty(devices[index], 0, 0, 76 kAudioDevicePropertyDeviceName, 77 &size, name); 78 79 result.insert(QString("CoreAudio:") + uid, name); 80 81 free(name); 82 } 83 84 delete devices; 85 86 return result; 87 } 88 89 VolumeControlCoreAudio::VolumeControlCoreAudio(QString device) : 90 m_DeviceId(kAudioDeviceUnknown) 91 { 92 if (device == QString("default")) 93 { 94 UInt32 size = sizeof(AudioDeviceID); 95 AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, 96 &size, &m_DeviceId); 97 } 98 else 99 { 100 CFStringRef cfString = 101 CFStringCreateWithCharacters(kCFAllocatorDefault, 102 reinterpret_cast<const UniChar*>(device.unicode()), 103 device.length()); 104 105 AudioValueTranslation translateUidToId = { 106 mInputData: &cfString, 107 mInputDataSize: sizeof(CFStringRef), 108 mOutputData: &m_DeviceId, 109 mOutputDataSize: sizeof(AudioDeviceID) 110 }; 111 112 UInt32 translateUidToIdSize = sizeof(AudioValueTranslation); 113 AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, 114 &translateUidToIdSize, 115 &translateUidToId); 116 CFRelease(cfString); 117 } 118 119 AudioDeviceAddPropertyListener(m_DeviceId, 1, false, 120 kAudioDevicePropertyVolumeScalar, 121 &event, 122 this); 123 124 AudioDeviceAddPropertyListener(m_DeviceId, 1, false, 125 kAudioDevicePropertyVolumeDecibels, 126 &event, 127 this); 128 129 AudioDeviceAddPropertyListener(m_DeviceId, 0, false, 130 kAudioDevicePropertyMute, 131 &event, 132 this); 133 134 m_Volume = volume(); 135 m_Mute = mute(); 136 } 137 138 VolumeControlCoreAudio::~VolumeControlCoreAudio() 139 { 140 AudioDeviceRemovePropertyListener(m_DeviceId, 1, false, 141 kAudioDevicePropertyVolumeScalar, 142 &event); 143 144 AudioDeviceRemovePropertyListener(m_DeviceId, 1, false, 145 kAudioDevicePropertyVolumeDecibels, 146 &event); 147 148 AudioDeviceRemovePropertyListener(m_DeviceId, 0, false, 149 kAudioDevicePropertyMute, 150 &event); 151 } 152 153 int VolumeControlCoreAudio::volume() const 154 { 155 Float32 volume = 0; 156 157 if (!mute()) 158 { 159 UInt32 size = sizeof(Float32); 160 AudioDeviceGetProperty(m_DeviceId, 1, false, 161 kAudioDevicePropertyVolumeScalar, 162 &size, &volume); 163 } 164 else 165 volume = static_cast<Float32>(m_Volume) / 100.0f; 166 167 VERBOSE(VB_AUDIO, 168 QString("VolumeControlCoreAudio::volume() = %1") 169 .arg(static_cast<int>(100.0f * volume))); 170 171 return static_cast<int>(100.0f * volume); 172 } 173 174 void VolumeControlCoreAudio::setVolume(int volume) 175 { 176 VERBOSE(VB_AUDIO, 177 QString("VolumeControlCoreAudio::setVolume(%1)") 178 .arg(volume)); 179 180 volume = std::min(std::max(0, volume), 100); 181 182 if (mute() && volume > VolumeControlCoreAudio::volume()) 183 setMute(false); 184 185 if (!mute()) 186 { 187 Float32 value = static_cast<Float32>(volume) / 100.0f; 188 AudioDeviceSetProperty(m_DeviceId, NULL, 1, false, 189 kAudioDevicePropertyVolumeScalar, 190 sizeof(UInt32), &value); 191 } 192 193 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 194 emit changedVolume(volume); 195 } 196 197 void VolumeControlCoreAudio::increaseVolume() 198 { 199 setVolume(volume() + 10); 200 } 201 202 void VolumeControlCoreAudio::decreaseVolume() 203 { 204 setVolume(volume() - 10); 205 } 206 207 bool VolumeControlCoreAudio::mute() const 208 { 209 UInt32 mute = false; 210 211 UInt32 size = sizeof(UInt32); 212 AudioDeviceGetProperty(m_DeviceId, 0, false, 213 kAudioDevicePropertyMute, &size, &mute); 214 215 VERBOSE(VB_AUDIO, 216 QString("VolumeControlCoreAudio::mute() = %1") 217 .arg(mute ? "mute" : "unmute")); 218 219 return mute; 220 } 221 222 void VolumeControlCoreAudio::setMute(bool mute) 223 { 224 VERBOSE(VB_AUDIO, 225 QString("VolumeControlCoreAudio::setMute(%1)") 226 .arg(mute ? "mute" : "unmute")); 227 228 if (VolumeControlCoreAudio::mute()) 229 { 230 Float32 value = static_cast<Float32>(m_Volume) / 100.0f; 231 AudioDeviceSetProperty(m_DeviceId, NULL, 1, false, 232 kAudioDevicePropertyVolumeScalar, 233 sizeof(UInt32), &value); 234 } 235 236 UInt32 value = mute; 237 AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, 238 kAudioDevicePropertyMute, sizeof(UInt32), &value); 239 240 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 241 emit changedMute(mute); 242 } 243 244 // static 245 OSStatus VolumeControlCoreAudio::event(AudioDeviceID deviceId, UInt32 channel, 246 Boolean input, 247 AudioDevicePropertyID property, 248 void* context) 249 { 250 VolumeControlCoreAudio* that = 251 static_cast<VolumeControlCoreAudio*>(context); 252 253 if (deviceId == that->m_DeviceId && !input) 254 switch(property) 255 { 256 case kAudioDevicePropertyVolumeScalar: 257 case kAudioDevicePropertyVolumeDecibels: 258 int volume = that->volume(); 259 if (that->m_Volume.fetchAndStoreRelaxed(volume) != volume) 260 emit that->changedVolume(volume); 261 break; 262 263 case kAudioDevicePropertyMute: 264 bool mute = that->mute(); 265 if (that->m_Mute.fetchAndStoreRelaxed(mute) != mute) 266 emit that->changedMute(mute); 267 break; 268 } 269 270 return noErr; 271 } -
mythtv/libs/libmyth/volumebase.h
1 #ifndef __VOLUME_BASE__2 #define __VOLUME_BASE__3 4 #include "mythexp.h"5 6 typedef enum {7 kMuteOff = 0,8 kMuteLeft,9 kMuteRight,10 kMuteAll,11 } MuteState;12 13 class MPUBLIC VolumeBase14 {15 public:16 VolumeBase();17 virtual ~VolumeBase() {};18 19 void SWVolume(bool set);20 bool SWVolume(void);21 virtual uint GetCurrentVolume(void) const;22 virtual void SetCurrentVolume(int value);23 virtual void AdjustCurrentVolume(int change);24 virtual void ToggleMute(void);25 26 virtual MuteState GetMuteState(void) const;27 virtual MuteState SetMuteState(MuteState);28 29 static MuteState NextMuteState(MuteState);30 31 protected:32 33 virtual int GetVolumeChannel(int channel) const = 0; // Returns 0-10034 virtual void SetVolumeChannel(int channel, int volume) = 0; // range 0-100 for vol35 virtual void SetSWVolume(int new_volume, bool save) = 0;36 virtual int GetSWVolume(void) = 0;37 38 void UpdateVolume(void);39 void SyncVolume(void);40 void SetChannels(int new_channels);41 bool internal_vol;42 43 private:44 45 int volume;46 MuteState current_mute_state;47 bool swvol;48 bool swvol_setting;49 int channels;50 51 };52 53 #endif // __VOLUME_BASE__ -
mythtv/libs/libmyth/volumecontrol.h
1 #ifndef VOLUMECONTROL 2 #define VOLUMECONTROL 3 4 #include <QObject> 5 #include <QString> 6 7 class VolumeControl : public QObject 8 { 9 Q_OBJECT 10 11 public: 12 virtual int volume() const = 0; 13 virtual void setVolume(int volume) = 0; 14 virtual void increaseVolume() = 0; 15 virtual void decreaseVolume() = 0; 16 17 virtual bool mute() const = 0; 18 virtual void setMute(bool mute) = 0; 19 20 signals: 21 void changedVolume(int volume); 22 void changedMute(bool mute); 23 }; 24 25 #endif // VOLUMECONTROL -
mythtv/libs/libmyth/volumecontrolsoftware.cpp
1 #include "volumecontrolsoftware.h" 2 3 #include "mythcorecontext.h" 4 #include "mythverbose.h" 5 #include <algorithm> 6 7 // static 8 QHash<QString, QString> VolumeControlSoftware::Enumerate() 9 { 10 QHash<QString, QString> result; 11 12 result.insert("Software:", "Software Volume Processing"); 13 14 return result; 15 } 16 17 VolumeControlSoftware::VolumeControlSoftware(QString device) 18 { 19 int volume = gCoreContext->GetNumSetting("SoftwareVolume", 80); 20 m_Volume = std::min(std::max(0, volume), 100); 21 m_Mute = gCoreContext->GetNumSetting("SoftwareMute", false) ? true : false; 22 } 23 24 VolumeControlSoftware::~VolumeControlSoftware() 25 { 26 27 } 28 29 int VolumeControlSoftware::volume() const 30 { 31 int volume = m_Volume; 32 33 VERBOSE(VB_AUDIO, 34 QString("VolumeControlSoftware::volume() = %1") 35 .arg(volume)); 36 37 return volume; 38 } 39 40 void VolumeControlSoftware::setVolume(int volume) 41 { 42 VERBOSE(VB_AUDIO, 43 QString("VolumeControlSoftware::setVolume(%1)") 44 .arg(volume)); 45 46 volume = std::min(std::max(0, volume), 100); 47 48 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 49 { 50 gCoreContext->SaveSetting("SoftwareVolume", volume); 51 emit changedVolume(volume); 52 } 53 } 54 55 void VolumeControlSoftware::increaseVolume() 56 { 57 setVolume(volume() + 1); 58 } 59 60 void VolumeControlSoftware::decreaseVolume() 61 { 62 setVolume(volume() - 1); 63 } 64 65 bool VolumeControlSoftware::mute() const 66 { 67 bool mute = m_Mute ? true : false; 68 69 VERBOSE(VB_AUDIO, 70 QString("VolumeControlSoftware::mute() = %1") 71 .arg(mute ? "mute" : "unmute")); 72 73 return mute; 74 } 75 76 void VolumeControlSoftware::setMute(bool mute) 77 { 78 VERBOSE(VB_AUDIO, 79 QString("VolumeControlSoftware::setMute(%1)") 80 .arg(mute ? "mute" : "unmute")); 81 82 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 83 { 84 gCoreContext->SaveSetting("SoftwareMute", mute); 85 emit changedMute(mute); 86 } 87 } 88 89 QAtomicInt VolumeControlSoftware::m_Volume; 90 QAtomicInt VolumeControlSoftware::m_Mute; -
mythtv/libs/libmyth/audiooutputpulse.h
30 30 AudioOutputPulseAudio(const AudioSettings &settings); 31 31 ~AudioOutputPulseAudio(); 32 32 33 int GetVolumeChannel(int channel) const;34 void SetVolumeChannel(int channel, int volume);35 33 void Drain(void); 36 34 37 35 protected: -
mythtv/libs/libmyth/volumecontroloss.h
1 #ifndef VOLUMECONTROLOSS 2 #define VOLUMECONTROLOSS 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QThread> 8 #include <QAtomicInt> 9 10 11 class VolumeControlOSS : public VolumeControl, protected QThread 12 { 13 public: 14 static QHash<QString, QString> Enumerate(); 15 16 public: 17 VolumeControlOSS(QString device); 18 virtual ~VolumeControlOSS(); 19 20 public: 21 int volume() const; 22 void setVolume(int volume); 23 void increaseVolume(); 24 void decreaseVolume(); 25 26 bool mute() const; 27 void setMute(bool mute); 28 29 protected: 30 virtual void run(); 31 32 private: 33 int m_Mixer; //< OSS mixer file descriptor 34 int m_MixerDev; //< OSS mixer device ID 35 int m_VolumeCtrl; //< OSS control ID for volume 36 int m_VolumeMax; //< OSS maximum for volume 37 int m_VolumeType; //< OSS control type for volume 38 int m_VolumeTimestamp; //< OSS timestamp for volume 39 int m_MuteCtrl; //< OSS control ID for mute 40 int m_MuteTimestamp; //< OSS timestamp for mute 41 int m_Range; //< Range of volume control 42 volatile bool m_Exit; //< Flag to notify thread to exit 43 QAtomicInt m_Volume; //< Volume state cache 44 QAtomicInt m_Mute; //< Mute state cache 45 }; 46 47 #endif // VOLUMECONTROLOSS -
mythtv/libs/libmyth/volumecontrolalsa.h
1 #ifndef VOLUMECONTROLALSA 2 #define VOLUMECONTROLALSA 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QThread> 8 #include <QAtomicInt> 9 #include <alsa/asoundlib.h> 10 11 12 class VolumeControlALSA : public VolumeControl, protected QThread 13 { 14 public: 15 static QHash<QString, QString> Enumerate(); 16 17 public: 18 VolumeControlALSA(QString device); 19 virtual ~VolumeControlALSA(); 20 21 public: 22 int volume() const; 23 void setVolume(int volume); 24 void increaseVolume(); 25 void decreaseVolume(); 26 27 bool mute() const; 28 void setMute(bool mute); 29 30 protected: 31 virtual void run(); 32 33 static int event(snd_mixer_elem_t* elem, unsigned int mask); 34 35 private: 36 snd_mixer_t* m_MixerHandle; //< ALSA mixer handle 37 snd_mixer_elem_t* m_MixerElement; //< ALSA mixer element handle 38 int m_Range; //< Range of mixer element 39 int m_Exit[2]; //< Pipe file descriptors 40 QAtomicInt m_Volume; //< Volume state cache 41 QAtomicInt m_Mute; //< Mute state cache 42 }; 43 44 #endif // VOLUMECONTROLALSA -
mythtv/libs/libmyth/audiooutputpulse.cpp
312 312 return (int)latency * samplerate * output_bytes_per_frame / 1000000; 313 313 } 314 314 315 int AudioOutputPulseAudio::GetVolumeChannel(int channel) const316 {317 return (float)volume_control.values[channel] /318 (float)PA_VOLUME_NORM * 100.0f;319 }320 321 void AudioOutputPulseAudio::SetVolumeChannel(int channel, int volume)322 {323 QString fn_log_tag = "SetVolumeChannel, ";324 325 if (channel < 0 || channel > PULSE_MAX_CHANNELS || volume < 0)326 {327 VBERROR(fn_log_tag + QString("bad volume params, channel %1, volume %2")328 .arg(channel).arg(volume));329 return;330 }331 332 volume_control.values[channel] =333 (float)volume / 100.0f * (float)PA_VOLUME_NORM;334 335 volume = min(100, volume);336 volume = max(0, volume);337 338 uint32_t sink_index = pa_stream_get_device_index(pstream);339 pa_threaded_mainloop_lock(mainloop);340 pa_operation *op =341 pa_context_set_sink_volume_by_index(pcontext, sink_index,342 &volume_control,343 OpCompletionCallback, this);344 pa_threaded_mainloop_unlock(mainloop);345 if (op)346 pa_operation_unref(op);347 else348 VBERROR(fn_log_tag +349 QString("set sink volume operation failed, sink %1, error %2 ")350 .arg(sink_index).arg(pa_strerror(pa_context_errno(pcontext))));351 }352 353 315 void AudioOutputPulseAudio::Drain(void) 354 316 { 355 317 AudioOutputBase::Drain(); … … 492 454 pa_stream_set_overflow_callback(pstream, BufferFlowCallback, (char*)"over"); 493 455 pa_stream_set_underflow_callback(pstream, BufferFlowCallback, 494 456 (char*)"under"); 495 if (set_initial_vol) 496 { 497 int volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80); 498 pa_cvolume_set(&volume_control, channels, 499 (float)volume * (float)PA_VOLUME_NORM / 100.0f); 500 } 501 else 502 pa_cvolume_reset(&volume_control, channels); 457 pa_cvolume_reset(&volume_control, channels); 503 458 504 459 fragment_size = (samplerate * 25 * output_bytes_per_frame) / 1000; 505 460 -
mythtv/libs/libmyth/volumecontrolendpoint.cpp
1 #include "volumecontrolendpoint.h" 2 3 #include "mythverbose.h" 4 #include <algorithm> 5 #include <math.h> 6 7 typedef struct _BYTE_BLOB 8 { 9 unsigned long clSize; 10 byte abData[ 1 ]; 11 } BYTE_BLOB; 12 13 typedef struct _tagpropertykey 14 { 15 GUID fmtid; 16 DWORD pid; 17 } PROPERTYKEY; 18 19 #define REFPROPVARIANT const PROPVARIANT & 20 21 inline void PropVariantInit ( PROPVARIANT * pvar ) 22 { 23 memset ( pvar, 0, sizeof(PROPVARIANT) ); 24 } 25 WINOLEAPI PropVariantClear ( PROPVARIANT * pvar ); 26 27 EXTERN_C const CLSID CLSID_MMDeviceEnumerator = {0xBCDE0395,0xE52F,0x467C,{0x8E,0x3D,0xC4,0x57,0x92,0x91,0x69,0x2E}}; 28 EXTERN_C const IID IID_IMMDeviceEnumerator = {0xA95664D2,0x9614,0x4F35,{0xA7,0x46,0xDE,0x8D,0xB6,0x36,0x17,0xE6}}; 29 EXTERN_C const IID IID_IAudioEndpointVolume = {0x5CDF2C82,0x841E,0x4546,{0x97,0x22,0x0C,0xF7,0x40,0x78,0x22,0x9A}}; 30 EXTERN_C const IID IID_IAudioEndpointVolumeCallback = {0x657804FA,0xD6AD,0x4496,{0x8A,0x60,0x35,0x27,0x52,0xAF,0x4F,0x89}}; 31 EXTERN_C const IID IID_IUnknown = {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; 32 #define INITGUID 33 #include <Unknwn.h> 34 #include <mmdeviceapi.h> 35 #include <FunctionDiscoveryKeys_devpkey.h> 36 37 38 QHash<QString, QString> VolumeControlEndpoint::Enumerate() 39 { 40 QHash<QString, QString> result; 41 42 HRESULT hr = S_OK; 43 IMMDeviceEnumerator* pEnumerator = NULL; 44 IMMDeviceCollection* pCollection = NULL; 45 46 CoInitialize(NULL); 47 48 // Get enumerator for audio endpoint devices. 49 hr = CoCreateInstance(CLSID_MMDeviceEnumerator, 50 NULL, CLSCTX_INPROC_SERVER, 51 IID_IMMDeviceEnumerator, 52 (void**)&pEnumerator); 53 if (!SUCCEEDED(hr) || !pEnumerator) 54 { 55 CoUninitialize(); 56 return result; 57 } 58 59 result.insert("Endpoint:default", "Default End Point device"); 60 61 hr = pEnumerator->EnumAudioEndpoints(eRender, 62 DEVICE_STATE_ACTIVE, 63 &pCollection); 64 if (!SUCCEEDED(hr) || !pCollection) 65 { 66 pEnumerator->Release(); 67 CoUninitialize(); 68 return result; 69 } 70 71 UINT devices = 0; 72 hr = pCollection->GetCount(&devices); 73 if (!SUCCEEDED(hr)) 74 { 75 pCollection->Release(); 76 pEnumerator->Release(); 77 CoUninitialize(); 78 return result; 79 } 80 81 for (UINT device = 0; device < devices; ++device) 82 { 83 IMMDevice* pDevice = NULL; 84 hr = pCollection->Item(device, &pDevice); 85 if (!SUCCEEDED(hr) || !pDevice) 86 continue; 87 88 LPWSTR pwszID = NULL; 89 hr = pDevice->GetId(&pwszID); 90 if (!SUCCEEDED(hr)) 91 { 92 pDevice->Release(); 93 continue; 94 } 95 QString uid(reinterpret_cast<const QChar*>(pwszID), wcslen(pwszID)); 96 CoTaskMemFree(pwszID); 97 98 IPropertyStore *pProps = NULL; 99 hr = pDevice->OpenPropertyStore(STGM_READ, &pProps); 100 if (!SUCCEEDED(hr) || !pProps) 101 { 102 pDevice->Release(); 103 continue; 104 } 105 106 PROPVARIANT varName; 107 PropVariantInit(&varName); 108 109 hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName); 110 if (!SUCCEEDED(hr)) 111 { 112 PropVariantClear(&varName); 113 pProps->Release(); 114 pDevice->Release(); 115 continue; 116 } 117 QString name(reinterpret_cast<const QChar*>(varName.pwszVal), 118 wcslen(varName.pwszVal)); 119 PropVariantClear(&varName); 120 121 pProps->Release(); 122 pDevice->Release(); 123 124 result.insert(QString("Endpoint:") + uid, name); 125 } 126 127 pCollection->Release(); 128 pEnumerator->Release(); 129 130 CoUninitialize(); 131 132 return result; 133 } 134 135 VolumeControlEndpoint::VolumeControlEndpoint(QString device) : 136 m_EndpointVolume(NULL) 137 { 138 HRESULT hr = S_OK; 139 IMMDeviceEnumerator* pEnumerator = NULL; 140 IMMDevice* pDevice = NULL; 141 142 CoInitialize(NULL); 143 144 // Get enumerator for audio endpoint devices. 145 hr = CoCreateInstance(CLSID_MMDeviceEnumerator, 146 NULL, CLSCTX_INPROC_SERVER, 147 IID_IMMDeviceEnumerator, 148 (void**)&pEnumerator); 149 if (!SUCCEEDED(hr) || !pEnumerator) 150 return; 151 152 if (device == QString("default")) 153 hr = pEnumerator->GetDefaultAudioEndpoint(eRender, 154 eMultimedia, 155 &pDevice); 156 else 157 hr = pEnumerator->GetDevice((LPCWSTR)device.constData(), &pDevice); 158 159 if (!SUCCEEDED(hr) || !pDevice) 160 { 161 pEnumerator->Release(); 162 return; 163 } 164 165 hr = pDevice->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, 166 NULL, (void**)&m_EndpointVolume); 167 if (!SUCCEEDED(hr) || !m_EndpointVolume) 168 { 169 pDevice->Release(); 170 pEnumerator->Release(); 171 return; 172 } 173 174 pDevice->Release(); 175 pEnumerator->Release(); 176 177 hr = m_EndpointVolume->RegisterControlChangeNotify(this); 178 if (!SUCCEEDED(hr)) 179 return; 180 181 UINT step, count; 182 hr = m_EndpointVolume->GetVolumeStepInfo(&step, &count); 183 if (!SUCCEEDED(hr)) 184 return; 185 186 m_Range = std::min(std::max(1U, count - 1), 100U); 187 188 m_Volume = volume(); 189 m_Mute = mute(); 190 } 191 192 VolumeControlEndpoint::~VolumeControlEndpoint() 193 { 194 if (m_EndpointVolume) 195 { 196 m_EndpointVolume->UnregisterControlChangeNotify(this); 197 m_EndpointVolume->Release(); 198 } 199 200 CoUninitialize(); 201 } 202 203 int VolumeControlEndpoint::volume() const 204 { 205 int volume = 0; 206 207 if (!mute()) 208 { 209 if (m_EndpointVolume) 210 { 211 float level; 212 m_EndpointVolume->GetMasterVolumeLevelScalar(&level); 213 volume = static_cast<int>(round(level * 100.0f)); 214 } 215 } 216 else 217 volume = m_Volume; 218 219 VERBOSE(VB_AUDIO, 220 QString("VolumeControlEndpoint::volume() = %1") 221 .arg(volume)); 222 223 return volume; 224 } 225 226 void VolumeControlEndpoint::setVolume(int volume) 227 { 228 VERBOSE(VB_AUDIO, 229 QString("VolumeControlEndpoint::setVolume(%1)") 230 .arg(volume)); 231 232 volume = std::min(std::max(0, volume), 100); 233 234 if (mute() && volume > VolumeControlEndpoint::volume()) 235 setMute(false); 236 237 if (!mute() && m_EndpointVolume) 238 m_EndpointVolume->SetMasterVolumeLevelScalar( 239 round(static_cast<float>(volume * m_Range) / 100.0f) / 240 static_cast<float>(m_Range), NULL); 241 242 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 243 emit changedVolume(volume); 244 } 245 246 void VolumeControlEndpoint::increaseVolume() 247 { 248 int volume = VolumeControlEndpoint::volume(); 249 float level = (round(static_cast<float>(volume * m_Range) / 100.0f) + 1.0f) 250 / static_cast<float>(m_Range); 251 volume = static_cast<int>(round(level * 100.0f)); 252 setVolume(volume); 253 } 254 255 void VolumeControlEndpoint::decreaseVolume() 256 { 257 int volume = VolumeControlEndpoint::volume(); 258 float level = (round(static_cast<float>(volume * m_Range) / 100.0f) - 1.0f) 259 / static_cast<float>(m_Range); 260 volume = static_cast<int>(round(level * 100.0f)); 261 setVolume(volume); 262 } 263 264 bool VolumeControlEndpoint::mute() const 265 { 266 BOOL mute = FALSE; 267 268 if (m_EndpointVolume) 269 m_EndpointVolume->GetMute(&mute); 270 271 VERBOSE(VB_AUDIO, 272 QString("VolumeControlEndpoint::mute() = %1") 273 .arg(mute ? "mute" : "unmute")); 274 275 return mute; 276 } 277 278 void VolumeControlEndpoint::setMute(bool mute) 279 { 280 VERBOSE(VB_AUDIO, 281 QString("VolumeControlEndpoint::setMute(%1)") 282 .arg(mute ? "mute" : "unmute")); 283 284 if (m_EndpointVolume) 285 { 286 if (VolumeControlEndpoint::mute()) 287 m_EndpointVolume->SetMasterVolumeLevelScalar( 288 static_cast<float>(m_Volume) / 100.0f, NULL); 289 290 m_EndpointVolume->SetMute(mute, NULL); 291 } 292 293 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 294 emit changedMute(mute); 295 } 296 297 ULONG STDMETHODCALLTYPE VolumeControlEndpoint::AddRef() 298 { 299 return 1; 300 } 301 302 ULONG STDMETHODCALLTYPE VolumeControlEndpoint::Release() 303 { 304 return 0; 305 } 306 307 HRESULT STDMETHODCALLTYPE 308 VolumeControlEndpoint::QueryInterface(REFIID riid, VOID **ppvInterface) 309 { 310 if (IID_IUnknown == riid) 311 { 312 AddRef(); 313 *ppvInterface = (IUnknown*)this; 314 } 315 else if (IID_IAudioEndpointVolumeCallback == riid) 316 { 317 AddRef(); 318 *ppvInterface = (IAudioEndpointVolumeCallback*)this; 319 } 320 else 321 { 322 *ppvInterface = NULL; 323 return E_NOINTERFACE; 324 } 325 return S_OK; 326 } 327 328 HRESULT STDMETHODCALLTYPE 329 VolumeControlEndpoint::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) 330 { 331 HRESULT hr = E_INVALIDARG; 332 333 if (pNotify) 334 { 335 int volume = VolumeControlEndpoint::volume(); 336 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 337 emit changedVolume(volume); 338 339 bool mute = VolumeControlEndpoint::mute(); 340 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 341 emit changedMute(mute); 342 343 hr = S_OK; 344 } 345 346 return hr; 347 } -
mythtv/libs/libmyth/audiooutputjack.h
18 18 AudioOutputJACK(const AudioSettings &settings); 19 19 virtual ~AudioOutputJACK(); 20 20 21 // Volume control22 virtual int GetVolumeChannel(int channel) const; // Returns 0-10023 virtual void SetVolumeChannel(int channel, int volume); // range 0-10024 25 21 protected: 26 22 27 23 // You need to implement the following functions … … 37 33 38 34 private: 39 35 40 void VolumeInit(void);41 42 36 // Our various callback functions 43 37 inline int JackCallback(jack_nframes_t nframes); 44 38 static int _JackCallback(jack_nframes_t nframes, void *arg); -
mythtv/libs/libmyth/audiosettings.cpp
15 15 channels(-1), 16 16 codec(0), 17 17 samplerate(-1), 18 set_initial_vol(false),19 18 use_passthru(false), 20 19 source(AUDIOOUTPUT_UNKNOWN), 21 20 upmixer(0), … … 30 29 channels(other.channels), 31 30 codec(other.codec), 32 31 samplerate(other.samplerate), 33 set_initial_vol(other.set_initial_vol),34 32 use_passthru(other.use_passthru), 35 33 source(other.source), 36 34 upmixer(other.upmixer), … … 46 44 int codec, 47 45 int samplerate, 48 46 AudioOutputSource source, 49 bool set_initial_vol,50 47 bool use_passthru, 51 48 int upmixer_startup) : 52 49 main_device(main_device), … … 55 52 channels(channels), 56 53 codec(codec), 57 54 samplerate(samplerate), 58 set_initial_vol(set_initial_vol),59 55 use_passthru(use_passthru), 60 56 source(source), 61 57 upmixer(upmixer_startup), … … 76 72 channels(channels), 77 73 codec(codec), 78 74 samplerate(samplerate), 79 set_initial_vol(false),80 75 use_passthru(use_passthru), 81 76 source(AUDIOOUTPUT_UNKNOWN), 82 77 upmixer(upmixer_startup), … … 93 88 channels(-1), 94 89 codec(0), 95 90 samplerate(-1), 96 set_initial_vol(false),97 91 use_passthru(false), 98 92 source(AUDIOOUTPUT_UNKNOWN), 99 93 upmixer(0), -
mythtv/libs/libmyth/audiooutputca.cpp
308 308 return false; 309 309 } 310 310 311 if (internal_vol && set_initial_vol)312 {313 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");314 controlLabel += "MixerVolume";315 SetCurrentVolume(gCoreContext->GetNumSetting(controlLabel, 80));316 }317 318 311 return true; 319 312 } 320 313 … … 420 413 return noErr; 421 414 } 422 415 423 int AudioOutputCA::GetVolumeChannel(int channel) const424 {425 // FIXME: this only returns global volume426 (void)channel;427 Float32 volume;428 429 if (!AudioUnitGetParameter(d->mOutputUnit,430 kHALOutputParam_Volume,431 kAudioUnitScope_Global, 0, &volume))432 return (int)lroundf(volume * 100.0f);433 434 return 0; // error case435 }436 437 void AudioOutputCA::SetVolumeChannel(int channel, int volume)438 {439 // FIXME: this only sets global volume440 (void)channel;441 AudioUnitSetParameter(d->mOutputUnit, kHALOutputParam_Volume,442 kAudioUnitScope_Global, 0, (volume * 0.01f), 0);443 }444 445 416 // IOProc style callback for SPDIF audio output 446 417 static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice, 447 418 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
489 489 chan_volumes[i] = volume; 490 490 } 491 491 492 int AudioOutputJACK::GetVolumeChannel(int channel) const493 {494 unsigned int vol = 0;495 496 if (!internal_vol)497 return 100;498 499 if (channel < JACK_CHANNELS_MAX)500 vol = chan_volumes[channel];501 502 return vol;503 }504 505 void AudioOutputJACK::SetVolumeChannel(int channel, int volume)506 {507 if (internal_vol && (channel < JACK_CHANNELS_MAX))508 {509 chan_volumes[channel] = volume;510 if (channel == 0)511 {512 // Left513 chan_volumes[2] = volume; // left rear514 }515 else if (channel == 1)516 {517 // Right518 chan_volumes[3] = volume; // right rear519 }520 521 // LFE and Center522 chan_volumes[4] = chan_volumes[5] =523 (chan_volumes[0] + chan_volumes[1]) / 2;524 }525 }526 527 528 492 /* We don't need an audio output thread for Jack 529 493 Everything handled by callbacks here 530 494 Therefore we can loose all the Start/StopOutputThread, WriteAudio, etc -
mythtv/libs/libmyth/audiooutputoss.h
12 12 AudioOutputOSS(const AudioSettings &settings); 13 13 virtual ~AudioOutputOSS(); 14 14 15 // Volume control16 virtual int GetVolumeChannel(int channel) const;17 virtual void SetVolumeChannel(int channel, int volume);18 19 15 protected: 20 16 // You need to implement the following functions 21 17 virtual bool OpenDevice(void); … … 25 21 AudioOutputSettings* GetOutputSettings(void); 26 22 27 23 private: 28 void VolumeInit(void);29 void VolumeCleanup(void);30 31 24 void SetFragSize(void); 32 25 33 26 int audiofd; 34 27 mutable int numbadioctls; 35 36 // Volume related37 int mixerfd;38 int control;39 28 }; 40 29 41 30 #endif -
mythtv/libs/libmyth/audiooutputbase.cpp
62 62 pauseaudio(false), actually_paused(false), 63 63 was_paused(false), unpause_when_ready(false), 64 64 65 set_initial_vol(settings.set_initial_vol),66 65 buffer_output_data_for_use(false), 67 66 68 67 // private … … 75 74 source_bytes_per_frame(0), 76 75 needs_upmix(false), needs_downmix(false), 77 76 surround_mode(QUALITY_LOW), old_stretchfactor(1.0f), 78 volume (80), volumeControl(NULL),77 volumeControl(NULL), 79 78 80 79 processing(false), 81 80 … … 116 115 117 116 VBAUDIO(QString("SRC quality = %1").arg(quality_string(src_quality))); 118 117 } 118 119 if (gCoreContext->GetSetting("MixerDevice") == "Software:") 120 volume_control = VolumeControlManager::GetControl("Software:"); 119 121 } 120 122 121 123 /** … … 393 395 394 396 killaudio = pauseaudio = false; 395 397 was_paused = true; 396 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);397 398 398 399 VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels") 399 400 .arg(codec_id_string((CodecID)codec)) … … 472 473 473 474 // Turn on float conversion? 474 475 if (need_resampler || needs_upmix || needs_downmix || 475 stretchfactor != 1.0f || ( internal_vol && SWVolume()) ||476 stretchfactor != 1.0f || (volume_control) || 476 477 (enc && output_format != FORMAT_S16) || 477 478 !output_settings->IsSupportedFormat(output_format)) 478 479 { … … 511 512 return; 512 513 } 513 514 514 // Only used for software volume515 if (set_initial_vol && internal_vol && SWVolume())516 {517 VBAUDIO("Software volume enabled");518 volumeControl = gCoreContext->GetSetting("MixerControl", "PCM");519 volumeControl += "MixerVolume";520 volume = gCoreContext->GetNumSetting(volumeControl, 80);521 }522 523 VolumeBase::SetChannels(channels);524 VolumeBase::SyncVolume();525 VolumeBase::UpdateVolume();526 527 515 VBAUDIO(QString("Audio fragment size: %1").arg(fragment_size)); 528 516 529 517 audbuf_timecode = audiotime = frames_buffered = 0; … … 802 790 } 803 791 804 792 /** 805 * Set the volume for software volume control806 */807 void AudioOutputBase::SetSWVolume(int new_volume, bool save)808 {809 volume = new_volume;810 if (save && volumeControl != NULL)811 gCoreContext->SaveSetting(volumeControl, volume);812 }813 814 /**815 * Get the volume for software volume control816 */817 int AudioOutputBase::GetSWVolume()818 {819 return volume;820 }821 822 /**823 793 * Check that there's enough space in the audiobuffer to write the provided 824 794 * number of frames 825 795 * … … 1067 1037 org_waud += nFrames * bpf; 1068 1038 } 1069 1039 1070 if ( internal_vol && SWVolume())1040 if (volume_control) 1071 1041 { 1072 1042 org_waud = waud; 1073 1043 int num = len; 1044 int volume = volume_control->volume(); 1074 1045 1075 1046 if (bdiff <= num) 1076 1047 { … … 1283 1254 raud += frag_size; 1284 1255 1285 1256 // Mute individual channels through mono->stereo duplication 1286 MuteState mute_state = GetMuteState(); 1287 if (written_size && channels > 1 && 1288 (mute_state == kMuteLeft || mute_state == kMuteRight)) 1257 bool mute = volume_control ? volume_control->mute() : false; 1258 if (written_size && channels > 1 && mute) 1289 1259 { 1290 AudioOutputUtil::MuteChannel(obytes << 3, channels, 1291 mute_state == kMuteLeft ? 0 : 1, 1260 AudioOutputUtil::MuteChannel(obytes << 3, channels, 1, 1292 1261 buffer, written_size); 1293 1262 } 1294 1263 -
mythtv/libs/libmyth/audiooutput.cpp
39 39 AudioOutput *AudioOutput::OpenAudio( 40 40 const QString &main_device, const QString &passthru_device, 41 41 AudioFormat format, int channels, int codec, int samplerate, 42 AudioOutputSource source, bool set_initial_vol, bool passthru, 43 int upmixer_startup) 42 AudioOutputSource source, bool passthru, int upmixer_startup) 44 43 { 45 44 AudioSettings settings( 46 45 main_device, passthru_device, format, channels, codec, samplerate, 47 source, set_initial_vol,passthru, upmixer_startup);46 source, passthru, upmixer_startup); 48 47 49 48 return OpenAudio(settings); 50 49 } -
mythtv/libs/libmyth/libmyth.pro
24 24 HEADERS += output.h 25 25 HEADERS += settings.h 26 26 HEADERS += uilistbtntype.h uitypes.h util.h mythuifilebrowser.h 27 HEADERS += volumebase.h visual.h xmlparse.h 27 HEADERS += volumecontrol.h volumecontrolmanager.h volumecontrolsoftware.h 28 HEADERS += visual.h xmlparse.h 28 29 HEADERS += mythhdd.h mythcdrom.h storagegroupeditor.h dbutil.h 29 30 HEADERS += mythcommandlineparser.h mythterminal.h 30 31 HEADERS += mythhttppool.h mythhttphandler.h … … 51 52 SOURCES += output.cpp 52 53 SOURCES += settings.cpp 53 54 SOURCES += uilistbtntype.cpp uitypes.cpp util.cpp mythuifilebrowser.cpp 54 SOURCES += volumebase.cpp xmlparse.cpp 55 SOURCES += volumecontrolmanager.cpp volumecontrolsoftware.cpp 56 SOURCES += xmlparse.cpp 55 57 SOURCES += mythhdd.cpp mythcdrom.cpp storagegroupeditor.cpp dbutil.cpp 56 58 SOURCES += mythcommandlineparser.cpp mythterminal.cpp 57 59 SOURCES += mythhttppool.cpp mythhttphandler.cpp … … 92 94 # Install headers so that plugins can compile independently 93 95 inc.path = $${PREFIX}/include/mythtv/ 94 96 inc.files = dialogbox.h mythcontext.h 95 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h97 inc.files += mythwidgets.h remotefile.h oldsettings.h 96 98 inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h 97 99 inc.files += audiooutput.h audiosettings.h audiooutputsettings.h util.h 98 100 inc.files += inetcomms.h mythmedia.h mythcdrom.h mythwizard.h schemawizard.h dbutil.h 99 101 inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h 100 inc.files += visual.h volume base.h output.h langsettings.h102 inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h 101 103 inc.files += mythexp.h mythpluginapi.h storagegroupeditor.h 102 104 inc.files += mythconfigdialogs.h mythconfiggroups.h 103 105 inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h … … 116 118 117 119 using_oss { 118 120 DEFINES += USING_OSS 119 SOURCES += audiooutputoss.cpp 120 HEADERS += audiooutputoss.h 121 SOURCES += audiooutputoss.cpp volumecontroloss.cpp 122 HEADERS += audiooutputoss.h volumecontroloss.h 121 123 } 122 124 123 125 using_pulse { … … 145 147 146 148 mingw { 147 149 DEFINES += USING_MINGW 148 SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp 149 HEADERS += mediamonitor-windows.h audiooutputwin.h audiooutputdx.h 150 LIBS += -lpthread -lwinmm -lws2_32 150 SOURCES += mediamonitor-windows.cpp 151 HEADERS += mediamonitor-windows.h 152 SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp 153 HEADERS += audiooutputwin.h audiooutputdx.h volumecontrolendpoint.h 154 LIBS += -lpthread -lwinmm -lws2_32 -lole32 151 155 } 152 156 153 157 macx { 154 HEADERS += audiooutputca.h 155 SOURCES += audiooutputca.cpp 158 DEFINES += USE_COREAUDIO 159 HEADERS += audiooutputca.h volumecontrolcoreaudio.h 160 SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp 156 161 HEADERS += mythcdrom-darwin.h 157 162 SOURCES += mythcdrom-darwin.cpp 158 163 … … 191 196 192 197 using_alsa { 193 198 DEFINES += USE_ALSA 194 HEADERS += audiooutputalsa.h 195 SOURCES += audiooutputalsa.cpp 199 HEADERS += audiooutputalsa.h volumecontrolalsa.h 200 SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp 196 201 } 197 202 198 203 using_jack { -
mythtv/libs/libmyth/audiosettings.h
33 33 int codec, 34 34 int samplerate, 35 35 AudioOutputSource source, 36 bool set_initial_vol,37 36 bool use_passthru, 38 37 int upmixer_startup = 0); 39 38 … … 60 59 int channels; 61 60 int codec; 62 61 int samplerate; 63 bool set_initial_vol;64 62 bool use_passthru; 65 63 AudioOutputSource source; 66 64 int upmixer; -
mythtv/libs/libmyth/audiooutputca.h
26 26 bool RenderAudio(unsigned char *aubuf, int size, 27 27 unsigned long long timestamp); 28 28 29 // Volume control30 virtual int GetVolumeChannel(int channel) const;31 virtual void SetVolumeChannel(int channel, int volume);32 33 29 void Debug(QString msg) 34 30 { VERBOSE(VB_AUDIO, "AudioOutputCA::" + msg); } 35 31 … … 38 34 39 35 void Warn(QString msg) 40 36 { VERBOSE(VB_IMPORTANT, "AudioOutputCA Warning: " + msg); } 37 bool internal_vol; 41 38 42 39 protected: 43 40 -
mythtv/libs/libmyth/audiooutputoss.cpp
32 32 33 33 AudioOutputOSS::AudioOutputOSS(const AudioSettings &settings) : 34 34 AudioOutputBase(settings), 35 audiofd(-1), numbadioctls(0), 36 mixerfd(-1), control(SOUND_MIXER_VOLUME) 35 audiofd(-1), numbadioctls(0) 37 36 { 38 37 // Set everything up 39 38 InitSettings(settings); … … 221 220 else 222 221 OERROR("Unable to get audio card capabilities"); 223 222 224 // Setup volume control225 if (internal_vol)226 VolumeInit();227 228 223 // Device opened successfully 229 224 return true; 230 225 } … … 235 230 close(audiofd); 236 231 237 232 audiofd = -1; 238 239 VolumeCleanup();240 233 } 241 234 242 235 … … 276 269 return soundcard_buffer; 277 270 } 278 271 279 void AudioOutputOSS::VolumeInit()280 {281 mixerfd = -1;282 283 QString device = gCoreContext->GetSetting("MixerDevice", "/dev/mixer");284 if (device.toLower() == "software")285 return;286 287 QByteArray dev = device.toAscii();288 mixerfd = open(dev.constData(), O_RDONLY);289 290 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");291 292 if (controlLabel == "Master")293 control = SOUND_MIXER_VOLUME;294 else295 control = SOUND_MIXER_PCM;296 297 if (mixerfd < 0)298 {299 VBERROR(QString("Unable to open mixer: '%1'").arg(device));300 return;301 }302 303 if (set_initial_vol)304 {305 int tmpVol;306 int volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);307 tmpVol = (volume << 8) + volume;308 int ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);309 if (ret < 0)310 VBERROR(QString("Error Setting initial Master Volume") + ENO);311 312 volume = gCoreContext->GetNumSetting("PCMMixerVolume", 80);313 tmpVol = (volume << 8) + volume;314 ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);315 if (ret < 0)316 VBERROR(QString("Error setting initial PCM Volume") + ENO);317 }318 }319 320 void AudioOutputOSS::VolumeCleanup()321 {322 if (mixerfd >= 0)323 {324 close(mixerfd);325 mixerfd = -1;326 }327 }328 329 int AudioOutputOSS::GetVolumeChannel(int channel) const330 {331 int volume=0;332 int tmpVol=0;333 334 if (mixerfd <= 0)335 return 100;336 337 int ret = ioctl(mixerfd, MIXER_READ(control), &tmpVol);338 if (ret < 0)339 {340 VBERROR(QString("Error reading volume for channel %1").arg(channel));341 return 0;342 }343 344 if (channel == 0)345 volume = tmpVol & 0xff; // left346 else if (channel == 1)347 volume = (tmpVol >> 8) & 0xff; // right348 else349 VBERROR("Invalid channel. Only stereo volume supported");350 351 return volume;352 }353 354 void AudioOutputOSS::SetVolumeChannel(int channel, int volume)355 {356 if (channel > 1)357 {358 // Don't support more than two channels!359 VBERROR(QString("Error setting channel %1. Only 2 ch volume supported")360 .arg(channel));361 return;362 }363 364 if (volume > 100)365 volume = 100;366 if (volume < 0)367 volume = 0;368 369 if (mixerfd >= 0)370 {371 int tmpVol = 0;372 if (channel == 0)373 tmpVol = (GetVolumeChannel(1) << 8) + volume;374 else375 tmpVol = (volume << 8) + GetVolumeChannel(0);376 377 int ret = ioctl(mixerfd, MIXER_WRITE(control), &tmpVol);378 if (ret < 0)379 VBERROR(QString("Error setting volume on channel %1").arg(channel));380 }381 }382 -
mythtv/libs/libmyth/audiooutputdx.cpp
482 482 | DSBCAPS_GLOBALFOCUS // Allows background playing 483 483 | DSBCAPS_LOCHARDWARE; // Needed for 5.1 on emu101k 484 484 485 if (!m_UseSPDIF)486 dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME; // Allow volume control487 488 485 dsbdesc.dwBufferBytes = soundcard_buffer_size; // buffer size 489 486 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf; 490 487 … … 555 552 return buffered; 556 553 } 557 554 558 int AudioOutputDX::GetVolumeChannel(int channel) const559 {560 HRESULT dsresult;561 long dxVolume = 0;562 int volume;563 564 if (m_UseSPDIF)565 return 100;566 567 dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);568 volume = (int)(pow(10,(float)dxVolume/20)*100);569 570 if (dsresult != DS_OK)571 {572 VBERROR(QString("Failed to get volume %1").arg(dxVolume));573 return volume;574 }575 576 VBAUDIO(QString("Got volume %1").arg(volume));577 return volume;578 }579 580 void AudioOutputDX::SetVolumeChannel(int channel, int volume)581 {582 HRESULT dsresult;583 float dbAtten = 20 * log10((float)volume/100);584 long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);585 586 if (m_UseSPDIF)587 return;588 589 // dxVolume is attenuation in 100ths of a decibel590 dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);591 592 if (dsresult != DS_OK)593 {594 VBERROR(QString("Failed to set volume %1").arg(dxVolume));595 return;596 }597 598 VBAUDIO(QString("Set volume %1").arg(dxVolume));599 }600 601 555 /* 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
7 7 #include "audiosettings.h" 8 8 #include "audiooutputsettings.h" 9 9 #include "mythcorecontext.h" 10 #include "volumebase.h"11 10 #include "output.h" 12 11 13 class MPUBLIC AudioOutput : public VolumeBase, publicOutputListeners12 class MPUBLIC AudioOutput : public OutputListeners 14 13 { 15 14 public: 16 15 class AudioDeviceConfig … … 38 37 static AudioOutput *OpenAudio( 39 38 const QString &audiodevice, const QString &passthrudevice, 40 39 AudioFormat format, int channels, int codec, int samplerate, 41 AudioOutputSource source, bool set_initial_vol, bool passthru, 42 int upmixer_startup = 0); 40 AudioOutputSource source, bool passthru, int upmixer_startup = 0); 43 41 static AudioOutput *OpenAudio(AudioSettings &settings, 44 42 bool willsuspendpa = true); 45 43 static AudioOutput *OpenAudio( … … 48 46 bool willsuspendpa = true); 49 47 50 48 AudioOutput() : 51 VolumeBase(),OutputListeners(),49 OutputListeners(), 52 50 lastError(QString::null), lastWarn(QString::null) {} 53 51 54 52 virtual ~AudioOutput(); -
mythtv/libs/libmyth/volumecontrolmanager.h
1 #ifndef VOLUMECONTROLMANAGER 2 #define VOLUMECONTROLMANAGER 3 4 #include "volumecontrol.h" 5 6 #include "mythexp.h" 7 8 #include <QHash> 9 #include <QSharedPointer> 10 #include <QString> 11 12 class MPUBLIC VolumeControlManager 13 { 14 public: 15 static QHash<QString, QString> Enumerate(); 16 static QSharedPointer<VolumeControl> GetControl(QString device); 17 }; 18 19 #endif // VOLUMECONTROLMANAGER -
mythtv/libs/libmyth/volumecontrolendpoint.h
1 #ifndef VOLUMECONTROLENDPOINT 2 #define VOLUMECONTROLENDPOINT 3 4 #include "volumecontrol.h" 5 6 #include <QHash> 7 #include <QAtomicInt> 8 9 #include <rpcsal.h> 10 #include <endpointvolume.h> 11 12 13 class VolumeControlEndpoint : public VolumeControl, 14 protected IAudioEndpointVolumeCallback 15 { 16 public: 17 static QHash<QString, QString> Enumerate(); 18 19 public: 20 VolumeControlEndpoint(QString device); 21 virtual ~VolumeControlEndpoint(); 22 23 public: 24 int volume() const; 25 void setVolume(int volume); 26 void increaseVolume(); 27 void decreaseVolume(); 28 29 bool mute() const; 30 void setMute(bool mute); 31 32 protected: 33 ULONG STDMETHODCALLTYPE AddRef(); 34 ULONG STDMETHODCALLTYPE Release(); 35 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface); 36 HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify); 37 38 private: 39 IAudioEndpointVolume* m_EndpointVolume; //< Endpoint volume interface 40 int m_Range; //< Range of mixer element 41 QAtomicInt m_Volume; //< Volume state cache 42 QAtomicInt m_Mute; //< Mute state cache 43 }; 44 45 #endif // VOLUMECONTROLWINDOWSENDPOINT -
mythtv/libs/libmyth/audiooutputdx.h
14 14 AudioOutputDX(const AudioSettings &settings); 15 15 virtual ~AudioOutputDX(); 16 16 17 virtual int GetVolumeChannel(int channel) const;18 virtual void SetVolumeChannel(int channel, int volume);19 20 17 protected: 21 18 virtual bool OpenDevice(void); 22 19 virtual void CloseDevice(void); -
mythtv/libs/libmyth/audiooutputalsa.h
17 17 AudioOutputALSA(const AudioSettings &settings); 18 18 virtual ~AudioOutputALSA(); 19 19 20 // Volume control21 virtual int GetVolumeChannel(int channel) const; // Returns 0-10022 virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol23 20 static QMap<QString, QString> *GetALSADevices(const char *type); 24 21 25 22 protected: … … 38 35 inline int SetParameters(snd_pcm_t *handle, snd_pcm_format_t format, 39 36 uint channels, uint rate, uint buffer_time, 40 37 uint period_time); 41 // Volume related42 bool OpenMixer(void);43 38 44 39 private: 45 40 snd_pcm_t *pcm_handle; … … 49 44 QMutex killAudioLock; 50 45 snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*, 51 46 snd_pcm_uframes_t); 52 struct {53 QString device;54 QString control;55 snd_mixer_t* handle;56 snd_mixer_elem_t* elem;57 long volmin;58 long volmax;59 long volrange;60 } m_mixer;61 62 47 }; 63 48 #endif -
mythtv/libs/libmyth/volumecontroloss.cpp
1 #include "volumecontroloss.h" 2 3 #include "mythverbose.h" 4 #include <algorithm> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <sys/ioctl.h> 8 #include <fcntl.h> 9 10 #include <QDir> 11 12 #include "mythconfig.h" 13 #ifdef HAVE_SYS_SOUNDCARD_H 14 #include <sys/soundcard.h> 15 #elif HAVE_SOUNDCARD_H 16 #include <soundcard.h> 17 #endif 18 19 static const unsigned long poll = 250; //< OSS control poll interval (ms) 20 21 // static 22 QHash<QString, QString> VolumeControlOSS::Enumerate() 23 { 24 QHash<QString, QString> result; 25 #if 1 26 int mixerfd = open("/dev/mixer", O_RDWR, 0); 27 28 if (mixerfd == -1) 29 { 30 VERBOSE(VB_IMPORTANT, 31 QString("VolumeControlOSS::Enumerate() - ERROR: " 32 "opening \"/dev/mixer\"")); 33 return result; 34 } 35 36 oss_sysinfo sysinfo; 37 if (ioctl(mixerfd, SNDCTL_SYSINFO, &sysinfo) == -1) 38 { 39 VERBOSE(VB_IMPORTANT, 40 QString("VolumeControlOSS::Enumerate() - ERROR: " 41 "obtaining system information")); 42 return result; 43 } 44 45 for (int mixer = 0; mixer < sysinfo.nummixers; ++mixer) 46 { 47 oss_mixerinfo info = { 48 dev: mixer 49 }; 50 51 if (ioctl(mixerfd, SNDCTL_MIXERINFO, &info) != -1) 52 result.insert(QString("OSS:%1").arg(info.devnode), info.name); 53 } 54 55 close(mixerfd); 56 57 #else 58 QDir devs("/dev", "mixer*", QDir::Name, QDir::System); 59 60 QFileInfoList files = devs.entryInfoList(); 61 QFileInfoList::Iterator file; 62 for (file = files.begin(); file != files.end(); ++file) 63 { 64 result.insert("OSS:" + file->absoluteFilePath(), 65 file->absoluteFilePath()); 66 } 67 68 devs.setPath("/dev/sound"); 69 files = devs.entryInfoList(); 70 for (file = files.begin(); file != files.end(); ++file) 71 { 72 result.insert("OSS:" + file->absoluteFilePath(), 73 file->absoluteFilePath()); 74 } 75 #endif 76 return result; 77 } 78 79 VolumeControlOSS::VolumeControlOSS(QString device) : 80 m_VolumeCtrl(-1), m_MuteCtrl(-1), m_Exit(false) 81 { 82 m_Mixer = open(device.toAscii().constData(), O_RDWR, 0); 83 84 if (m_Mixer == -1) 85 { 86 VERBOSE(VB_IMPORTANT, 87 QString("VolumeControlOSS::VolumeControlOSS() - ERROR: " 88 "opening \"%1\"").arg(device)); 89 return; 90 } 91 92 oss_sysinfo sysinfo; 93 if (ioctl(m_Mixer, SNDCTL_SYSINFO, &sysinfo) == -1) 94 { 95 VERBOSE(VB_IMPORTANT, 96 QString("VolumeControlOSS::VolumeControlOSS() - ERROR: " 97 "obtaining system information")); 98 return; 99 } 100 101 for (m_MixerDev = 0; m_MixerDev < sysinfo.nummixers; ++m_MixerDev) 102 { 103 oss_mixerinfo info = { 104 dev: m_MixerDev 105 }; 106 107 if (ioctl(m_Mixer, SNDCTL_MIXERINFO, &info) != -1) 108 if (QString(info.devnode) == device) 109 break; 110 } 111 112 int extensions = m_MixerDev; 113 if (ioctl(m_Mixer, SNDCTL_MIX_NREXT, &extensions) == -1) 114 { 115 VERBOSE(VB_IMPORTANT, 116 QString("VolumeControlOSS::VolumeControlOSS() - ERROR: " 117 "obtaining number of extensions")); 118 return; 119 } 120 121 for (int control = 0; control < extensions; ++control) 122 { 123 oss_mixext info = { 124 dev: m_MixerDev, 125 ctrl: control 126 }; 127 128 if (ioctl(m_Mixer, SNDCTL_MIX_EXTINFO, &info) == -1) 129 continue; 130 131 switch (info.type) 132 { 133 case MIXT_MONODB: 134 case MIXT_MONOSLIDER: 135 case MIXT_MONOSLIDER16: 136 case MIXT_SLIDER: 137 case MIXT_STEREOSLIDER: 138 case MIXT_STEREOSLIDER16: 139 if (m_VolumeCtrl == -1) 140 { 141 m_VolumeCtrl = info.ctrl; 142 m_VolumeMax = info.maxvalue; 143 m_VolumeType = info.type; 144 m_VolumeTimestamp = info.timestamp; 145 } 146 break; 147 148 case MIXT_ONOFF: 149 case MIXT_MUTE: 150 if (m_MuteCtrl == -1) 151 { 152 m_MuteCtrl = info.ctrl; 153 m_MuteTimestamp = info.timestamp; 154 } 155 break; 156 } 157 158 if (m_VolumeCtrl != -1 && m_MuteCtrl != -1) 159 break; 160 } 161 162 m_Range = std::min(std::max(1, m_VolumeMax), 100); 163 164 if (m_VolumeCtrl != -1) 165 start(); 166 } 167 168 VolumeControlOSS::~VolumeControlOSS() 169 { 170 m_Exit = true; 171 172 if (isRunning()) 173 wait(); 174 175 if (m_Mixer != -1) 176 close(m_Mixer); 177 } 178 179 int VolumeControlOSS::volume() const 180 { 181 int volume = 0; 182 183 if (m_VolumeCtrl != -1) 184 { 185 if (m_MuteCtrl != -1 || !mute()) 186 { 187 oss_mixer_value value; 188 memset(&value, 0, sizeof(value)); 189 190 value.dev = m_MixerDev; 191 value.ctrl = m_VolumeCtrl; 192 value.timestamp = m_VolumeTimestamp; 193 194 if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1) 195 { 196 switch (m_VolumeType) 197 { 198 case MIXT_MONODB: 199 case MIXT_MONOSLIDER: 200 volume = value.value & 0xFF; 201 break; 202 203 case MIXT_MONOSLIDER16: 204 volume = value.value & 0xFFFF; 205 break; 206 207 case MIXT_SLIDER: 208 volume = value.value & 0x7FFFFFFF; 209 break; 210 211 case MIXT_STEREOSLIDER: 212 volume = std::max(value.value & 0xFF, 213 (value.value >> 8) & 0xFF); 214 break; 215 216 case MIXT_STEREOSLIDER16: 217 volume = std::max(value.value & 0xFFFF, 218 (value.value >> 16) & 0xFFFF); 219 break; 220 } 221 222 volume = ((200 * volume) + m_VolumeMax) / (2 * m_VolumeMax); 223 } 224 } 225 else 226 volume = m_Volume; 227 } 228 229 VERBOSE(VB_AUDIO, 230 QString("VolumeControlOSS::volume() = %1") 231 .arg(volume)); 232 233 return volume; 234 } 235 236 void VolumeControlOSS::setVolume(int volume) 237 { 238 VERBOSE(VB_AUDIO, 239 QString("VolumeControlOSS::setVolume(%1)") 240 .arg(volume)); 241 242 volume = std::min(std::max(0, volume), 100); 243 244 if (mute() && volume > VolumeControlOSS::volume()) 245 setMute(false); 246 247 if (m_VolumeCtrl != -1 && (m_MuteCtrl != -1 || !mute())) 248 { 249 oss_mixer_value value; 250 memset(&value, 0, sizeof(value)); 251 252 value.dev = m_MixerDev; 253 value.ctrl = m_VolumeCtrl; 254 value.timestamp = m_VolumeTimestamp; 255 value.value = (m_VolumeMax * volume) / 100; 256 257 switch (m_VolumeType) 258 { 259 case MIXT_STEREOSLIDER: 260 value.value = value.value | (value.value << 8); 261 break; 262 263 case MIXT_STEREOSLIDER16: 264 value.value = value.value | (value.value << 16); 265 break; 266 } 267 268 ioctl(m_Mixer, SNDCTL_MIX_WRITE, &value); 269 } 270 271 if (m_Volume.fetchAndStoreRelaxed(volume) != volume) 272 emit changedVolume(volume); 273 } 274 275 void VolumeControlOSS::increaseVolume() 276 { 277 setVolume((volume() * m_Range + 100) / m_Range); 278 } 279 280 void VolumeControlOSS::decreaseVolume() 281 { 282 setVolume((volume() * m_Range - 100) / m_Range); 283 } 284 285 bool VolumeControlOSS::mute() const 286 { 287 bool mute = false; 288 289 if (m_VolumeCtrl != -1) 290 { 291 oss_mixer_value value; 292 memset(&value, 0, sizeof(value)); 293 294 value.dev = m_MixerDev; 295 296 if (m_MuteCtrl != -1) 297 { 298 value.ctrl = m_MuteCtrl; 299 value.timestamp = m_MuteTimestamp; 300 301 if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1) 302 mute = value.value; 303 } 304 else 305 { 306 value.ctrl = m_VolumeCtrl; 307 value.timestamp = m_VolumeTimestamp; 308 309 if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1) 310 mute = !value.value; 311 } 312 } 313 314 VERBOSE(VB_AUDIO, 315 QString("VolumeControlOSS::mute() = %1") 316 .arg(mute ? "mute" : "unmute")); 317 318 return mute; 319 } 320 321 void VolumeControlOSS::setMute(bool mute) 322 { 323 VERBOSE(VB_AUDIO, 324 QString("VolumeControlOSS::setMute(%1)") 325 .arg(mute ? "mute" : "unmute")); 326 327 if (m_VolumeCtrl != -1) 328 { 329 oss_mixer_value value; 330 memset(&value, 0, sizeof(value)); 331 332 value.dev = m_MixerDev; 333 334 if (m_MuteCtrl != -1) 335 { 336 value.ctrl = m_MuteCtrl; 337 value.timestamp = m_MuteTimestamp; 338 value.value = mute; 339 } 340 else 341 { 342 value.ctrl = m_VolumeCtrl; 343 value.timestamp = m_VolumeTimestamp; 344 value.value = mute ? 0 : (m_VolumeMax * m_Volume) / 100; 345 346 switch (m_VolumeType) 347 { 348 case MIXT_STEREOSLIDER: 349 value.value = value.value | (value.value << 8); 350 break; 351 352 case MIXT_STEREOSLIDER16: 353 value.value = value.value | (value.value << 16); 354 break; 355 } 356 } 357 358 ioctl(m_Mixer, SNDCTL_MIX_WRITE, &value); 359 } 360 361 if (m_Mute.fetchAndStoreRelaxed(mute) != mute) 362 emit changedMute(mute); 363 } 364 365 void VolumeControlOSS::run() 366 { 367 VERBOSE(VB_AUDIO, 368 QString("VolumeControlOSS::run() - begin")); 369 370 m_Volume = volume(); 371 m_Mute = mute(); 372 373 while(!m_Exit) 374 { 375 msleep(poll); 376 377 int pollvolume = volume(); 378 if (m_Volume.fetchAndStoreRelaxed(pollvolume) != pollvolume) 379 emit changedVolume(pollvolume); 380 381 bool pollmute = mute(); 382 if (m_Mute.fetchAndStoreRelaxed(pollmute) != pollmute) 383 emit changedMute(pollmute); 384 } 385 386 VERBOSE(VB_AUDIO, 387 QString("VolumeControlOSS::run() - end")); 388 } 389 -
mythtv/programs/mythfrontend/globalsettings.cpp
29 29 #include "iso639.h" 30 30 #include "playbackbox.h" 31 31 #include "globalsettings.h" 32 #include "libmyth/volumecontrolmanager.h" 32 33 #include "recordingprofile.h" 33 34 #include "mythxdisplay.h" 34 35 #include "DisplayRes.h" … … 511 512 return gc; 512 513 } 513 514 514 static HostCheckBox *MythControlsVolume()515 {516 HostCheckBox *gc = new HostCheckBox("MythControlsVolume");517 gc->setLabel(QObject::tr("Use internal volume controls"));518 gc->setValue(true);519 gc->setHelpText(QObject::tr("If enabled, MythTV will control the PCM and "520 "master mixer volume. Disable this option if you prefer "521 "to control the volume externally (for example, using "522 "your amplifier) or if you use an external mixer program."));523 return gc;524 }525 526 515 static HostComboBox *MixerDevice() 527 516 { 528 517 HostComboBox *gc = new HostComboBox("MixerDevice", true); 529 518 gc->setLabel(QObject::tr("Mixer device")); 519 gc->addSelection(QObject::tr("Disabled"), QString()); 530 520 531 #ifdef USING_OSS 532 QDir dev("/dev", "mixer*", QDir::Name, QDir::System); 533 gc->fillSelectionsFromDir(dev); 521 QHash<QString, QString> controls = VolumeControlManager::Enumerate(); 534 522 535 dev.setPath("/dev/sound");536 if (dev.exists())523 for (QHash<QString, QString>::const_iterator control = controls.begin(); 524 control != controls.end(); ++control) 537 525 { 538 gc-> fillSelectionsFromDir(dev);526 gc->addSelection(control.value(), control.key()); 539 527 } 540 #endif541 #ifdef USING_ALSA542 gc->addSelection("ALSA:default", "ALSA:default");543 #endif544 #ifdef USING_MINGW545 gc->addSelection("DirectX:", "DirectX:");546 gc->addSelection("Windows:", "Windows:");547 #endif548 #if !defined(USING_MINGW)549 gc->addSelection("software", "software");550 gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" "551 "lets MythTV control the volume of all audio at the "552 "expense of a slight quality loss."));553 #endif554 528 555 529 return gc; 556 530 } 557 531 558 static const char* MixerControlControls[] = { "PCM",559 "Master" };560 561 static HostComboBox *MixerControl()562 {563 HostComboBox *gc = new HostComboBox("MixerControl", true);564 gc->setLabel(QObject::tr("Mixer controls"));565 for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);566 ++i)567 {568 gc->addSelection(QObject::tr(MixerControlControls[i]),569 MixerControlControls[i]);570 }571 572 gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));573 return gc;574 }575 576 static HostSlider *MixerVolume()577 {578 HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);579 gs->setLabel(QObject::tr("Master mixer volume"));580 gs->setValue(70);581 gs->setHelpText(QObject::tr("Initial volume for the Master mixer. "582 "This affects all sound created by the audio device. "583 "Note: Do not set this too low."));584 return gs;585 }586 587 static HostSlider *PCMVolume()588 {589 HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);590 gs->setLabel(QObject::tr("PCM mixer volume"));591 gs->setValue(70);592 gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "593 "volume keys in MythTV will adjust this parameter."));594 return gs;595 }596 597 532 static HostCheckBox *DecodeExtraAudio() 598 533 { 599 534 HostCheckBox *gc = new HostCheckBox("DecodeExtraAudio"); … … 3358 3293 return gs; 3359 3294 } 3360 3295 3361 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup 3296 static ConfigurationGroup *AudioMixerSettingsGroup() 3362 3297 { 3363 public: 3364 AudioMixerSettingsGroup() : 3365 TriggeredConfigurationGroup(false, true, false, false) 3366 { 3367 setLabel(QObject::tr("Audio Mixer")); 3368 setUseLabel(false); 3298 ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false); 3299 3300 vcg->setLabel(QObject::tr("Audio Mixer")); 3301 vcg->setUseLabel(false); 3369 3302 3370 Setting *volumeControl = MythControlsVolume(); 3371 addChild(volumeControl); 3303 vcg->addChild(MixerDevice()); 3372 3304 3373 // Mixer settings 3374 ConfigurationGroup *settings = 3375 new VerticalConfigurationGroup(false, true, false, false); 3376 settings->addChild(MixerDevice()); 3377 settings->addChild(MixerControl()); 3378 settings->addChild(MixerVolume()); 3379 settings->addChild(PCMVolume()); 3305 return vcg; 3306 } 3380 3307 3381 ConfigurationGroup *dummy =3382 new VerticalConfigurationGroup(false, true, false, false);3383 3384 // Show Mixer config only if internal volume controls enabled3385 setTrigger(volumeControl);3386 addTarget("0", dummy);3387 addTarget("1", settings);3388 }3389 };3390 3391 3308 static HostComboBox *MythLanguage() 3392 3309 { 3393 3310 HostComboBox *gc = new HostComboBox("Language"); … … 4085 4002 4086 4003 addChild(new AudioConfigSettings()); 4087 4004 4088 addChild( newAudioMixerSettingsGroup());4005 addChild(AudioMixerSettingsGroup()); 4089 4006 4090 4007 VerticalConfigurationGroup *general = 4091 4008 new VerticalConfigurationGroup(false, true, false, false); -
mythtv/programs/mythtranscode/transcode.cpp
137 137 return last_audiotime; 138 138 } 139 139 140 virtual int GetVolumeChannel(int) const141 {142 // Do nothing143 return 100;144 }145 virtual void SetVolumeChannel(int, int)146 {147 // Do nothing148 }149 virtual void SetVolumeAll(int)150 {151 // Do nothing152 }153 virtual uint GetCurrentVolume(void) const154 {155 // Do nothing156 return 100;157 }158 virtual void SetCurrentVolume(int)159 {160 // Do nothing161 }162 virtual void AdjustCurrentVolume(int)163 {164 // Do nothing165 }166 virtual void SetMute(bool)167 {168 // Do nothing169 }170 virtual void ToggleMute(void)171 {172 // Do nothing173 }174 virtual MuteState GetMuteState(void) const175 {176 // Do nothing177 return kMuteOff;178 }179 virtual MuteState IterateMutedChannels(void)180 {181 // Do nothing182 return kMuteOff;183 }184 140 virtual bool ToggleUpmix(void) 185 141 { 186 142 // Do nothing 187 143 return false; 188 144 } 189 145 190 virtual void SetSWVolume(int new_volume, bool save)191 {192 // Do nothing193 return;194 }195 virtual int GetSWVolume(void)196 {197 // Do nothing198 return 100;199 }200 201 146 // These are pure virtual in AudioOutput, but we don't need them here 202 147 virtual void bufferOutputData(bool){ return; } 203 148 virtual int readOutputData(unsigned char*, int ){ return 0; }
