Ticket #7517: volume_control_trunk_r25178.patch
| File volume_control_trunk_r25178.patch, 130.5 KB (added by , 15 years ago) |
|---|
-
mythplugins/mythmusic/mythmusic/playbackbox.cpp
98 98 99 99 // Possibly (user-defined) control the volume 100 100 101 volume_control = false; 102 volume_display_timer = new QTimer(this); 103 if (gCoreContext->GetNumSetting("MythControlsVolume", 0)) 101 volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 102 if (volume_control) 104 103 { 105 volume_control = true; 104 connect(volume_control.data(), SIGNAL(changedVolume(int)), 105 this, SLOT(VolumeChanged(int))); 106 connect(volume_control.data(), SIGNAL(changedMute(bool)), 107 this, SLOT(MuteChanged(bool))); 106 108 } 109 110 volume_display_timer = new QTimer(this); 107 111 volume_display_timer->setSingleShot(true); 108 112 volume_display_timer->start(2000); 109 113 connect(volume_display_timer, SIGNAL(timeout()), … … 1178 1182 if (volume_control && gPlayer->getOutput()) 1179 1183 { 1180 1184 if (up_or_down) 1181 gPlayer-> getOutput()->AdjustCurrentVolume(2);1185 gPlayer->incVolume(); 1182 1186 else 1183 gPlayer-> getOutput()->AdjustCurrentVolume(-2);1187 gPlayer->decVolume(); 1184 1188 showVolume(true); 1185 1189 } 1186 1190 } … … 1201 1205 { 1202 1206 if (volume_control && gPlayer->getOutput()) 1203 1207 { 1204 gPlayer-> getOutput()->ToggleMute();1208 gPlayer->toggleMute(); 1205 1209 showVolume(true); 1206 1210 } 1207 1211 } … … 1243 1247 { 1244 1248 if (on_or_off) 1245 1249 { 1246 volume_status->SetUsed(gPlayer->get Output()->GetCurrentVolume());1250 volume_status->SetUsed(gPlayer->getVolume()); 1247 1251 volume_status->SetOrder(0); 1248 1252 volume_status->refresh(); 1249 1253 volume_display_timer->setSingleShot(true); … … 2454 2458 2455 2459 return time_string; 2456 2460 } 2461 2462 void PlaybackBoxMusic::VolumeChanged(int) 2463 { 2464 showVolume(true); 2465 } 2466 2467 void PlaybackBoxMusic::MuteChanged(bool) 2468 { 2469 showVolume(true); 2470 } -
mythplugins/mythmusic/mythmusic/musicplayer.h
3 3 4 4 #include <mythdialogs.h> 5 5 #include <audiooutput.h> 6 #include <libmyth/volumecontrolmanager.h> 6 7 #include <mythobservable.h> 7 8 8 9 #include "metadata.h" … … 55 56 56 57 void setCDDevice(const QString &dev) { m_CDdevice = dev; } 57 58 58 void toggleMute(void); 59 MuteState getMuteState(void) const; 60 bool isMuted(void) const { return getMuteState() == kMuteAll; } 59 void toggleMute(void); 60 bool isMuted(void) const; 61 61 62 62 void setVolume(int volume); 63 63 void incVolume(void); … … 176 176 AudioOutput *m_output; 177 177 Decoder *m_decoder; 178 178 179 QSharedPointer<VolumeControl> volume_control; ///< Volume control interface 180 179 181 QSet<QObject*> m_visualisers; 180 182 181 183 QString m_CDdevice; -
mythplugins/mythmusic/mythmusic/musicplayer.cpp
88 88 89 89 m_autoShowPlayer = (gCoreContext->GetNumSetting("MusicAutoShowPlayer", 1) > 0); 90 90 91 volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 92 91 93 gCoreContext->addListener(this); 92 94 } 93 95 … … 379 381 // TODO: Error checking that device is opened correctly! 380 382 m_output = AudioOutput::OpenAudio( 381 383 adevice, pdevice, FORMAT_S16, 2, 0, 44100, 382 AUDIOOUTPUT_MUSIC, true,false,384 AUDIOOUTPUT_MUSIC, false, 383 385 gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1); 384 386 385 387 m_output->setBufferSize(256 * 1024); … … 939 941 940 942 void MusicPlayer::incVolume() 941 943 { 942 if ( getOutput())944 if (volume_control) 943 945 { 944 getOutput()->AdjustCurrentVolume(2);946 volume_control->increaseVolume(); 945 947 sendVolumeChangedEvent(); 946 948 } 947 949 } 948 950 949 951 void MusicPlayer::decVolume() 950 952 { 951 if ( getOutput())953 if (volume_control) 952 954 { 953 getOutput()->AdjustCurrentVolume(-2);955 volume_control->decreaseVolume(); 954 956 sendVolumeChangedEvent(); 955 957 } 956 958 } 957 959 958 960 void MusicPlayer::setVolume(int volume) 959 961 { 960 if ( getOutput())962 if (volume_control) 961 963 { 962 getOutput()->SetCurrentVolume(volume);964 volume_control->setVolume(volume); 963 965 sendVolumeChangedEvent(); 964 966 } 965 967 } 966 968 967 969 uint MusicPlayer::getVolume(void) const 968 970 { 969 if ( m_output)970 return m_output->GetCurrentVolume();971 if (volume_control) 972 return volume_control->volume(); 971 973 return 0; 972 974 } 973 975 974 976 void MusicPlayer::toggleMute(void) 975 977 { 976 if ( m_output)978 if (volume_control) 977 979 { 978 m_output->ToggleMute();980 volume_control->setMute(!volume_control->mute()); 979 981 sendVolumeChangedEvent(); 980 982 } 981 983 } 982 984 983 MuteState MusicPlayer::getMuteState(void) const985 bool MusicPlayer::isMuted(void) const 984 986 { 985 if ( m_output)986 return m_output->GetMuteState();987 return kMuteAll;987 if (volume_control) 988 return volume_control->mute(); 989 return true; 988 990 } 989 991 990 992 void MusicPlayer::toMap(QHash<QString, QString> &map) -
mythplugins/mythmusic/mythmusic/playbackbox.h
8 8 // mythtv 9 9 #include <mythwidgets.h> 10 10 #include <dialogbox.h> 11 #include < audiooutput.h>11 #include <libmyth/volumecontrolmanager.h> 12 12 13 13 // mythmusic 14 14 #include "mainvisual.h" … … 101 101 bool getInsertPLOptions(InsertPLOption &insertOption, 102 102 PlayPLOption &playOption, bool &bRemoveDups); 103 103 104 protected slots: 105 void VolumeChanged(int volume); 106 void MuteChanged(bool mute); 107 104 108 signals: 105 109 106 110 void dummy(); // debugging … … 172 176 bool show_album_art; 173 177 bool show_whole_tree; 174 178 bool keyboard_accelerators; 175 bool volume_control;179 QSharedPointer<VolumeControl> volume_control; ///< Volume control interface 176 180 177 181 QString exit_action; 178 182 -
mythtv/configure
637 637 eval "$var=\"\$$var $*\"" 638 638 } 639 639 640 prepend(){ 641 var=$1 642 shift 643 flags_saved && eval "SAVE_$var=\"$* \$SAVE_$var\"" 644 eval "$var=\"$* \$$var\"" 645 } 646 640 647 append_uniq(){ 641 648 log append_uniq "$@" 642 649 var=$1 … … 3642 3649 { { ! enabled audio_alsa || die "ERROR: Alsa >= 1.0.16 required"; } && 3643 3650 disable audio_alsa; } 3644 3651 3652 # OSS probe 3653 if ! disabled audio_oss ; then 3654 if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h && 3655 check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3656 disable soundcard_h 3657 enable sys_soundcard_h 3658 prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include" 3659 elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h && 3660 check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3661 disable soundcard_h 3662 enable sys_soundcard_h 3663 prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include" 3664 else 3665 if enabled soundcard_h ; then 3666 check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" && 3667 enable audio_oss || 3668 disable audio_oss 3669 elif enabled sys_soundcard_h ; then 3670 check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" && 3671 enable audio_oss || 3672 disable audio_oss 3673 fi 3674 fi 3675 fi 3645 3676 3646 3677 # JACK probe 3647 3678 ! disabled audio_jack && -
mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
154 154 return 0; 155 155 } 156 156 157 NuppelVideoPlayer::NuppelVideoPlayer( bool muted)157 NuppelVideoPlayer::NuppelVideoPlayer() 158 158 : decoder(NULL), decoder_change_lock(QMutex::Recursive), 159 159 videoOutput(NULL), player_ctx(NULL), 160 160 decoderThread(NULL), playerThread(NULL), … … 214 214 // OSD stuff 215 215 osd(NULL), 216 216 // Audio 217 audio(this , muted),217 audio(this), 218 218 // Picture-in-Picture stuff 219 219 pip_active(false), pip_visible(true), 220 220 // Filters -
mythtv/libs/libmythtv/avformatdecoder.cpp
496 496 selectedVideoIndex(-1), 497 497 // Audio 498 498 audioSamples(NULL), 499 internal_vol(false),500 499 disable_passthru(false), 501 500 dummy_frame(NULL), 502 501 // DVD … … 517 516 av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR); 518 517 av_log_set_callback(myth_av_log); 519 518 520 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);521 519 522 520 audioIn.sample_size = -32; // force SetupAudioStream to run once 523 521 itv = GetNVP()->GetInteractiveTV(); … … 4641 4639 bool passthru = false; 4642 4640 4643 4641 if (ctx->codec_id == CODEC_ID_AC3) 4644 passthru = m_audio->CanAC3() && 4645 ctx->channels >= (int)m_audio->GetMaxChannels() && 4646 !internal_vol; 4642 passthru = m_audio->CanAC3(); 4647 4643 else if (ctx->codec_id == CODEC_ID_DTS) 4648 passthru = m_audio->CanDTS() && !internal_vol;4644 passthru = m_audio->CanDTS(); 4649 4645 4650 4646 passthru &= m_audio->CanPassthrough(); 4651 4647 passthru &= !transcoding && !disable_passthru; -
mythtv/libs/libmythtv/mythbdplayer.h
6 6 class MythBDPlayer : public NuppelVideoPlayer 7 7 { 8 8 public: 9 MythBDPlayer( bool muted = false);9 MythBDPlayer(); 10 10 }; 11 11 12 12 #endif // MYTHBDPLAYER_H -
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 … … 292 292 void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*); 293 293 void ClearUDPNotifyEvents(void); 294 294 295 void VolumeChanged(int volume); 296 void MuteChanged(bool mute); 297 295 298 protected: 296 299 void OSDDialogEvent(int result, QString text, QString action); 297 300 … … 484 487 485 488 vector<long long> TeardownAllNVPs(PlayerContext*); 486 489 void RestartAllNVPs(PlayerContext *lctx, 487 const vector<long long> &pos, 488 MuteState mctx_mute); 490 const vector<long long> &pos); 489 491 void RestartMainNVP(PlayerContext *mctx); 490 492 491 493 void PxPToggleView( PlayerContext *actx, bool wantPBP); … … 708 710 /// Picture attribute to modify (on arrow left or right) 709 711 PictureAttribute adjustingPictureAttribute; 710 712 713 QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface 714 711 715 // Ask Allow state 712 716 QMap<QString,AskProgramInfo> askAllowPrograms; 713 717 QMutex askAllowLock; -
mythtv/libs/libmythtv/mythdvdplayer.h
6 6 class MythDVDPlayer : public NuppelVideoPlayer 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
3 3 #define LOC QString("BDPlayer: ") 4 4 #define LOC_ERR QString("BDPlayer error: ") 5 5 6 MythBDPlayer::MythBDPlayer( bool muted) : NuppelVideoPlayer(muted)6 MythBDPlayer::MythBDPlayer() : NuppelVideoPlayer() 7 7 { 8 8 } -
mythtv/libs/libmythtv/audioplayer.cpp
4 4 5 5 #define LOC QString("AudioPlayer: ") 6 6 7 AudioPlayer::AudioPlayer(NuppelVideoPlayer *parent , bool muted)7 AudioPlayer::AudioPlayer(NuppelVideoPlayer *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) … … 147 142 m_lock.unlock(); 148 143 } 149 144 150 uint AudioPlayer::GetVolume(void)151 {152 uint res = 0;153 m_lock.lock();154 if (m_audioOutput)155 res = m_audioOutput->GetCurrentVolume();156 m_lock.unlock();157 return res;158 }159 160 145 void AudioPlayer::SetAudioInfo(const QString &main_device, 161 146 const QString &passthru_device, 162 147 uint samplerate) … … 193 178 m_lock.unlock(); 194 179 } 195 180 196 bool AudioPlayer::SetMuted(bool mute)197 {198 QMutexLocker lock(&m_lock);199 bool is_muted = IsMuted();200 201 if (m_audioOutput && !is_muted && mute &&202 (kMuteAll == SetMuteState(kMuteAll)))203 {204 VERBOSE(VB_AUDIO, "muting sound " <<IsMuted());205 return true;206 }207 else if (m_audioOutput && is_muted && !mute &&208 (kMuteOff == SetMuteState(kMuteOff)))209 {210 VERBOSE(VB_AUDIO, "unmuting sound "<<IsMuted());211 return true;212 }213 214 VERBOSE(VB_AUDIO, "not changing sound mute state "<<IsMuted());215 216 return false;217 }218 219 MuteState AudioPlayer::SetMuteState(MuteState mstate)220 {221 QMutexLocker lock(&m_lock);222 if (m_audioOutput)223 return m_audioOutput->SetMuteState(mstate);224 return kMuteAll;225 }226 227 MuteState AudioPlayer::IncrMuteState(void)228 {229 QMutexLocker lock(&m_lock);230 MuteState mstate = kMuteAll;231 if (m_audioOutput)232 mstate = SetMuteState(VolumeBase::NextMuteState(GetMuteState()));233 return mstate;234 }235 236 MuteState AudioPlayer::GetMuteState(void)237 {238 QMutexLocker lock(&m_lock);239 if (m_audioOutput)240 return m_audioOutput->GetMuteState();241 return kMuteAll;242 }243 244 uint AudioPlayer::AdjustVolume(int change)245 {246 QMutexLocker lock(&m_lock);247 if (m_audioOutput)248 m_audioOutput->AdjustCurrentVolume(change);249 return GetVolume();250 }251 252 181 long long AudioPlayer::GetAudioTime(void) 253 182 { 254 183 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 : NuppelVideoPlayer( muted), hidedvdbutton(true),11 MythDVDPlayer::MythDVDPlayer() 12 : NuppelVideoPlayer(), 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::CreateNVP(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 NuppelVideoPlayer *_nvp = NULL; 417 416 if (kState_WatchingBD == desiredState) 418 _nvp = new MythBDPlayer( muted);417 _nvp = new MythBDPlayer(); 419 418 if (kState_WatchingDVD == desiredState) 420 _nvp = new MythDVDPlayer( muted);419 _nvp = new MythDVDPlayer(); 421 420 else 422 _nvp = new NuppelVideoPlayer( muted);421 _nvp = new NuppelVideoPlayer(); 423 422 424 423 if (nohardwaredecoders) 425 424 _nvp->DisableHardwareDecoders(); … … 471 470 VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg); 472 471 } 473 472 } 474 else if (pipState == kPBPRight)475 nvp->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
1037 1037 player.push_back(new PlayerContext(kPlayerInUseID)); 1038 1038 playerActive = 0; 1039 1039 playerLock.unlock(); 1040 1041 volumeControl = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice")); 1042 if (volumeControl) 1043 { 1044 connect(volumeControl.data(), SIGNAL(changedVolume(int)), 1045 this, SLOT(VolumeChanged(int)), Qt::QueuedConnection); 1046 connect(volumeControl.data(), SIGNAL(changedMute(bool)), 1047 this, SLOT(MuteChanged(bool)), Qt::QueuedConnection); 1048 } 1049 1040 1050 VERBOSE(VB_PLAYBACK, LOC + "ctor -- end"); 1041 1051 } 1042 1052 … … 5116 5126 } 5117 5127 } 5118 5128 5119 MuteState mctx_mute = kMuteOff;5120 mctx->LockDeleteNVP(__FILE__, __LINE__);5121 if (mctx->nvp)5122 mctx_mute = mctx->nvp->GetMuteState();5123 mctx->UnlockDeleteNVP(__FILE__, __LINE__);5124 5125 5129 vector<long long> pos = TeardownAllNVPs(mctx); 5126 5130 5127 5131 if (wantPBP) … … 5139 5143 } 5140 5144 } 5141 5145 5142 RestartAllNVPs(mctx, pos , mctx_mute);5146 RestartAllNVPs(mctx, pos); 5143 5147 5144 5148 VERBOSE(VB_PLAYBACK, LOC + 5145 5149 QString("PxPToggleType() converting from %1 to %2 -- end") … … 5283 5287 * \brief Recreate Main and PIP windows. Could be either PIP or PBP views. 5284 5288 */ 5285 5289 void TV::RestartAllNVPs(PlayerContext *lctx, 5286 const vector<long long> &pos, 5287 MuteState mctx_mute) 5290 const vector<long long> &pos) 5288 5291 { 5289 5292 QString loc = LOC + QString("RestartAllNVPs(): "); 5290 5293 … … 5331 5334 pipctx->LockDeleteNVP(__FILE__, __LINE__); 5332 5335 if (pipctx->nvp) 5333 5336 { 5334 pipctx->nvp->SetMuted(true);5335 5337 pipctx->nvp->JumpToFrame(pos[i]); 5336 5338 } 5337 5339 pipctx->UnlockDeleteNVP(__FILE__, __LINE__); … … 5343 5345 ForceNextStateNone(pipctx); 5344 5346 } 5345 5347 } 5346 5347 // If old main player had a kMuteAll | kMuteOff setting,5348 // apply old main player's mute setting to new main player.5349 mctx->LockDeleteNVP(__FILE__, __LINE__);5350 if (mctx->nvp && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))5351 mctx->nvp->SetMuteState(mctx_mute);5352 mctx->UnlockDeleteNVP(__FILE__, __LINE__);5353 5348 } 5354 5349 5355 5350 void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx) … … 5377 5372 return; 5378 5373 } 5379 5374 5380 MuteState mctx_mute = mctx->nvp->GetMuteState();5381 5375 mctx->deleteNVPLock.unlock(); 5382 5376 pipctx->deleteNVPLock.unlock(); 5383 5377 … … 5391 5385 playerActive = (ctx_index == playerActive) ? 5392 5386 0 : ((ctx_index == 0) ? ctx_index : playerActive); 5393 5387 5394 RestartAllNVPs(mctx, pos , mctx_mute);5388 RestartAllNVPs(mctx, pos); 5395 5389 5396 5390 SetActive(mctx, playerActive, false); 5397 5391 … … 5412 5406 mctx->deleteNVPLock.unlock(); 5413 5407 return; 5414 5408 } 5415 5416 MuteState mctx_mute = mctx->nvp->GetMuteState();5417 5418 // HACK - FIXME5419 // workaround muted audio when NVP is re-created5420 mctx_mute = kMuteOff;5421 // FIXME - end5422 5409 mctx->deleteNVPLock.unlock(); 5423 5410 5424 5411 vector<long long> pos = TeardownAllNVPs(mctx); 5425 RestartAllNVPs(mctx, pos , mctx_mute);5412 RestartAllNVPs(mctx, pos); 5426 5413 SetActive(mctx, playerActive, false); 5427 5414 5428 5415 VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end"); … … 6126 6113 if (mctx != ctx) 6127 6114 PIPRemovePlayer(mctx, ctx); 6128 6115 6129 bool muted = false;6130 ctx->LockDeleteNVP(__FILE__, __LINE__);6131 if (ctx->nvp && ctx->nvp->IsMuted())6132 muted = true;6133 ctx->UnlockDeleteNVP(__FILE__, __LINE__);6134 6135 6116 // pause the decoder first, so we're not reading too close to the end. 6136 6117 ctx->buffer->IgnoreLiveEOF(true); 6137 6118 ctx->buffer->StopReads(); … … 6183 6164 6184 6165 if (ctx->CreateNVP( 6185 6166 this, GetMythMainWindow(), ctx->GetState(), 6186 mctx->embedWinID, &mctx->embedBounds , muted))6167 mctx->embedWinID, &mctx->embedBounds)) 6187 6168 { 6188 6169 ScheduleStateChange(ctx); 6189 6170 ok = true; … … 7775 7756 7776 7757 void TV::ChangeVolume(PlayerContext *ctx, bool up) 7777 7758 { 7778 ctx->LockDeleteNVP(__FILE__, __LINE__); 7779 if (!ctx->nvp) 7759 if (volumeControl) 7780 7760 { 7781 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 7782 return; 7761 if (up) 7762 volumeControl->increaseVolume(); 7763 else 7764 volumeControl->decreaseVolume(); 7783 7765 } 7784 uint curvol = ctx->nvp->AdjustVolume((up) ? +2 : -2);7785 ctx->UnlockDeleteNVP(__FILE__, __LINE__);7786 7787 if (!browsemode)7788 {7789 UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"),7790 QString::number(curvol),7791 kOSDFunctionalType_PictureAdjust, "%", curvol * 10);7792 SetUpdateOSDPosition(false);7793 }7794 7766 } 7795 7767 7796 7768 void TV::ToggleTimeStretch(PlayerContext *ctx) … … 7932 7904 7933 7905 void TV::ToggleMute(PlayerContext *ctx, const bool muteIndividualChannels) 7934 7906 { 7935 ctx->LockDeleteNVP(__FILE__, __LINE__); 7936 if (!ctx->nvp || !ctx->nvp->HasAudioOut()) 7937 { 7938 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 7939 return; 7940 } 7941 7942 MuteState mute_status; 7943 7944 if (!muteIndividualChannels) 7945 { 7946 ctx->nvp->SetMuted(!ctx->nvp->IsMuted()); 7947 mute_status = (ctx->nvp->IsMuted()) ? kMuteAll : kMuteOff; 7948 } 7949 else 7950 { 7951 mute_status = ctx->nvp->IncrMuteState(); 7952 } 7953 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 7954 7955 QString text; 7956 7957 switch (mute_status) 7958 { 7959 case kMuteOff: text = tr("Mute Off"); break; 7960 case kMuteAll: text = tr("Mute On"); break; 7961 case kMuteLeft: text = tr("Left Channel Muted"); break; 7962 case kMuteRight: text = tr("Right Channel Muted"); break; 7963 } 7964 7965 SetOSDMessage(ctx, text); 7907 if (volumeControl) 7908 volumeControl->setMute(!volumeControl->mute()); 7966 7909 } 7967 7910 7968 7911 void TV::ToggleSleepTimer(const PlayerContext *ctx) … … 8917 8860 { 8918 8861 value = ctx->nvp->getVideoOutput()->GetPictureAttribute(attr); 8919 8862 } 8920 else if (ctx->nvp->HasAudioOut() )8863 else if (ctx->nvp->HasAudioOut() && volumeControl) 8921 8864 { 8922 value = ctx->nvp->GetVolume();8865 value = volumeControl->volume(); 8923 8866 title = tr("Adjust Volume"); 8924 8867 } 8925 8868 } … … 11778 11721 ReturnPlayerLock(mctx); 11779 11722 } 11780 11723 11724 void TV::VolumeChanged(int volume) 11725 { 11726 if (!browsemode) 11727 { 11728 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 11729 UpdateOSDStatus(actx, tr("Adjust Volume"), tr("Volume"), 11730 QString::number(volume), 11731 kOSDFunctionalType_PictureAdjust, "%", 10 * volume); 11732 SetUpdateOSDPosition(false); 11733 ReturnPlayerLock(actx); 11734 } 11735 } 11736 11737 void TV::MuteChanged(bool mute) 11738 { 11739 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 11740 SetOSDMessage(actx, mute ? tr("Mute On") : tr("Mute Off")); 11741 ReturnPlayerLock(actx); 11742 } 11743 11744 11781 11745 OSD *TV::GetOSDL(const char *file, int location) 11782 11746 { 11783 11747 PlayerContext *actx = GetPlayerReadLock(-1, file, location); -
mythtv/libs/libmythtv/playercontext.h
68 68 // Actions 69 69 bool CreateNVP(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/avformatdecoder.h
298 298 299 299 // Audio 300 300 short int *audioSamples; 301 bool internal_vol;302 301 bool disable_passthru; 303 302 304 303 VideoFrame *dummy_frame; -
mythtv/libs/libmythtv/mythcommflagplayer.h
6 6 class MPUBLIC MythCommFlagPlayer : public NuppelVideoPlayer 7 7 { 8 8 public: 9 MythCommFlagPlayer(bool muted = false) : NuppelVideoPlayer(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(NuppelVideoPlayer *parent , bool muted);10 AudioPlayer(NuppelVideoPlayer *parent); 11 11 ~AudioPlayer(); 12 12 13 13 void Reset(void); … … 28 28 bool Pause(bool pause); 29 29 bool IsPaused(void); 30 30 void PauseAudioUntilBuffered(void); 31 uint GetVolume(void);32 uint AdjustVolume(int change);33 31 float GetStretchFactor(void) { return m_stretchfactor; } 34 32 void SetStretchFactor(float factor); 35 33 bool ToggleUpmix(void); … … 39 37 uint GetMaxChannels(void); 40 38 long long GetAudioTime(void); 41 39 42 bool IsMuted(void) { return GetMuteState() == kMuteAll; }43 bool SetMuted(bool mute);44 MuteState GetMuteState(void);45 MuteState SetMuteState(MuteState);46 MuteState IncrMuteState(void);47 48 40 void AddAudioData(char *buffer, int len, long long timecode); 49 41 bool GetBufferStatus(uint &fill, uint &total); 50 42 … … 58 50 float m_stretchfactor; 59 51 bool m_passthru; 60 52 QMutex m_lock; 61 bool m_muted_on_creation;62 53 QString m_main_device; 63 54 QString m_passthru_device; 64 55 bool no_audio_in; -
mythtv/libs/libmyth/audiooutputwin.cpp
280 280 return m_nPkts * fragment_size; 281 281 } 282 282 283 int AudioOutputWin::GetVolumeChannel(int channel) const284 {285 DWORD dwVolume = 0xffffffff;286 int Volume = 100;287 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))288 {289 Volume = (channel == 0) ?290 (LOWORD(dwVolume) / (0xffff / 100)) :291 (HIWORD(dwVolume) / (0xffff / 100));292 }293 294 VERBOSE(VB_AUDIO, "GetVolume(" << channel << ") "295 << Volume << "(" << dwVolume << ")");296 297 return Volume;298 }299 300 void AudioOutputWin::SetVolumeChannel(int channel, int volume)301 {302 if (channel > 1)303 VBERROR("Windows volume only supports stereo!");304 305 DWORD dwVolume = 0xffffffff;306 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))307 {308 if (channel == 0)309 dwVolume = dwVolume & 0xffff0000 | volume * (0xffff / 100);310 else311 dwVolume = dwVolume & 0xffff | ((volume * (0xffff / 100)) << 16);312 }313 else314 {315 dwVolume = volume * (0xffff / 100);316 dwVolume |= (dwVolume << 16);317 }318 319 VBAUDIO(QString("SetVolume(%1) %2(%3)")320 .arg(channel).arg(volume).arg(dwVolume));321 322 waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, dwVolume);323 } -
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; … … 174 171 int surround_mode; 175 172 bool allow_ac3_passthru; 176 173 float old_stretchfactor; 177 int volume;174 QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface 178 175 QString volumeControl; 179 176 180 177 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) … … 406 404 return OpenDevice(); 407 405 } 408 406 409 if (internal_vol && !OpenMixer())410 VBERROR("Unable to open audio mixer. Volume control disabled");411 412 407 // Device opened successfully 413 408 return true; 414 409 } 415 410 416 411 void AudioOutputALSA::CloseDevice() 417 412 { 418 if (m_mixer.handle)419 snd_mixer_close(m_mixer.handle);420 m_mixer.handle = NULL;421 413 if (pcm_handle) 422 414 { 423 415 snd_pcm_close(pcm_handle); … … 685 677 return 0; 686 678 } 687 679 688 int AudioOutputALSA::GetVolumeChannel(int channel) const689 {690 int retvol = 0;691 692 if (!m_mixer.elem)693 return retvol;694 695 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;696 if (!snd_mixer_selem_has_playback_channel(m_mixer.elem, chan))697 return retvol;698 699 long mixervol;700 int chk;701 if ((chk = snd_mixer_selem_get_playback_volume(m_mixer.elem,702 chan,703 &mixervol)) < 0)704 {705 VBERROR(QString("failed to get channel %1 volume, mixer %2/%3: %4")706 .arg(channel).arg(m_mixer.device)707 .arg(m_mixer.control)708 .arg(snd_strerror(chk)));709 }710 else711 {712 retvol = (m_mixer.volrange != 0L) ? (mixervol - m_mixer.volmin) *713 100.0f / m_mixer.volrange + 0.5f714 : 0;715 retvol = max(retvol, 0);716 retvol = min(retvol, 100);717 VBAUDIO(QString("get volume channel %1: %2")718 .arg(channel).arg(retvol));719 }720 return retvol;721 }722 723 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)724 {725 if (!(internal_vol && m_mixer.elem))726 return;727 728 long mixervol = volume * m_mixer.volrange / 100.0f - m_mixer.volmin + 0.5f;729 mixervol = max(mixervol, m_mixer.volmin);730 mixervol = min(mixervol, m_mixer.volmax);731 732 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;733 if (snd_mixer_selem_set_playback_volume(m_mixer.elem, chan, mixervol) < 0)734 VBERROR(QString("failed to set channel %1 volume").arg(channel));735 else736 VBAUDIO(QString("channel %1 volume set %2 => %3")737 .arg(channel).arg(volume).arg(mixervol));738 }739 740 bool AudioOutputALSA::OpenMixer(void)741 {742 if (!pcm_handle)743 {744 VBERROR("mixer setup without a pcm");745 return false;746 }747 m_mixer.device = gCoreContext->GetSetting("MixerDevice", "default");748 m_mixer.device = m_mixer.device.remove(QString("ALSA:"));749 if (m_mixer.device.toLower() == "software")750 return true;751 752 m_mixer.control = gCoreContext->GetSetting("MixerControl", "PCM");753 754 QString mixer_device_tag = QString("mixer device %1").arg(m_mixer.device);755 756 int chk;757 if ((chk = snd_mixer_open(&m_mixer.handle, 0)) < 0)758 {759 VBERROR(QString("failed to open mixer device %1: %2")760 .arg(mixer_device_tag).arg(snd_strerror(chk)));761 return false;762 }763 764 QByteArray dev_ba = m_mixer.device.toAscii();765 struct snd_mixer_selem_regopt regopts =766 {1, SND_MIXER_SABSTRACT_NONE, dev_ba.constData(), NULL, NULL};767 768 if ((chk = snd_mixer_selem_register(m_mixer.handle, ®opts, NULL)) < 0)769 {770 snd_mixer_close(m_mixer.handle);771 m_mixer.handle = NULL;772 VBERROR(QString("failed to register %1: %2")773 .arg(mixer_device_tag).arg(snd_strerror(chk)));774 return false;775 }776 777 if ((chk = snd_mixer_load(m_mixer.handle)) < 0)778 {779 snd_mixer_close(m_mixer.handle);780 m_mixer.handle = NULL;781 VBERROR(QString("failed to load %1: %2")782 .arg(mixer_device_tag).arg(snd_strerror(chk)));783 return false;784 }785 786 m_mixer.elem = NULL;787 uint elcount = snd_mixer_get_count(m_mixer.handle);788 snd_mixer_elem_t* elx = snd_mixer_first_elem(m_mixer.handle);789 790 for (uint ctr = 0; elx != NULL && ctr < elcount; ctr++)791 {792 QString tmp = QString(snd_mixer_selem_get_name(elx));793 if (m_mixer.control == tmp &&794 !snd_mixer_selem_is_enumerated(elx) &&795 snd_mixer_selem_has_playback_volume(elx) &&796 snd_mixer_selem_is_active(elx))797 {798 m_mixer.elem = elx;799 VBAUDIO(QString("found playback control %1 on %2")800 .arg(m_mixer.control)801 .arg(mixer_device_tag));802 break;803 }804 elx = snd_mixer_elem_next(elx);805 }806 if (!m_mixer.elem)807 {808 snd_mixer_close(m_mixer.handle);809 m_mixer.handle = NULL;810 VBERROR(QString("no playback control %1 found on %2")811 .arg(m_mixer.control).arg(mixer_device_tag));812 return false;813 }814 if ((snd_mixer_selem_get_playback_volume_range(m_mixer.elem,815 &m_mixer.volmin,816 &m_mixer.volmax) < 0))817 {818 snd_mixer_close(m_mixer.handle);819 m_mixer.handle = NULL;820 VBERROR(QString("failed to get volume range on %1/%2")821 .arg(mixer_device_tag).arg(m_mixer.control));822 return false;823 }824 825 m_mixer.volrange = m_mixer.volmax - m_mixer.volmin;826 VBAUDIO(QString("mixer volume range on %1/%2 - min %3, max %4, range %5")827 .arg(mixer_device_tag).arg(m_mixer.control)828 .arg(m_mixer.volmin).arg(m_mixer.volmax).arg(m_mixer.volrange));829 VBAUDIO(QString("%1/%2 set up successfully")830 .arg(mixer_device_tag)831 .arg(m_mixer.control));832 833 if (set_initial_vol)834 {835 int initial_vol;836 if (m_mixer.control == "PCM")837 initial_vol = gCoreContext->GetNumSetting("PCMMixerVolume", 80);838 else839 initial_vol = gCoreContext->GetNumSetting("MasterMixerVolume", 80);840 for (int ch = 0; ch < channels; ++ch)841 SetVolumeChannel(ch, initial_vol);842 }843 844 return true;845 }846 847 680 QMap<QString, QString> *AudioOutputALSA::GetALSADevices(const char *type) 848 681 { 849 682 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
310 310 return false; 311 311 } 312 312 313 if (internal_vol && set_initial_vol)314 {315 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");316 controlLabel += "MixerVolume";317 SetCurrentVolume(gCoreContext->GetNumSetting(controlLabel, 80));318 }319 320 313 return true; 321 314 } 322 315 … … 422 415 return noErr; 423 416 } 424 417 425 int AudioOutputCA::GetVolumeChannel(int channel) const426 {427 // FIXME: this only returns global volume428 (void)channel;429 Float32 volume;430 431 if (!AudioUnitGetParameter(d->mOutputUnit,432 kHALOutputParam_Volume,433 kAudioUnitScope_Global, 0, &volume))434 return (int)lroundf(volume * 100.0f);435 436 return 0; // error case437 }438 439 void AudioOutputCA::SetVolumeChannel(int channel, int volume)440 {441 // FIXME: this only sets global volume442 (void)channel;443 AudioUnitSetParameter(d->mOutputUnit, kHALOutputParam_Volume,444 kAudioUnitScope_Global, 0, (volume * 0.01f), 0);445 }446 447 418 // IOProc style callback for SPDIF audio output 448 419 static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice, 449 420 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 /** … … 426 428 427 429 killaudio = pauseaudio = false; 428 430 was_paused = true; 429 internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);430 431 431 432 VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels") 432 433 .arg(codec_id_string((CodecID)codec)) … … 505 506 506 507 // Turn on float conversion? 507 508 if (need_resampler || needs_upmix || needs_downmix || 508 stretchfactor != 1.0f || ( internal_vol && SWVolume()) ||509 stretchfactor != 1.0f || (volume_control) || 509 510 (enc && output_format != FORMAT_S16) || 510 511 !output_settings->IsSupportedFormat(output_format)) 511 512 { … … 544 545 return; 545 546 } 546 547 547 // Only used for software volume548 if (set_initial_vol && internal_vol && SWVolume())549 {550 VBAUDIO("Software volume enabled");551 volumeControl = gCoreContext->GetSetting("MixerControl", "PCM");552 volumeControl += "MixerVolume";553 volume = gCoreContext->GetNumSetting(volumeControl, 80);554 }555 556 VolumeBase::SetChannels(channels);557 VolumeBase::SyncVolume();558 VolumeBase::UpdateVolume();559 560 548 VBAUDIO(QString("Audio fragment size: %1").arg(fragment_size)); 561 549 562 550 audbuf_timecode = audiotime = frames_buffered = 0; … … 835 823 } 836 824 837 825 /** 838 * Set the volume for software volume control839 */840 void AudioOutputBase::SetSWVolume(int new_volume, bool save)841 {842 volume = new_volume;843 if (save && volumeControl != NULL)844 gCoreContext->SaveSetting(volumeControl, volume);845 }846 847 /**848 * Get the volume for software volume control849 */850 int AudioOutputBase::GetSWVolume()851 {852 return volume;853 }854 855 /**856 826 * Check that there's enough space in the audiobuffer to write the provided 857 827 * number of frames 858 828 * … … 1100 1070 org_waud += nFrames * bpf; 1101 1071 } 1102 1072 1103 if ( internal_vol && SWVolume())1073 if (volume_control) 1104 1074 { 1105 1075 org_waud = waud; 1106 1076 int num = len; 1077 int volume = volume_control->volume(); 1107 1078 1108 1079 if (bdiff <= num) 1109 1080 { … … 1316 1287 raud += frag_size; 1317 1288 1318 1289 // Mute individual channels through mono->stereo duplication 1319 MuteState mute_state = GetMuteState(); 1320 if (written_size && channels > 1 && 1321 (mute_state == kMuteLeft || mute_state == kMuteRight)) 1290 bool mute = volume_control ? volume_control->mute() : false; 1291 if (written_size && channels > 1 && mute) 1322 1292 { 1323 AudioOutputUtil::MuteChannel(obytes << 3, channels, 1324 mute_state == kMuteLeft ? 0 : 1, 1293 AudioOutputUtil::MuteChannel(obytes << 3, channels, 1, 1325 1294 buffer, written_size); 1326 1295 } 1327 1296 -
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 … … 93 95 # Install headers so that plugins can compile independently 94 96 inc.path = $${PREFIX}/include/mythtv/ 95 97 inc.files = dialogbox.h mythcontext.h 96 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h98 inc.files += mythwidgets.h remotefile.h oldsettings.h 97 99 inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h 98 100 inc.files += audiooutput.h audiosettings.h audiooutputsettings.h util.h 99 101 inc.files += inetcomms.h mythmedia.h mythcdrom.h mythwizard.h schemawizard.h dbutil.h 100 102 inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h 101 inc.files += visual.h volume base.h output.h langsettings.h103 inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h 102 104 inc.files += mythexp.h mythpluginapi.h storagegroupeditor.h 103 105 inc.files += mythconfigdialogs.h mythconfiggroups.h 104 106 inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h … … 117 119 118 120 using_oss { 119 121 DEFINES += USING_OSS 120 SOURCES += audiooutputoss.cpp 121 HEADERS += audiooutputoss.h 122 SOURCES += audiooutputoss.cpp volumecontroloss.cpp 123 HEADERS += audiooutputoss.h volumecontroloss.h 122 124 LIBS += $$OSS_LIBS 123 125 } 124 126 … … 146 148 147 149 mingw { 148 150 DEFINES += USING_MINGW 149 SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp 150 HEADERS += mediamonitor-windows.h audiooutputwin.h audiooutputdx.h 151 LIBS += -lpthread -lwinmm -lws2_32 151 SOURCES += mediamonitor-windows.cpp 152 HEADERS += mediamonitor-windows.h 153 SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp 154 HEADERS += audiooutputwin.h audiooutputdx.h volumecontrolendpoint.h 155 LIBS += -lpthread -lwinmm -lws2_32 -lole32 152 156 } 153 157 154 158 macx { 155 HEADERS += audiooutputca.h 156 SOURCES += audiooutputca.cpp 159 DEFINES += USE_COREAUDIO 160 HEADERS += audiooutputca.h volumecontrolcoreaudio.h 161 SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp 157 162 HEADERS += mythcdrom-darwin.h 158 163 SOURCES += mythcdrom-darwin.cpp 159 164 … … 193 198 194 199 using_alsa { 195 200 DEFINES += USE_ALSA 196 HEADERS += audiooutputalsa.h 197 SOURCES += audiooutputalsa.cpp 201 HEADERS += audiooutputalsa.h volumecontrolalsa.h 202 SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp 198 203 LIBS += $$ALSA_LIBS 199 204 } 200 205 -
mythtv/libs/libmyth/audiosettings.h
33 33 int codec, 34 34 int samplerate, 35 35 AudioOutputSource source, 36 bool set_initial_vol,37 36 bool use_passthru, 38 37 int upmixer_startup = 0); 39 38 … … 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
483 483 | DSBCAPS_GLOBALFOCUS // Allows background playing 484 484 | DSBCAPS_LOCHARDWARE; // Needed for 5.1 on emu101k 485 485 486 if (!m_UseSPDIF)487 dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME; // Allow volume control488 489 486 dsbdesc.dwBufferBytes = soundcard_buffer_size; // buffer size 490 487 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf; 491 488 … … 556 553 return buffered; 557 554 } 558 555 559 int AudioOutputDX::GetVolumeChannel(int channel) const560 {561 HRESULT dsresult;562 long dxVolume = 0;563 int volume;564 565 if (m_UseSPDIF)566 return 100;567 568 dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);569 volume = (int)(pow(10,(float)dxVolume/20)*100);570 571 if (dsresult != DS_OK)572 {573 VBERROR(QString("Failed to get volume %1").arg(dxVolume));574 return volume;575 }576 577 VBAUDIO(QString("Got volume %1").arg(volume));578 return volume;579 }580 581 void AudioOutputDX::SetVolumeChannel(int channel, int volume)582 {583 HRESULT dsresult;584 float dbAtten = 20 * log10((float)volume/100);585 long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);586 587 if (m_UseSPDIF)588 return;589 590 // dxVolume is attenuation in 100ths of a decibel591 dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);592 593 if (dsresult != DS_OK)594 {595 VBERROR(QString("Failed to set volume %1").arg(dxVolume));596 return;597 }598 599 VBAUDIO(QString("Set volume %1").arg(dxVolume));600 }601 602 556 /* 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" … … 464 465 return gc; 465 466 } 466 467 467 static HostCheckBox *MythControlsVolume()468 {469 HostCheckBox *gc = new HostCheckBox("MythControlsVolume");470 gc->setLabel(QObject::tr("Use internal volume controls"));471 gc->setValue(true);472 gc->setHelpText(QObject::tr("MythTV can control the PCM and master "473 "mixer volume. If you prefer to control the volume "474 "externally (for example, using your amplifier) or to "475 "use an external mixer program, disable this option."));476 return gc;477 }478 479 468 static HostComboBox *MixerDevice() 480 469 { 481 470 HostComboBox *gc = new HostComboBox("MixerDevice", true); 482 471 gc->setLabel(QObject::tr("Mixer device")); 472 gc->addSelection(QObject::tr("Disabled"), QString()); 483 473 484 #ifdef USING_OSS 485 QDir dev("/dev", "mixer*", QDir::Name, QDir::System); 486 gc->fillSelectionsFromDir(dev); 474 QHash<QString, QString> controls = VolumeControlManager::Enumerate(); 487 475 488 dev.setPath("/dev/sound");489 if (dev.exists())476 for (QHash<QString, QString>::const_iterator control = controls.begin(); 477 control != controls.end(); ++control) 490 478 { 491 gc-> fillSelectionsFromDir(dev);479 gc->addSelection(control.value(), control.key()); 492 480 } 493 #endif494 #ifdef USING_ALSA495 gc->addSelection("ALSA:default", "ALSA:default");496 #endif497 #ifdef USING_MINGW498 gc->addSelection("DirectX:", "DirectX:");499 gc->addSelection("Windows:", "Windows:");500 #endif501 #if !defined(USING_MINGW)502 gc->addSelection("software", "software");503 gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" "504 "lets MythTV control the volume of all audio at the "505 "expense of a slight quality loss."));506 #endif507 481 508 482 return gc; 509 483 } 510 484 511 static const char* MixerControlControls[] = { "PCM",512 "Master" };513 514 static HostComboBox *MixerControl()515 {516 HostComboBox *gc = new HostComboBox("MixerControl", true);517 gc->setLabel(QObject::tr("Mixer controls"));518 for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);519 ++i)520 {521 gc->addSelection(QObject::tr(MixerControlControls[i]),522 MixerControlControls[i]);523 }524 525 gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));526 return gc;527 }528 529 static HostSlider *MixerVolume()530 {531 HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);532 gs->setLabel(QObject::tr("Master mixer volume"));533 gs->setValue(70);534 gs->setHelpText(QObject::tr("Initial volume for the Master mixer. "535 "This affects all sound created by the audio device. "536 "Note: Do not set this too low."));537 return gs;538 }539 540 static HostSlider *PCMVolume()541 {542 HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);543 gs->setLabel(QObject::tr("PCM mixer volume"));544 gs->setValue(70);545 gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "546 "volume keys in MythTV will adjust this parameter."));547 return gs;548 }549 550 485 static HostCheckBox *DecodeExtraAudio() 551 486 { 552 487 HostCheckBox *gc = new HostCheckBox("DecodeExtraAudio"); … … 3411 3346 return gs; 3412 3347 } 3413 3348 3414 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup 3349 static ConfigurationGroup *AudioMixerSettingsGroup() 3415 3350 { 3416 public: 3417 AudioMixerSettingsGroup() : 3418 TriggeredConfigurationGroup(false, true, false, false) 3419 { 3420 setLabel(QObject::tr("Audio Mixer")); 3421 setUseLabel(false); 3351 ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false); 3352 3353 vcg->setLabel(QObject::tr("Audio Mixer")); 3354 vcg->setUseLabel(false); 3422 3355 3423 Setting *volumeControl = MythControlsVolume(); 3424 addChild(volumeControl); 3356 vcg->addChild(MixerDevice()); 3425 3357 3426 // Mixer settings 3427 ConfigurationGroup *settings = 3428 new VerticalConfigurationGroup(false, true, false, false); 3429 settings->addChild(MixerDevice()); 3430 settings->addChild(MixerControl()); 3431 settings->addChild(MixerVolume()); 3432 settings->addChild(PCMVolume()); 3358 return vcg; 3359 } 3433 3360 3434 ConfigurationGroup *dummy =3435 new VerticalConfigurationGroup(false, true, false, false);3436 3437 // Show Mixer config only if internal volume controls enabled3438 setTrigger(volumeControl);3439 addTarget("0", dummy);3440 addTarget("1", settings);3441 }3442 };3443 3444 3361 static HostComboBox *MythLanguage() 3445 3362 { 3446 3363 HostComboBox *gc = new HostComboBox("Language"); … … 4124 4041 4125 4042 addChild(new AudioConfigSettings()); 4126 4043 4127 addChild( newAudioMixerSettingsGroup());4044 addChild(AudioMixerSettingsGroup()); 4128 4045 4129 4046 VerticalConfigurationGroup *general = 4130 4047 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; }
