Ticket #7517: volume_control_trunk_r25559.patch
File volume_control_trunk_r25559.patch, 133.6 KB (added by , 14 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()), … … 1174 1178 if (volume_control && gPlayer->getOutput()) 1175 1179 { 1176 1180 if (up_or_down) 1177 gPlayer-> getOutput()->AdjustCurrentVolume(2);1181 gPlayer->incVolume(); 1178 1182 else 1179 gPlayer-> getOutput()->AdjustCurrentVolume(-2);1183 gPlayer->decVolume(); 1180 1184 showVolume(true); 1181 1185 } 1182 1186 } … … 1197 1201 { 1198 1202 if (volume_control && gPlayer->getOutput()) 1199 1203 { 1200 gPlayer-> getOutput()->ToggleMute();1204 gPlayer->toggleMute(); 1201 1205 showVolume(true); 1202 1206 } 1203 1207 } … … 1239 1243 { 1240 1244 if (on_or_off) 1241 1245 { 1242 volume_status->SetUsed(gPlayer->get Output()->GetCurrentVolume());1246 volume_status->SetUsed(gPlayer->getVolume()); 1243 1247 volume_status->SetOrder(0); 1244 1248 volume_status->refresh(); 1245 1249 volume_display_timer->setSingleShot(true); … … 2454 2458 2455 2459 return time_string; 2456 2460 } 2461 2462 void PlaybackBoxMusic::VolumeChanged(int) 2463 { 2464 showVolume(true); 2465 } 2466 2467 void PlaybackBoxMusic::MuteChanged(bool) 2468 { 2469 showVolume(true); 2470 } -
mythplugins/mythmusic/mythmusic/musicplayer.h
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 … … 306 308 // TODO: Error checking that device is opened correctly! 307 309 m_output = AudioOutput::OpenAudio( 308 310 adevice, pdevice, FORMAT_S16, 2, 0, 44100, 309 AUDIOOUTPUT_MUSIC, true,false,311 AUDIOOUTPUT_MUSIC, false, 310 312 gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1); 311 313 312 314 m_output->setBufferSize(256 * 1024); … … 881 883 882 884 void MusicPlayer::incVolume() 883 885 { 884 if ( getOutput())886 if (volume_control) 885 887 { 886 getOutput()->AdjustCurrentVolume(2);888 volume_control->increaseVolume(); 887 889 sendVolumeChangedEvent(); 888 890 } 889 891 } 890 892 891 893 void MusicPlayer::decVolume() 892 894 { 893 if ( getOutput())895 if (volume_control) 894 896 { 895 getOutput()->AdjustCurrentVolume(-2);897 volume_control->decreaseVolume(); 896 898 sendVolumeChangedEvent(); 897 899 } 898 900 } 899 901 900 902 void MusicPlayer::setVolume(int volume) 901 903 { 902 if ( getOutput())904 if (volume_control) 903 905 { 904 getOutput()->SetCurrentVolume(volume);906 volume_control->setVolume(volume); 905 907 sendVolumeChangedEvent(); 906 908 } 907 909 } 908 910 909 911 uint MusicPlayer::getVolume(void) const 910 912 { 911 if ( m_output)912 return m_output->GetCurrentVolume();913 if (volume_control) 914 return volume_control->volume(); 913 915 return 0; 914 916 } 915 917 916 918 void MusicPlayer::toggleMute(void) 917 919 { 918 if ( m_output)920 if (volume_control) 919 921 { 920 m_output->ToggleMute();922 volume_control->setMute(!volume_control->mute()); 921 923 sendVolumeChangedEvent(); 922 924 } 923 925 } 924 926 925 MuteState MusicPlayer::getMuteState(void) const927 bool MusicPlayer::isMuted(void) const 926 928 { 927 if ( m_output)928 return m_output->GetMuteState();929 return kMuteAll;929 if (volume_control) 930 return volume_control->mute(); 931 return true; 930 932 } 931 933 932 934 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 … … 3658 3665 { { ! enabled audio_alsa || die "ERROR: Alsa >= 1.0.16 required"; } && 3659 3666 disable audio_alsa; } 3660 3667 3668 # OSS probe 3669 if ! disabled audio_oss ; then 3670 if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h && 3671 check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3672 disable soundcard_h 3673 enable sys_soundcard_h 3674 prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include" 3675 elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h && 3676 check_cpp_condition /usr/local/"${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/local/${libdir_name}/oss/include" 3680 else 3681 if enabled soundcard_h ; then 3682 check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" && 3683 enable audio_oss || 3684 disable audio_oss 3685 elif enabled sys_soundcard_h ; then 3686 check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" && 3687 enable audio_oss || 3688 disable audio_oss 3689 fi 3690 fi 3691 fi 3661 3692 3662 3693 # JACK probe 3663 3694 ! 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
245 245 itv(NULL), 246 246 // Audio 247 247 audioSamples(NULL), 248 internal_vol(false),249 248 disable_passthru(false), 250 249 dummy_frame(NULL), 251 250 // DVD … … 266 265 av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR); 267 266 av_log_set_callback(myth_av_log); 268 267 269 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);270 268 271 269 audioIn.sample_size = -32; // force SetupAudioStream to run once 272 270 itv = GetPlayer()->GetInteractiveTV(); … … 4376 4374 bool passthru = false; 4377 4375 4378 4376 if (ctx->codec_id == CODEC_ID_AC3) 4379 passthru = m_audio->CanAC3() && 4380 ctx->channels >= (int)m_audio->GetMaxChannels() && 4381 !internal_vol; 4377 passthru = m_audio->CanAC3(); 4382 4378 else if (ctx->codec_id == CODEC_ID_DTS) 4383 passthru = m_audio->CanDTS() && !internal_vol;4379 passthru = m_audio->CanDTS(); 4384 4380 4385 4381 passthru &= m_audio->CanPassthrough(); 4386 4382 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" … … 294 294 void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*); 295 295 void ClearUDPNotifyEvents(void); 296 296 297 void VolumeChanged(int volume); 298 void MuteChanged(bool mute); 299 297 300 protected: 298 301 void OSDDialogEvent(int result, QString text, QString action); 299 302 … … 492 495 493 496 vector<long long> TeardownAllPlayers(PlayerContext*); 494 497 void RestartAllPlayers(PlayerContext *lctx, 495 const vector<long long> &pos, 496 MuteState mctx_mute); 498 const vector<long long> &pos); 497 499 void RestartMainPlayer(PlayerContext *mctx); 498 500 499 501 void PxPToggleView( PlayerContext *actx, bool wantPBP); … … 722 724 /// Picture attribute to modify (on arrow left or right) 723 725 PictureAttribute adjustingPictureAttribute; 724 726 727 QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface 728 725 729 // Ask Allow state 726 730 QMap<QString,AskProgramInfo> askAllowPrograms; 727 731 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
401 401 402 402 bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget, 403 403 TVState desiredState, 404 WId embedwinid, const QRect *embedbounds, 405 bool muted) 404 WId embedwinid, const QRect *embedbounds) 406 405 { 407 406 int exact_seeking = gCoreContext->GetNumSetting("ExactSeeking", 0); 408 407 … … 415 414 416 415 MythPlayer *player = NULL; 417 416 if (kState_WatchingBD == desiredState) 418 player = new MythBDPlayer( muted);417 player = new MythBDPlayer(); 419 418 else if (kState_WatchingDVD == desiredState) 420 player = new MythDVDPlayer( muted);419 player = new MythDVDPlayer(); 421 420 else 422 player = new MythPlayer( muted);421 player = new MythPlayer(); 423 422 424 423 if (nohardwaredecoders) 425 424 player->DisableHardwareDecoders(); … … 471 470 VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg); 472 471 } 473 472 } 474 else if (pipState == kPBPRight)475 player->SetMuted(true);476 473 477 474 return StartPlaying(-1); 478 475 } -
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
1053 1053 1054 1054 gCoreContext->addListener(this); 1055 1055 1056 volumeControl = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 1057 if (volumeControl) 1058 { 1059 connect(volumeControl.data(), SIGNAL(changedVolume(int)), 1060 this, SLOT(VolumeChanged(int)), Qt::QueuedConnection); 1061 connect(volumeControl.data(), SIGNAL(changedMute(bool)), 1062 this, SLOT(MuteChanged(bool)), Qt::QueuedConnection); 1063 } 1064 1065 VERBOSE(VB_PLAYBACK, LOC + "ctor -- end"); 1066 1056 1067 QMutexLocker lock(&initFromDBLock); 1057 1068 initFromDBDone = true; 1058 1069 initFromDBWait.wakeAll(); … … 5145 5156 } 5146 5157 } 5147 5158 5148 MuteState mctx_mute = kMuteOff;5149 mctx->LockDeletePlayer(__FILE__, __LINE__);5150 if (mctx->player)5151 mctx_mute = mctx->player->GetMuteState();5152 mctx->UnlockDeletePlayer(__FILE__, __LINE__);5153 5154 5159 vector<long long> pos = TeardownAllPlayers(mctx); 5155 5160 5156 5161 if (wantPBP) … … 5168 5173 } 5169 5174 } 5170 5175 5171 RestartAllPlayers(mctx, pos , mctx_mute);5176 RestartAllPlayers(mctx, pos); 5172 5177 5173 5178 VERBOSE(VB_PLAYBACK, LOC + 5174 5179 QString("PxPToggleType() converting from %1 to %2 -- end") … … 5312 5317 * \brief Recreate Main and PIP windows. Could be either PIP or PBP views. 5313 5318 */ 5314 5319 void TV::RestartAllPlayers(PlayerContext *lctx, 5315 const vector<long long> &pos, 5316 MuteState mctx_mute) 5320 const vector<long long> &pos) 5317 5321 { 5318 5322 QString loc = LOC + QString("RestartAllPlayers(): "); 5319 5323 … … 5360 5364 pipctx->LockDeletePlayer(__FILE__, __LINE__); 5361 5365 if (pipctx->player) 5362 5366 { 5363 pipctx->player->SetMuted(true);5364 5367 pipctx->player->JumpToFrame(pos[i]); 5365 5368 } 5366 5369 pipctx->UnlockDeletePlayer(__FILE__, __LINE__); … … 5372 5375 ForceNextStateNone(pipctx); 5373 5376 } 5374 5377 } 5375 5376 // If old main player had a kMuteAll | kMuteOff setting,5377 // apply old main player's mute setting to new main player.5378 mctx->LockDeletePlayer(__FILE__, __LINE__);5379 if (mctx->player && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))5380 mctx->player->SetMuteState(mctx_mute);5381 mctx->UnlockDeletePlayer(__FILE__, __LINE__);5382 5378 } 5383 5379 5384 5380 void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx) … … 5406 5402 return; 5407 5403 } 5408 5404 5409 MuteState mctx_mute = mctx->player->GetMuteState();5410 5405 mctx->deletePlayerLock.unlock(); 5411 5406 pipctx->deletePlayerLock.unlock(); 5412 5407 … … 5420 5415 playerActive = (ctx_index == playerActive) ? 5421 5416 0 : ((ctx_index == 0) ? ctx_index : playerActive); 5422 5417 5423 RestartAllPlayers(mctx, pos , mctx_mute);5418 RestartAllPlayers(mctx, pos); 5424 5419 5425 5420 SetActive(mctx, playerActive, false); 5426 5421 … … 5441 5436 mctx->deletePlayerLock.unlock(); 5442 5437 return; 5443 5438 } 5444 5445 MuteState mctx_mute = mctx->player->GetMuteState();5446 5447 // HACK - FIXME5448 // workaround muted audio when Player is re-created5449 mctx_mute = kMuteOff;5450 // FIXME - end5451 5439 mctx->deletePlayerLock.unlock(); 5452 5440 5453 5441 vector<long long> pos = TeardownAllPlayers(mctx); 5454 RestartAllPlayers(mctx, pos , mctx_mute);5442 RestartAllPlayers(mctx, pos); 5455 5443 SetActive(mctx, playerActive, false); 5456 5444 5457 5445 VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end"); … … 6217 6205 if (mctx != ctx) 6218 6206 PIPRemovePlayer(mctx, ctx); 6219 6207 6220 bool muted = false;6221 ctx->LockDeletePlayer(__FILE__, __LINE__);6222 if (ctx->player && ctx->player->IsMuted())6223 muted = true;6224 ctx->UnlockDeletePlayer(__FILE__, __LINE__);6225 6226 6208 // pause the decoder first, so we're not reading too close to the end. 6227 6209 ctx->buffer->IgnoreLiveEOF(true); 6228 6210 ctx->buffer->StopReads(); … … 6274 6256 6275 6257 if (ctx->CreatePlayer( 6276 6258 this, GetMythMainWindow(), ctx->GetState(), 6277 mctx->embedWinID, &mctx->embedBounds , muted))6259 mctx->embedWinID, &mctx->embedBounds)) 6278 6260 { 6279 6261 ScheduleStateChange(ctx); 6280 6262 ok = true; … … 7889 7871 7890 7872 void TV::ChangeVolume(PlayerContext *ctx, bool up) 7891 7873 { 7892 ctx->LockDeletePlayer(__FILE__, __LINE__); 7893 if (!ctx->player) 7874 if (volumeControl) 7894 7875 { 7895 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 7896 return; 7876 if (up) 7877 volumeControl->increaseVolume(); 7878 else 7879 volumeControl->decreaseVolume(); 7897 7880 } 7898 uint curvol = ctx->player->AdjustVolume((up) ? +2 : -2);7899 ctx->UnlockDeletePlayer(__FILE__, __LINE__);7900 7901 if (!browsemode)7902 {7903 UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"),7904 QString::number(curvol),7905 kOSDFunctionalType_PictureAdjust, "%", curvol * 10,7906 kOSDTimeout_Med);7907 SetUpdateOSDPosition(false);7908 }7909 7881 } 7910 7882 7911 7883 void TV::ToggleTimeStretch(PlayerContext *ctx) … … 8048 8020 8049 8021 void TV::ToggleMute(PlayerContext *ctx, const bool muteIndividualChannels) 8050 8022 { 8051 ctx->LockDeletePlayer(__FILE__, __LINE__); 8052 if (!ctx->player || !ctx->player->HasAudioOut()) 8053 { 8054 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 8055 return; 8056 } 8057 8058 MuteState mute_status; 8059 8060 if (!muteIndividualChannels) 8061 { 8062 ctx->player->SetMuted(!ctx->player->IsMuted()); 8063 mute_status = (ctx->player->IsMuted()) ? kMuteAll : kMuteOff; 8064 } 8065 else 8066 { 8067 mute_status = ctx->player->IncrMuteState(); 8068 } 8069 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 8070 8071 QString text; 8072 8073 switch (mute_status) 8074 { 8075 case kMuteOff: text = tr("Mute Off"); break; 8076 case kMuteAll: text = tr("Mute On"); break; 8077 case kMuteLeft: text = tr("Left Channel Muted"); break; 8078 case kMuteRight: text = tr("Right Channel Muted"); break; 8079 } 8080 8081 SetOSDMessage(ctx, text); 8023 if (volumeControl) 8024 volumeControl->setMute(!volumeControl->mute()); 8082 8025 } 8083 8026 8084 8027 void TV::ToggleSleepTimer(const PlayerContext *ctx) … … 9038 8981 { 9039 8982 value = ctx->player->getVideoOutput()->GetPictureAttribute(attr); 9040 8983 } 9041 else if (ctx->player->HasAudioOut() )8984 else if (ctx->player->HasAudioOut() && volumeControl) 9042 8985 { 9043 value = ctx->player->GetVolume();8986 value = volumeControl->volume(); 9044 8987 title = tr("Adjust Volume"); 9045 8988 } 9046 8989 } … … 11942 11885 ReturnPlayerLock(mctx); 11943 11886 } 11944 11887 11888 void TV::VolumeChanged(int volume) 11889 { 11890 if (!browsemode) 11891 { 11892 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 11893 UpdateOSDStatus(actx, tr("Adjust Volume"), tr("Volume"), 11894 QString::number(volume), 11895 kOSDFunctionalType_PictureAdjust, "%", 10 * volume); 11896 SetUpdateOSDPosition(false); 11897 ReturnPlayerLock(actx); 11898 } 11899 } 11900 11901 void TV::MuteChanged(bool mute) 11902 { 11903 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 11904 SetOSDMessage(actx, mute ? tr("Mute On") : tr("Mute Off")); 11905 ReturnPlayerLock(actx); 11906 } 11907 11908 11945 11909 OSD *TV::GetOSDL(const char *file, int location) 11946 11910 { 11947 11911 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
300 300 301 301 // Audio 302 302 short int *audioSamples; 303 bool internal_vol;304 303 bool disable_passthru; 305 304 306 305 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(); … … 493 455 pa_stream_set_overflow_callback(pstream, BufferFlowCallback, (char*)"over"); 494 456 pa_stream_set_underflow_callback(pstream, BufferFlowCallback, 495 457 (char*)"under"); 496 if (set_initial_vol) 497 { 498 int volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80); 499 pa_cvolume_set(&volume_control, channels, 500 (float)volume * (float)PA_VOLUME_NORM / 100.0f); 501 } 502 else 503 pa_cvolume_reset(&volume_control, channels); 458 pa_cvolume_reset(&volume_control, channels); 504 459 505 460 fragment_size = (samplerate * 25 * output_bytes_per_frame) / 1000; 506 461 -
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
410 410 411 411 return 0; 412 412 } 413 <<<<<<< .mine 414 ======= 413 415 414 416 415 417 /* Our Jack XRun callback. … … 489 491 chan_volumes[i] = volume; 490 492 } 491 493 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 494 /* We don't need an audio output thread for Jack 529 495 Everything handled by callbacks here 530 496 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 { … … 143 145 144 146 mingw { 145 147 DEFINES += USING_MINGW 146 SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp 147 HEADERS += mediamonitor-windows.h audiooutputwin.h audiooutputdx.h 148 LIBS += -lpthread -lwinmm -lws2_32 148 SOURCES += mediamonitor-windows.cpp 149 HEADERS += mediamonitor-windows.h 150 SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp 151 HEADERS += audiooutputwin.h audiooutputdx.h volumecontrolendpoint.h 152 LIBS += -lpthread -lwinmm -lws2_32 -lole32 149 153 } 150 154 151 155 macx { 152 HEADERS += audiooutputca.h 153 SOURCES += audiooutputca.cpp 156 DEFINES += USE_COREAUDIO 157 HEADERS += audiooutputca.h volumecontrolcoreaudio.h 158 SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp 154 159 HEADERS += mythcdrom-darwin.h 155 160 SOURCES += mythcdrom-darwin.cpp 156 161 … … 189 194 190 195 using_alsa { 191 196 DEFINES += USE_ALSA 192 HEADERS += audiooutputalsa.h 193 SOURCES += audiooutputalsa.cpp 197 HEADERS += audiooutputalsa.h volumecontrolalsa.h 198 SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp 194 199 } 195 200 196 201 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 int volume = 0;283 284 QString device = gCoreContext->GetSetting("MixerDevice", "/dev/mixer");285 if (device.toLower() == "software")286 return;287 288 QByteArray dev = device.toAscii();289 mixerfd = open(dev.constData(), O_RDONLY);290 291 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");292 293 if (controlLabel == "Master")294 control = SOUND_MIXER_VOLUME;295 else296 control = SOUND_MIXER_PCM;297 298 if (mixerfd < 0)299 {300 VBERROR(QString("Unable to open mixer: '%1'").arg(device));301 return;302 }303 304 if (set_initial_vol)305 {306 int tmpVol;307 volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);308 tmpVol = (volume << 8) + volume;309 int ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);310 if (ret < 0)311 VBERROR(QString("Error Setting initial Master Volume") + ENO);312 313 volume = gCoreContext->GetNumSetting("PCMMixerVolume", 80);314 tmpVol = (volume << 8) + volume;315 ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);316 if (ret < 0)317 VBERROR(QString("Error setting initial PCM Volume") + ENO);318 }319 }320 321 void AudioOutputOSS::VolumeCleanup()322 {323 if (mixerfd >= 0)324 {325 close(mixerfd);326 mixerfd = -1;327 }328 }329 330 int AudioOutputOSS::GetVolumeChannel(int channel) const331 {332 int volume=0;333 int tmpVol=0;334 335 if (mixerfd <= 0)336 return 100;337 338 int ret = ioctl(mixerfd, MIXER_READ(control), &tmpVol);339 if (ret < 0)340 {341 VBERROR(QString("Error reading volume for channel %1").arg(channel));342 return 0;343 }344 345 if (channel == 0)346 volume = tmpVol & 0xff; // left347 else if (channel == 1)348 volume = (tmpVol >> 8) & 0xff; // right349 else350 VBERROR("Invalid channel. Only stereo volume supported");351 352 return volume;353 }354 355 void AudioOutputOSS::SetVolumeChannel(int channel, int volume)356 {357 if (channel > 1)358 {359 // Don't support more than two channels!360 VBERROR(QString("Error setting channel %1. Only 2 ch volume supported")361 .arg(channel));362 return;363 }364 365 if (volume > 100)366 volume = 100;367 if (volume < 0)368 volume = 0;369 370 if (mixerfd >= 0)371 {372 int tmpVol = 0;373 if (channel == 0)374 tmpVol = (GetVolumeChannel(1) << 8) + volume;375 else376 tmpVol = (volume << 8) + GetVolumeChannel(0);377 378 int ret = ioctl(mixerfd, MIXER_WRITE(control), &tmpVol);379 if (ret < 0)380 VBERROR(QString("Error setting volume on channel %1").arg(channel));381 }382 }383 -
mythtv/libs/libmyth/audiooutputdx.cpp
481 481 | DSBCAPS_GLOBALFOCUS // Allows background playing 482 482 | DSBCAPS_LOCHARDWARE; // Needed for 5.1 on emu101k 483 483 484 if (!m_UseSPDIF)485 dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME; // Allow volume control486 487 484 dsbdesc.dwBufferBytes = soundcard_buffer_size; // buffer size 488 485 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf; 489 486 … … 554 551 return buffered; 555 552 } 556 553 557 int AudioOutputDX::GetVolumeChannel(int channel) const558 {559 HRESULT dsresult;560 long dxVolume = 0;561 int volume;562 563 if (m_UseSPDIF)564 return 100;565 566 dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);567 volume = (int)(pow(10,(float)dxVolume/20)*100);568 569 if (dsresult != DS_OK)570 {571 VBERROR(QString("Failed to get volume %1").arg(dxVolume));572 return volume;573 }574 575 VBAUDIO(QString("Got volume %1").arg(volume));576 return volume;577 }578 579 void AudioOutputDX::SetVolumeChannel(int channel, int volume)580 {581 HRESULT dsresult;582 float dbAtten = 20 * log10((float)volume/100);583 long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);584 585 if (m_UseSPDIF)586 return;587 588 // dxVolume is attenuation in 100ths of a decibel589 dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);590 591 if (dsresult != DS_OK)592 {593 VBERROR(QString("Failed to set volume %1").arg(dxVolume));594 return;595 }596 597 VBAUDIO(QString("Set volume %1").arg(dxVolume));598 }599 600 554 /* 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
28 28 #include "iso639.h" 29 29 #include "playbackbox.h" 30 30 #include "globalsettings.h" 31 #include "libmyth/volumecontrolmanager.h" 31 32 #include "recordingprofile.h" 32 33 #include "mythxdisplay.h" 33 34 #include "DisplayRes.h" … … 510 511 return gc; 511 512 } 512 513 513 static HostCheckBox *MythControlsVolume()514 {515 HostCheckBox *gc = new HostCheckBox("MythControlsVolume");516 gc->setLabel(QObject::tr("Use internal volume controls"));517 gc->setValue(true);518 gc->setHelpText(QObject::tr("If enabled, MythTV will control the PCM and "519 "master mixer volume. Disable this option if you prefer "520 "to control the volume externally (for example, using "521 "your amplifier) or if you use an external mixer program."));522 return gc;523 }524 525 514 static HostComboBox *MixerDevice() 526 515 { 527 516 HostComboBox *gc = new HostComboBox("MixerDevice", true); 528 517 gc->setLabel(QObject::tr("Mixer device")); 518 gc->addSelection(QObject::tr("Disabled"), QString()); 529 519 530 #ifdef USING_OSS 531 QDir dev("/dev", "mixer*", QDir::Name, QDir::System); 532 gc->fillSelectionsFromDir(dev); 520 QHash<QString, QString> controls = VolumeControlManager::Enumerate(); 533 521 534 dev.setPath("/dev/sound");535 if (dev.exists())522 for (QHash<QString, QString>::const_iterator control = controls.begin(); 523 control != controls.end(); ++control) 536 524 { 537 gc-> fillSelectionsFromDir(dev);525 gc->addSelection(control.value(), control.key()); 538 526 } 539 #endif540 #ifdef USING_ALSA541 gc->addSelection("ALSA:default", "ALSA:default");542 #endif543 #ifdef USING_MINGW544 gc->addSelection("DirectX:", "DirectX:");545 gc->addSelection("Windows:", "Windows:");546 #endif547 #if !defined(USING_MINGW)548 gc->addSelection("software", "software");549 gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" "550 "lets MythTV control the volume of all audio at the "551 "expense of a slight quality loss."));552 #endif553 527 554 528 return gc; 555 529 } 556 530 557 static const char* MixerControlControls[] = { "PCM",558 "Master" };559 560 static HostComboBox *MixerControl()561 {562 HostComboBox *gc = new HostComboBox("MixerControl", true);563 gc->setLabel(QObject::tr("Mixer controls"));564 for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);565 ++i)566 {567 gc->addSelection(QObject::tr(MixerControlControls[i]),568 MixerControlControls[i]);569 }570 571 gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));572 return gc;573 }574 575 static HostSlider *MixerVolume()576 {577 HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);578 gs->setLabel(QObject::tr("Master mixer volume"));579 gs->setValue(70);580 gs->setHelpText(QObject::tr("Initial volume for the Master mixer. "581 "This affects all sound created by the audio device. "582 "Note: Do not set this too low."));583 return gs;584 }585 586 static HostSlider *PCMVolume()587 {588 HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);589 gs->setLabel(QObject::tr("PCM mixer volume"));590 gs->setValue(70);591 gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "592 "volume keys in MythTV will adjust this parameter."));593 return gs;594 }595 596 531 static HostCheckBox *DecodeExtraAudio() 597 532 { 598 533 HostCheckBox *gc = new HostCheckBox("DecodeExtraAudio"); … … 3325 3260 return gs; 3326 3261 } 3327 3262 3328 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup 3263 static ConfigurationGroup *AudioMixerSettingsGroup() 3329 3264 { 3330 public: 3331 AudioMixerSettingsGroup() : 3332 TriggeredConfigurationGroup(false, true, false, false) 3333 { 3334 setLabel(QObject::tr("Audio Mixer")); 3335 setUseLabel(false); 3265 ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false); 3266 3267 vcg->setLabel(QObject::tr("Audio Mixer")); 3268 vcg->setUseLabel(false); 3336 3269 3337 Setting *volumeControl = MythControlsVolume(); 3338 addChild(volumeControl); 3270 vcg->addChild(MixerDevice()); 3339 3271 3340 // Mixer settings 3341 ConfigurationGroup *settings = 3342 new VerticalConfigurationGroup(false, true, false, false); 3343 settings->addChild(MixerDevice()); 3344 settings->addChild(MixerControl()); 3345 settings->addChild(MixerVolume()); 3346 settings->addChild(PCMVolume()); 3272 return vcg; 3273 } 3347 3274 3348 ConfigurationGroup *dummy =3349 new VerticalConfigurationGroup(false, true, false, false);3350 3351 // Show Mixer config only if internal volume controls enabled3352 setTrigger(volumeControl);3353 addTarget("0", dummy);3354 addTarget("1", settings);3355 }3356 };3357 3358 3275 static HostComboBox *MythLanguage() 3359 3276 { 3360 3277 HostComboBox *gc = new HostComboBox("Language"); … … 4050 3967 4051 3968 addChild(new AudioConfigSettings()); 4052 3969 4053 addChild( newAudioMixerSettingsGroup());3970 addChild(AudioMixerSettingsGroup()); 4054 3971 4055 3972 VerticalConfigurationGroup *general = 4056 3973 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; }