Ticket #7517: volume_control_mythtv_r23492.patch
| File volume_control_mythtv_r23492.patch, 76.5 KB (added by , 16 years ago) |
|---|
-
configure
595 595 eval "$var=\"\$$var $*\"" 596 596 } 597 597 598 prepend(){ 599 var=$1 600 shift 601 flags_saved && eval "SAVE_$var=\"$* \$SAVE_$var\"" 602 eval "$var=\"$* \$$var\"" 603 } 604 598 605 add_cflags(){ 599 606 append CFLAGS "$@" 600 607 } … … 3325 3332 enable audio_alsa || 3326 3333 disable audio_alsa 3327 3334 3335 # OSS probe 3336 if ! disabled audio_oss ; then 3337 if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h && 3338 check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3339 disable soundcard_h 3340 enable sys_soundcard_h 3341 prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include" 3342 elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h && 3343 check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then 3344 disable soundcard_h 3345 enable sys_soundcard_h 3346 prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include" 3347 else 3348 if enabled soundcard_h ; then 3349 check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" && 3350 enable audio_oss || 3351 disable audio_oss 3352 elif enabled sys_soundcard_h ; then 3353 check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" && 3354 enable audio_oss || 3355 disable audio_oss 3356 fi 3357 fi 3358 fi 3359 3328 3360 # JACK probe 3329 3361 ! disabled audio_jack && 3330 3362 check_lib jack/jack.h jack_client_new $audio_jack_libs && -
libs/libmythtv/NuppelVideoPlayer.cpp
100 100 kDisplayNUVTeletextCaptions, 101 101 }; 102 102 103 NuppelVideoPlayer::NuppelVideoPlayer( bool muted)103 NuppelVideoPlayer::NuppelVideoPlayer() 104 104 : decoder(NULL), decoder_change_lock(QMutex::Recursive), 105 105 videoOutput(NULL), player_ctx(NULL), 106 106 no_hardware_decoders(false), … … 170 170 audio_channels(2), audio_codec(0), 171 171 audio_bits(-1), audio_samplerate(44100), 172 172 audio_stretchfactor(1.0f), audio_lock(QMutex::Recursive), 173 audio_muted_on_creation(muted),174 173 // Picture-in-Picture stuff 175 174 pip_active(false), pip_visible(true), 176 175 // Preview window support … … 367 366 audio_samplerate = (int)samplerate; 368 367 } 369 368 370 uint NuppelVideoPlayer::GetVolume(void)371 {372 QMutexLocker lock(&audio_lock);373 if (audioOutput)374 return audioOutput->GetCurrentVolume();375 return 0;376 }377 378 bool NuppelVideoPlayer::SetMuted(bool mute)379 {380 QMutexLocker lock(&audio_lock);381 bool is_muted = IsMuted();382 383 if (audioOutput && !is_muted && mute &&384 (kMuteAll == SetMuteState(kMuteAll)))385 {386 VERBOSE(VB_AUDIO, "muting sound " <<IsMuted());387 return true;388 }389 else if (audioOutput && is_muted && !mute &&390 (kMuteOff == SetMuteState(kMuteOff)))391 {392 VERBOSE(VB_AUDIO, "unmuting sound "<<IsMuted());393 return true;394 }395 396 VERBOSE(VB_AUDIO, "not changing sound mute state "<<IsMuted());397 398 return false;399 }400 401 MuteState NuppelVideoPlayer::SetMuteState(MuteState mstate)402 {403 QMutexLocker lock(&audio_lock);404 if (audioOutput)405 return audioOutput->SetMuteState(mstate);406 return kMuteAll;407 }408 409 MuteState NuppelVideoPlayer::IncrMuteState(void)410 {411 QMutexLocker lock(&audio_lock);412 MuteState mstate = kMuteAll;413 if (audioOutput)414 mstate = SetMuteState(VolumeBase::NextMuteState(GetMuteState()));415 return mstate;416 }417 418 MuteState NuppelVideoPlayer::GetMuteState(void)419 {420 QMutexLocker lock(&audio_lock);421 if (audioOutput)422 return audioOutput->GetMuteState();423 return kMuteAll;424 }425 426 uint NuppelVideoPlayer::AdjustVolume(int change)427 {428 QMutexLocker lock(&audio_lock);429 if (audioOutput)430 audioOutput->AdjustCurrentVolume(change);431 return GetVolume();432 }433 434 369 void NuppelVideoPlayer::PauseDecoder(void) 435 370 { 436 371 decoder_lock.lock(); … … 859 794 860 795 if (!audioOutput && !using_null_videoout && player_ctx->IsAudioNeeded()) 861 796 { 862 bool setVolume = gContext->GetNumSetting("MythControlsVolume", 1);863 797 audioOutput = AudioOutput::OpenAudio(audio_main_device, 864 798 audio_passthru_device, 865 799 audio_bits, audio_channels, 866 800 audio_codec, audio_samplerate, 867 801 AUDIOOUTPUT_VIDEO, 868 setVolume,audio_passthru);802 audio_passthru); 869 803 if (!audioOutput) 870 804 errMsg = QObject::tr("Unable to create AudioOutput."); 871 805 else … … 887 821 VERBOSE(VB_IMPORTANT, LOC + "Enabling Audio"); 888 822 no_audio_out = false; 889 823 } 890 if (audio_muted_on_creation)891 {892 SetMuteState(kMuteAll);893 audio_muted_on_creation = false;894 }895 824 } 896 825 897 826 if (audioOutput) -
libs/libmythtv/avformatdecoder.cpp
495 495 audioSamples(NULL), audioSamplesResampled(NULL), 496 496 reformat_ctx(NULL), audio_src_fmt(SAMPLE_FMT_NONE), 497 497 allow_ac3_passthru(false), allow_dts_passthru(false), 498 internal_vol(false),499 498 disable_passthru(false), max_channels(2), 500 499 last_ac3_channels(0), dummy_frame(NULL), 501 500 // DVD … … 518 517 max_channels = (uint) gContext->GetNumSetting("MaxChannels", 2); 519 518 allow_ac3_passthru = (max_channels > 2) ? gContext->GetNumSetting("AC3PassThru", false) : false; 520 519 allow_dts_passthru = (max_channels > 2) ? gContext->GetNumSetting("DTSPassThru", false) : false; 521 internal_vol = gContext->GetNumSetting("MythControlsVolume", 0);522 520 523 521 audioIn.sample_size = -32; // force SetupAudioStream to run once 524 522 itv = GetNVP()->GetInteractiveTV(); … … 4528 4526 4529 4527 if (ctx->codec_id == CODEC_ID_AC3) 4530 4528 passthru = allow_ac3_passthru && 4531 ctx->channels >= (int)max_channels && 4532 !internal_vol; 4529 ctx->channels >= (int)max_channels; 4533 4530 else if (ctx->codec_id == CODEC_ID_DTS) 4534 passthru = allow_dts_passthru && !internal_vol;4531 passthru = allow_dts_passthru; 4535 4532 4536 4533 passthru &= !transcoding && !disable_passthru; 4537 4534 // Don't know any cards that support spdif clocked at < 44100 -
libs/libmythtv/tv_play.h
34 34 #include "programlist.h" 35 35 #include "channelutil.h" 36 36 #include "videoouttypes.h" 37 #include "volume base.h"37 #include "volumecontrolmanager.h" 38 38 #include "inputinfo.h" 39 39 #include "channelgroup.h" 40 40 … … 293 293 void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*); 294 294 void ClearUDPNotifyEvents(void); 295 295 296 void VolumeChanged(int volume); 297 void MuteChanged(bool mute); 298 296 299 protected: 297 300 void TreeMenuEntered(OSDListTreeItemEnteredEvent *e); 298 301 void TreeMenuSelected(OSDListTreeItemSelectedEvent *e); … … 302 305 virtual void run(void); 303 306 void TVEventThreadChecks(void); 304 307 305 void SetMuteTimer(PlayerContext*, int timeout);306 bool MuteChannelChange(PlayerContext *ctx);307 308 308 bool eventFilter(QObject *o, QEvent *e); 309 309 static QStringList lastProgramStringList; 310 310 static EMBEDRETURNVOID RunPlaybackBoxPtr; … … 502 502 503 503 vector<long long> TeardownAllNVPs(PlayerContext*); 504 504 void RestartAllNVPs(PlayerContext *lctx, 505 const vector<long long> &pos, 506 MuteState mctx_mute); 505 const vector<long long> &pos); 507 506 void RestartMainNVP(PlayerContext *mctx); 508 507 509 508 void PxPToggleView( PlayerContext *actx, bool wantPBP); … … 664 663 /// Picture attribute to modify (on arrow left or right) 665 664 PictureAttribute adjustingPictureAttribute; 666 665 666 QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface 667 667 668 // Ask Allow state 668 669 AskAllowType askAllowType; 669 670 QMap<QString,AskProgramInfo> askAllowPrograms; … … 821 822 TimerContextMap stateChangeTimerId; 822 823 TimerContextMap signalMonitorTimerId; 823 824 TimerContextMap tvchainUpdateTimerId; 824 TimerContextMap unmuteTimerId;825 825 826 826 /// Condition to signal that the Event thread is up and running 827 827 QWaitCondition mainLoopCond; … … 842 842 843 843 ///< Timeout for entry modes in msec 844 844 static const uint kInputModeTimeout; 845 /// Channel changing mute timeout in msec846 static const uint kMuteTimeout;847 845 /// Timeout for updating LCD info in msec 848 846 static const uint kLCDTimeout; 849 847 /// Timeout for browse mode exit in msec -
libs/libmythtv/playercontext.cpp
430 430 431 431 bool PlayerContext::CreateNVP(TV *tv, QWidget *widget, 432 432 TVState desiredState, 433 WId embedwinid, const QRect *embedbounds, 434 bool muted) 433 WId embedwinid, const QRect *embedbounds) 435 434 { 436 435 int exact_seeking = gContext->GetNumSetting("ExactSeeking", 0); 437 436 … … 442 441 return false; 443 442 } 444 443 445 NuppelVideoPlayer *_nvp = new NuppelVideoPlayer( muted);444 NuppelVideoPlayer *_nvp = new NuppelVideoPlayer(); 446 445 447 446 if (nohardwaredecoders) 448 447 _nvp->DisableHardwareDecoders(); … … 492 491 VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg); 493 492 } 494 493 } 495 else if (pipState == kPBPRight)496 nvp->SetMuted(true);497 494 498 495 int maxWait = -1; 499 496 //if (isPIP()) -
libs/libmythtv/NuppelVideoPlayer.h
4 4 #include <sys/time.h> 5 5 6 6 #include "playercontext.h" 7 #include "volumebase.h"8 7 #include "RingBuffer.h" 9 8 #include "osd.h" 10 9 #include "jitterometer.h" … … 89 88 friend class PlayerContext; 90 89 91 90 public: 92 NuppelVideoPlayer( bool muted = false);91 NuppelVideoPlayer(); 93 92 ~NuppelVideoPlayer(); 94 93 95 94 // Initialization … … 112 111 void SetAudioInfo(const QString &main, const QString &passthru, uint rate); 113 112 void SetAudioParams(int bits, int channels, int codec, int samplerate, bool passthru); 114 113 void SetEffDsp(int dsprate); 115 uint AdjustVolume(int change);116 bool SetMuted(bool mute);117 MuteState SetMuteState(MuteState);118 MuteState IncrMuteState(void);119 114 void SetAudioCodec(void *ac); 120 115 121 116 // Sets … … 172 167 float GetVideoAspect(void) const { return video_aspect; } 173 168 float GetFrameRate(void) const { return video_frame_rate; } 174 169 175 uint GetVolume(void);176 170 int GetSecondsBehind(void) const; 177 171 AspectOverrideMode GetAspectOverride(void) const; 178 172 AdjustFillMode GetAdjustFill(void) const; 179 MuteState GetMuteState(void);180 173 CommSkipMode GetAutoCommercialSkip(void) const; 181 174 182 175 int GetFFRewSkip(void) const { return ffrew_skip; } … … 211 204 bool HasAudioOut(void) const { return !no_audio_out; } 212 205 bool IsPIPActive(void) const { return pip_active; } 213 206 bool IsPIPVisible(void) const { return pip_visible; } 214 bool IsMuted(void) { return GetMuteState() == kMuteAll; }215 207 bool UsingNullVideo(void) const { return using_null_videoout; } 216 208 bool HasTVChainNext(void) const; 217 209 … … 719 711 float audio_stretchfactor; 720 712 bool audio_passthru; 721 713 QMutex audio_lock; 722 bool audio_muted_on_creation;723 714 724 715 // Picture-in-Picture 725 716 mutable QMutex pip_players_lock; -
libs/libmythtv/tv_play.cpp
84 84 85 85 86 86 const uint TV::kInputModeTimeout = 5000; 87 const uint TV::kMuteTimeout = 800;88 87 const uint TV::kLCDTimeout = 1000; 89 88 const uint TV::kBrowseTimeout = 30000; 90 89 const uint TV::kKeyRepeatTimeout = 300; … … 991 990 player.push_back(new PlayerContext(kPlayerInUseID)); 992 991 playerActive = 0; 993 992 playerLock.unlock(); 993 994 volumeControl = VolumeControlManager::GetControl(gContext->GetSetting("MixerDevice")); 995 if (volumeControl) 996 { 997 connect(volumeControl.data(), SIGNAL(changedVolume(int)), 998 this, SLOT(VolumeChanged(int)), Qt::QueuedConnection); 999 connect(volumeControl.data(), SIGNAL(changedMute(bool)), 1000 this, SLOT(MuteChanged(bool)), Qt::QueuedConnection); 1001 } 1002 994 1003 VERBOSE(VB_PLAYBACK, LOC + "ctor -- end"); 995 1004 } 996 1005 … … 2852 2861 if (handled) 2853 2862 return; 2854 2863 2855 // Check unmute..2856 ctx = NULL;2857 {2858 QMutexLocker locker(&timerIdLock);2859 TimerContextMap::iterator it = unmuteTimerId.find(timer_id);2860 if (it != unmuteTimerId.end())2861 {2862 KillTimer(timer_id);2863 ctx = *it;2864 unmuteTimerId.erase(it);2865 }2866 }2867 2868 if (ctx)2869 {2870 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__);2871 if (find_player_index(ctx) >= 0)2872 {2873 ctx->LockDeleteNVP(__FILE__, __LINE__);2874 if (ctx->nvp && ctx->nvp->IsMuted())2875 ctx->nvp->SetMuted(false);2876 ctx->UnlockDeleteNVP(__FILE__, __LINE__);2877 }2878 ReturnPlayerLock(mctx);2879 handled = true;2880 }2881 2882 2864 if (handled) 2883 2865 return; 2884 2866 … … 5419 5401 } 5420 5402 } 5421 5403 5422 MuteState mctx_mute = kMuteOff;5423 mctx->LockDeleteNVP(__FILE__, __LINE__);5424 if (mctx->nvp)5425 mctx_mute = mctx->nvp->GetMuteState();5426 mctx->UnlockDeleteNVP(__FILE__, __LINE__);5427 5428 5404 vector<long long> pos = TeardownAllNVPs(mctx); 5429 5405 5430 5406 if (wantPBP) … … 5442 5418 } 5443 5419 } 5444 5420 5445 RestartAllNVPs(mctx, pos , mctx_mute);5421 RestartAllNVPs(mctx, pos); 5446 5422 5447 5423 VERBOSE(VB_PLAYBACK, LOC + 5448 5424 QString("PxPToggleType() converting from %1 to %2 -- end") … … 5586 5562 * \brief Recreate Main and PIP windows. Could be either PIP or PBP views. 5587 5563 */ 5588 5564 void TV::RestartAllNVPs(PlayerContext *lctx, 5589 const vector<long long> &pos, 5590 MuteState mctx_mute) 5565 const vector<long long> &pos) 5591 5566 { 5592 5567 QString loc = LOC + QString("RestartAllNVPs(): "); 5593 5568 … … 5634 5609 pipctx->LockDeleteNVP(__FILE__, __LINE__); 5635 5610 if (pipctx->nvp) 5636 5611 { 5637 pipctx->nvp->SetMuted(true);5638 5612 pipctx->nvp->JumpToFrame(pos[i]); 5639 5613 } 5640 5614 pipctx->UnlockDeleteNVP(__FILE__, __LINE__); … … 5646 5620 ForceNextStateNone(pipctx); 5647 5621 } 5648 5622 } 5649 5650 // If old main player had a kMuteAll | kMuteOff setting,5651 // apply old main player's mute setting to new main player.5652 mctx->LockDeleteNVP(__FILE__, __LINE__);5653 if (mctx->nvp && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))5654 mctx->nvp->SetMuteState(mctx_mute);5655 mctx->UnlockDeleteNVP(__FILE__, __LINE__);5656 5623 } 5657 5624 5658 5625 void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx) … … 5680 5647 return; 5681 5648 } 5682 5649 5683 MuteState mctx_mute = mctx->nvp->GetMuteState();5684 5650 mctx->deleteNVPLock.unlock(); 5685 5651 pipctx->deleteNVPLock.unlock(); 5686 5652 … … 5694 5660 playerActive = (ctx_index == playerActive) ? 5695 5661 0 : ((ctx_index == 0) ? ctx_index : playerActive); 5696 5662 5697 RestartAllNVPs(mctx, pos , mctx_mute);5663 RestartAllNVPs(mctx, pos); 5698 5664 5699 5665 SetActive(mctx, playerActive, false); 5700 5666 … … 5715 5681 mctx->deleteNVPLock.unlock(); 5716 5682 return; 5717 5683 } 5718 5719 MuteState mctx_mute = mctx->nvp->GetMuteState();5720 5721 // HACK - FIXME5722 // workaround muted audio when NVP is re-created5723 mctx_mute = kMuteOff;5724 // FIXME - end5725 5684 mctx->deleteNVPLock.unlock(); 5726 5685 5727 5686 vector<long long> pos = TeardownAllNVPs(mctx); 5728 RestartAllNVPs(mctx, pos , mctx_mute);5687 RestartAllNVPs(mctx, pos); 5729 5688 SetActive(mctx, playerActive, false); 5730 5689 5731 5690 VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end"); … … 5850 5809 5851 5810 VERBOSE(VB_PLAYBACK, LOC + "DoNVPSeek() -- begin"); 5852 5811 5853 bool muted = false;5854 5855 5812 ctx->LockDeleteNVP(__FILE__, __LINE__); 5856 5813 if (!ctx->nvp) 5857 5814 { … … 5859 5816 return false; 5860 5817 } 5861 5818 5862 if (ctx == GetPlayer(ctx, 0))5863 muted = MuteChannelChange(ctx);5864 5865 5819 bool res = false; 5866 5820 5867 5821 if (LONG_LONG_MIN != audiosyncBaseline) … … 5882 5836 } 5883 5837 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 5884 5838 5885 if (muted)5886 SetMuteTimer(ctx, kMuteTimeout);5887 5888 5839 VERBOSE(VB_PLAYBACK, LOC + "DoNVPSeek() -- end"); 5889 5840 5890 5841 return res; … … 6247 6198 NormalSpeed(ctx); 6248 6199 StopFFRew(ctx); 6249 6200 6250 ctx->LockDeleteNVP(__FILE__, __LINE__);6251 bool muted = MuteChannelChange(ctx);6252 ctx->UnlockDeleteNVP(__FILE__, __LINE__);6253 6254 6201 struct StatusPosInfo posInfo; 6255 6202 ctx->CalcNVPSliderPosition(posInfo); 6256 6203 … … 6269 6216 if (ctx->nvp) 6270 6217 ctx->nvp->JumpChapter(chapter); 6271 6218 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 6272 6273 if (muted)6274 SetMuteTimer(ctx, kMuteTimeout);6275 6219 } 6276 6220 6277 6221 void TV::DoSkipCommercials(PlayerContext *ctx, int direction) … … 6282 6226 if (StateIsLiveTV(GetState(ctx))) 6283 6227 return; 6284 6228 6285 ctx->LockDeleteNVP(__FILE__, __LINE__);6286 bool muted = MuteChannelChange(ctx);6287 ctx->UnlockDeleteNVP(__FILE__, __LINE__);6288 6289 6229 struct StatusPosInfo posInfo; 6290 6230 ctx->CalcNVPSliderPosition(posInfo); 6291 6231 … … 6304 6244 if (ctx->nvp) 6305 6245 ctx->nvp->SkipCommercials(direction); 6306 6246 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 6307 6308 if (muted)6309 SetMuteTimer(ctx, kMuteTimeout);6310 6247 } 6311 6248 6312 6249 void TV::SwitchSource(uint source_direction) … … 6476 6413 if (mctx != ctx) 6477 6414 PIPRemovePlayer(mctx, ctx); 6478 6415 6479 bool muted = false;6480 ctx->LockDeleteNVP(__FILE__, __LINE__);6481 if (ctx->nvp && ctx->nvp->IsMuted())6482 muted = true;6483 ctx->UnlockDeleteNVP(__FILE__, __LINE__);6484 6485 6416 // pause the decoder first, so we're not reading too close to the end. 6486 6417 ctx->buffer->IgnoreLiveEOF(true); 6487 6418 ctx->buffer->StopReads(); … … 6533 6464 6534 6465 if (ctx->CreateNVP( 6535 6466 this, gContext->GetMainWindow(), ctx->GetState(), 6536 mctx->embedWinID, &mctx->embedBounds , muted))6467 mctx->embedWinID, &mctx->embedBounds)) 6537 6468 { 6538 6469 ScheduleStateChange(ctx); 6539 6470 ok = true; … … 6890 6821 6891 6822 void TV::ChangeChannel(PlayerContext *ctx, int direction) 6892 6823 { 6893 bool muted = false;6894 6895 6824 if ((browse_changrp || (direction == CHANNEL_DIRECTION_FAVORITE)) && 6896 6825 (channel_group_id > -1)) 6897 6826 { … … 6922 6851 6923 6852 QString oldinputname = ctx->recorder->GetInput(); 6924 6853 6925 muted = MuteChannelChange(ctx);6926 6927 6854 if (ctx->paused) 6928 6855 { 6929 6856 OSD *osd = GetOSDLock(ctx); … … 6951 6878 ctx->recorder->ChangeChannel(direction); 6952 6879 ClearInputQueues(ctx, false); 6953 6880 6954 if (muted)6955 SetMuteTimer(ctx, kMuteTimeout * 2);6956 6957 6881 UnpauseLiveTV(ctx); 6958 6882 6959 6883 if (oldinputname != ctx->recorder->GetInput()) … … 6970 6894 6971 6895 QString channum = chan; 6972 6896 QStringList reclist; 6973 bool muted = false;6974 6897 6975 6898 QString oldinputname = ctx->recorder->GetInput(); 6976 6899 … … 7040 6963 if (getit || !ctx->recorder || !ctx->recorder->CheckChannel(channum)) 7041 6964 return; 7042 6965 7043 muted = MuteChannelChange(ctx);7044 7045 6966 OSD *osd = GetOSDLock(ctx); 7046 6967 if (osd && ctx->paused) 7047 6968 { … … 7067 6988 7068 6989 ctx->recorder->SetChannel(channum); 7069 6990 7070 if (muted)7071 SetMuteTimer(ctx, kMuteTimeout * 2);7072 7073 6991 UnpauseLiveTV(ctx); 7074 6992 7075 6993 if (oldinputname != ctx->recorder->GetInput()) … … 8180 8098 8181 8099 void TV::ChangeVolume(PlayerContext *ctx, bool up) 8182 8100 { 8183 ctx->LockDeleteNVP(__FILE__, __LINE__); 8184 if (!ctx->nvp) 8101 if (volumeControl) 8185 8102 { 8186 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8187 return; 8103 if (up) 8104 volumeControl->increaseVolume(); 8105 else 8106 volumeControl->decreaseVolume(); 8188 8107 } 8189 uint curvol = ctx->nvp->AdjustVolume((up) ? +2 : -2);8190 ctx->UnlockDeleteNVP(__FILE__, __LINE__);8191 8192 QString text = tr("Volume %1 %").arg(curvol);8193 8194 OSD *osd = GetOSDLock(ctx);8195 if (osd && !browsemode)8196 {8197 osd->ShowStatus(curvol * 10, true, tr("Adjust Volume"), text, 5,8198 kOSDFunctionalType_PictureAdjust);8199 SetUpdateOSDPosition(false);8200 }8201 ReturnOSDLock(ctx, osd);8202 8108 } 8203 8109 8204 8110 void TV::ToggleTimeStretch(PlayerContext *ctx) … … 8347 8253 8348 8254 void TV::ToggleMute(PlayerContext *ctx) 8349 8255 { 8350 ctx->LockDeleteNVP(__FILE__, __LINE__); 8351 if (!ctx->nvp || !ctx->nvp->HasAudioOut()) 8352 { 8353 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8354 return; 8355 } 8356 8357 MuteState mute_status; 8358 8359 if (!MuteIndividualChannels) 8360 { 8361 ctx->nvp->SetMuted(!ctx->nvp->IsMuted()); 8362 mute_status = (ctx->nvp->IsMuted()) ? kMuteAll : kMuteOff; 8363 } 8364 else 8365 { 8366 mute_status = ctx->nvp->IncrMuteState(); 8367 } 8368 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8369 8370 QString text; 8371 8372 switch (mute_status) 8373 { 8374 case kMuteOff: text = tr("Mute Off"); break; 8375 case kMuteAll: text = tr("Mute On"); break; 8376 case kMuteLeft: text = tr("Left Channel Muted"); break; 8377 case kMuteRight: text = tr("Right Channel Muted"); break; 8378 } 8379 8380 OSD *osd = GetOSDLock(ctx); 8381 if (osd && !browsemode) 8382 osd->SetSettingsText(text, 5); 8383 ReturnOSDLock(ctx, osd); 8256 if (volumeControl) 8257 volumeControl->setMute(!volumeControl->mute()); 8384 8258 } 8385 8259 8386 8260 void TV::ToggleSleepTimer(const PlayerContext *ctx) … … 8540 8414 ReturnOSDLock(ctx, osd); 8541 8415 } 8542 8416 8543 void TV::SetMuteTimer(PlayerContext *ctx, int timeout)8544 {8545 // message to set the timer will be posted to the main UI thread8546 // where it will be caught in eventFilter and processed as CustomEvent8547 // this will properly set the mute timer8548 // otherwise it never fires on Win328549 QString message = QString("UNMUTE %1 %2").arg((long long)ctx).arg(timeout);8550 qApp->postEvent(gContext->GetMainWindow(), new MythEvent(message));8551 }8552 8553 bool TV::MuteChannelChange(PlayerContext *ctx)8554 {8555 if (!ctx)8556 return false;8557 8558 bool muted = false;8559 ctx->LockDeleteNVP(__FILE__, __LINE__);8560 if (ctx->nvp && !ctx->nvp->IsMuted())8561 muted = ctx->nvp->SetMuted(true);8562 ctx->UnlockDeleteNVP(__FILE__, __LINE__);8563 8564 return muted;8565 }8566 8567 8417 void TV::customEvent(QEvent *e) 8568 8418 { 8569 8419 if (e->type() == OSDCloseEvent::kEventType) … … 8839 8689 } 8840 8690 } 8841 8691 8842 if (message.left(6) == "UNMUTE")8843 {8844 if (tokens.size() >= 3)8845 {8846 long long target = tokens[1].toLongLong();8847 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__);8848 for (uint i = 0; i < player.size(); i++)8849 {8850 PlayerContext *ctx = GetPlayer(mctx, i);8851 if (((long long)ctx) == target)8852 {8853 QMutexLocker locker(&timerIdLock);8854 unmuteTimerId[StartTimer(tokens[2].toUInt(), __LINE__)] = ctx;8855 }8856 }8857 ReturnPlayerLock(mctx);8858 }8859 }8860 8861 8692 if (message.left(9) == "START_EPG") 8862 8693 { 8863 8694 int editType = tokens[1].toInt(); … … 9346 9177 { 9347 9178 value = ctx->nvp->getVideoOutput()->GetPictureAttribute(attr); 9348 9179 } 9349 else if (ctx->nvp->HasAudioOut() )9180 else if (ctx->nvp->HasAudioOut() && volumeControl) 9350 9181 { 9351 value = ctx->nvp->GetVolume();9182 value = volumeControl->volume(); 9352 9183 title = tr("Adjust Volume"); 9353 9184 } 9354 9185 } … … 11885 11716 ReturnPlayerLock(mctx); 11886 11717 } 11887 11718 11719 void TV::VolumeChanged(int volume) 11720 { 11721 OSD *osd = GetOSDL(__FILE__, __LINE__); 11722 if (osd && !browsemode) 11723 { 11724 osd->ShowStatus(volume * 10, true, tr("Adjust Volume"), 11725 tr("Volume %1 %").arg(volume), 5, 11726 kOSDFunctionalType_PictureAdjust); 11727 SetUpdateOSDPosition(false); 11728 } 11729 ReturnOSDLock(osd); 11730 } 11731 11732 void TV::MuteChanged(bool mute) 11733 { 11734 OSD *osd = GetOSDL(__FILE__, __LINE__); 11735 if (osd && !browsemode) 11736 osd->SetSettingsText(mute ? tr("Mute On") : tr("Mute Off"), 5); 11737 ReturnOSDLock(osd); 11738 } 11739 11740 11888 11741 OSD *TV::GetOSDL(const char *file, int location) 11889 11742 { 11890 11743 PlayerContext *actx = GetPlayerReadLock(-1, file, location); -
libs/libmythtv/playercontext.h
47 47 // Actions 48 48 bool CreateNVP(TV *tv, QWidget *widget, 49 49 TVState desiredState, 50 WId embedwinid, const QRect *embedBounds, 51 bool muted = false); 50 WId embedwinid, const QRect *embedBounds); 52 51 void TeardownPlayer(void); 53 52 bool StartDecoderThread(int maxWait = -1); 54 53 bool StartOSD(TV *tv); -
libs/libmythtv/avformatdecoder.h
269 269 270 270 bool allow_ac3_passthru; 271 271 bool allow_dts_passthru; 272 bool internal_vol;273 272 bool disable_passthru; 274 273 uint max_channels; 275 274 uint last_ac3_channels; -
libs/libmyth/audiooutputwin.cpp
280 280 { 281 281 return m_nPkts * fragment_size; 282 282 } 283 284 int AudioOutputWin::GetVolumeChannel(int channel) const285 {286 DWORD dwVolume = 0xffffffff;287 int Volume = 100;288 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))289 {290 Volume = (channel == 0) ?291 (LOWORD(dwVolume) / (0xffff / 100)) :292 (HIWORD(dwVolume) / (0xffff / 100));293 }294 295 VERBOSE(VB_AUDIO, "GetVolume(" << channel << ") "296 << Volume << "(" << dwVolume << ")");297 298 return Volume;299 }300 301 void AudioOutputWin::SetVolumeChannel(int channel, int volume)302 {303 if (channel > 1)304 {305 Error(QString("Error setting channel: %1. "306 "Only stereo volume supported").arg(channel));307 return;308 }309 310 DWORD dwVolume = 0xffffffff;311 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))312 {313 if (channel == 0)314 dwVolume = dwVolume & 0xffff0000 | volume * (0xffff / 100);315 else316 dwVolume = dwVolume & 0xffff | ((volume * (0xffff / 100)) << 16);317 }318 else319 {320 dwVolume = volume * (0xffff / 100);321 dwVolume |= (dwVolume << 16);322 }323 324 VERBOSE(VB_AUDIO, QString("SetVolume(%1) %2(%3)")325 .arg(channel).arg(volume).arg(dwVolume));326 waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, dwVolume);327 } -
libs/libmyth/audiooutputjack.h
11 11 AudioOutputJACK(const AudioSettings &settings); 12 12 virtual ~AudioOutputJACK(); 13 13 14 // Volume control15 virtual int GetVolumeChannel(int channel) const; // Returns 0-10016 virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol17 18 14 protected: 19 15 20 16 // You need to implement the following functions … … 27 23 28 24 private: 29 25 30 void VolumeInit(void);31 32 26 int audioid; 33 27 34 28 }; -
libs/libmyth/audiooutputbase.h
18 18 #include "audiooutput.h" 19 19 #include "samplerate.h" 20 20 #include "mythverbose.h" 21 #include "volumecontrolmanager.h" 21 22 22 23 namespace soundtouch { 23 24 class SoundTouch; … … 47 48 48 49 virtual void Reset(void); 49 50 50 void SetSWVolume(int new_volume, bool save);51 int GetSWVolume(void);52 53 51 // timecode is in milliseconds. 54 52 virtual bool AddSamples(char *buffer, int samples, long long timecode); 55 53 virtual bool AddSamples(char *buffers[], int samples, long long timecode); … … 113 111 int audiolen(bool use_lock); // number of valid bytes in audio buffer 114 112 int audiofree(bool use_lock); // number of free bytes in audio buffer 115 113 116 void UpdateVolume(void);117 118 114 void SetStretchFactorLocked(float factor); 119 115 120 116 int GetBaseAudioTime() const { return audiotime; } … … 148 144 bool killaudio; 149 145 150 146 bool pauseaudio, audio_actually_paused, was_paused; 151 bool set_initial_vol;152 147 bool buffer_output_data_for_use; // used by AudioOutputNULL 153 148 154 149 int configured_audio_channels; … … 181 176 int surround_mode; 182 177 bool allow_ac3_passthru; 183 178 float old_audio_stretchfactor; 184 int volume;179 QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface 185 180 186 181 bool blocking; // do AddSamples calls block? 187 182 -
libs/libmyth/audiosettings.cpp
15 15 channels(-1), 16 16 codec(0), 17 17 samplerate(-1), 18 set_initial_vol(false),19 18 use_passthru(false), 20 19 source(AUDIOOUTPUT_UNKNOWN), 21 20 upmixer(0) … … 29 28 channels(other.channels), 30 29 codec(other.codec), 31 30 samplerate(other.samplerate), 32 set_initial_vol(other.set_initial_vol),33 31 use_passthru(other.use_passthru), 34 32 source(other.source), 35 33 upmixer(other.upmixer) … … 44 42 int audio_codec, 45 43 int audio_samplerate, 46 44 AudioOutputSource audio_source, 47 bool audio_set_initial_vol,48 45 bool audio_use_passthru, 49 46 int upmixer_startup) : 50 47 main_device(audio_main_device), … … 53 50 channels(audio_channels), 54 51 codec(audio_codec), 55 52 samplerate(audio_samplerate), 56 set_initial_vol(audio_set_initial_vol),57 53 use_passthru(audio_use_passthru), 58 54 source(audio_source), 59 55 upmixer(upmixer_startup) … … 73 69 channels(audio_channels), 74 70 codec(audio_codec), 75 71 samplerate(audio_samplerate), 76 set_initial_vol(false),77 72 use_passthru(audio_use_passthru), 78 73 source(AUDIOOUTPUT_UNKNOWN), 79 74 upmixer(upmixer_startup) -
libs/libmyth/audiooutputalsa.cpp
21 21 AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) : 22 22 AudioOutputBase(settings), 23 23 pcm_handle(NULL), 24 numbadioctls(0), 25 mixer_handle(NULL), 26 mixer_control(QString::null) 24 numbadioctls(0) 27 25 { 28 26 // Set everything up 29 27 Reconfigure(settings); … … 252 250 // it really is 253 251 audio_buffer_unused = soundcard_buffer_size - (fragment_size * 4); 254 252 255 if (internal_vol)256 OpenMixer(set_initial_vol);257 258 253 // Device opened successfully 259 254 return true; 260 255 } 261 256 262 257 void AudioOutputALSA::CloseDevice() 263 258 { 264 CloseMixer();265 259 if (pcm_handle != NULL) 266 260 { 267 261 snd_pcm_close(pcm_handle); … … 620 614 621 615 return 0; 622 616 } 623 624 625 int AudioOutputALSA::GetVolumeChannel(int channel) const626 {627 long actual_volume;628 629 if (mixer_handle == NULL)630 return 100;631 632 QByteArray mix_ctl = mixer_control.toAscii();633 snd_mixer_selem_id_t *sid;634 snd_mixer_selem_id_alloca(&sid);635 snd_mixer_selem_id_set_index(sid, 0);636 snd_mixer_selem_id_set_name(sid, mix_ctl.constData());637 638 snd_mixer_elem_t *elem = snd_mixer_find_selem(mixer_handle, sid);639 if (!elem)640 {641 VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1")642 .arg(mixer_control));643 return 100;644 }645 646 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;647 if (!snd_mixer_selem_has_playback_channel(elem, chan))648 {649 snd_mixer_selem_id_set_index(sid, channel);650 if ((elem = snd_mixer_find_selem(mixer_handle, sid)) == NULL)651 {652 VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1 %2")653 .arg(mixer_control).arg(channel));654 return 100;655 }656 }657 658 ALSAVolumeInfo vinfo = GetVolumeRange(elem);659 660 snd_mixer_selem_get_playback_volume(661 elem, (snd_mixer_selem_channel_id_t)channel, &actual_volume);662 663 return vinfo.ToMythRange(actual_volume);664 }665 666 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)667 {668 SetCurrentVolume(mixer_control, channel, volume);669 }670 671 void AudioOutputALSA::SetCurrentVolume(QString control, int channel, int volume)672 {673 VERBOSE(VB_AUDIO, QString("Setting %1 volume to %2")674 .arg(control).arg(volume));675 676 if (!mixer_handle)677 return; // no mixer, nothing to do678 679 QByteArray ctl = control.toAscii();680 snd_mixer_selem_id_t *sid;681 snd_mixer_selem_id_alloca(&sid);682 snd_mixer_selem_id_set_index(sid, 0);683 snd_mixer_selem_id_set_name(sid, ctl.constData());684 685 snd_mixer_elem_t *elem = snd_mixer_find_selem(mixer_handle, sid);686 if (!elem)687 {688 VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1")689 .arg(control));690 return;691 }692 693 snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;694 if (!snd_mixer_selem_has_playback_channel(elem, chan))695 {696 snd_mixer_selem_id_set_index(sid, channel);697 if ((elem = snd_mixer_find_selem(mixer_handle, sid)) == NULL)698 {699 VERBOSE(VB_IMPORTANT,700 QString("mixer unable to find control %1 %2")701 .arg(control).arg(channel));702 return;703 }704 }705 706 ALSAVolumeInfo vinfo = GetVolumeRange(elem);707 708 long set_vol = vinfo.ToALSARange(volume);709 710 int err = snd_mixer_selem_set_playback_volume(elem, chan, set_vol);711 if (err < 0)712 {713 VERBOSE(VB_IMPORTANT, QString("mixer set channel %1 err %2: %3")714 .arg(channel).arg(err).arg(snd_strerror(err)));715 }716 else717 {718 VERBOSE(VB_AUDIO, QString("channel %1 vol set to %2")719 .arg(channel).arg(set_vol));720 }721 722 if (snd_mixer_selem_has_playback_switch(elem))723 {724 int unmute = (0 != set_vol);725 if (snd_mixer_selem_has_playback_switch_joined(elem))726 {727 // Only mute if all the channels should be muted.728 for (int i = 0; i < audio_channels; i++)729 {730 if (0 != GetVolumeChannel(i))731 unmute = 1;732 }733 }734 735 err = snd_mixer_selem_set_playback_switch(elem, chan, unmute);736 if (err < 0)737 {738 VERBOSE(VB_IMPORTANT, LOC_ERR +739 QString("Mixer set playback switch %1 err %2: %3")740 .arg(channel).arg(err).arg(snd_strerror(err)));741 }742 else743 {744 VERBOSE(VB_AUDIO, LOC +745 QString("channel %1 playback switch set to %2")746 .arg(channel).arg(unmute));747 }748 }749 }750 751 void AudioOutputALSA::OpenMixer(bool setstartingvolume)752 {753 int volume;754 755 mixer_control = gContext->GetSetting("MixerControl", "PCM");756 757 SetupMixer();758 759 if (mixer_handle != NULL && setstartingvolume)760 {761 volume = gContext->GetNumSetting("MasterMixerVolume", 80);762 SetCurrentVolume("Master", 0, volume);763 SetCurrentVolume("Master", 1, volume);764 765 volume = gContext->GetNumSetting("PCMMixerVolume", 80);766 SetCurrentVolume("PCM", 0, volume);767 SetCurrentVolume("PCM", 1, volume);768 }769 }770 771 void AudioOutputALSA::CloseMixer(void)772 {773 if (mixer_handle != NULL)774 snd_mixer_close(mixer_handle);775 mixer_handle = NULL;776 }777 778 void AudioOutputALSA::SetupMixer(void)779 {780 int err;781 782 QString alsadevice = gContext->GetSetting("MixerDevice", "default");783 QString device = alsadevice.remove(QString("ALSA:"));784 785 if (mixer_handle != NULL)786 CloseMixer();787 788 if (alsadevice.toLower() == "software")789 return;790 791 VERBOSE(VB_AUDIO, QString("Opening mixer %1").arg(device));792 793 // TODO: This is opening card 0. Fix for case of multiple soundcards794 if ((err = snd_mixer_open(&mixer_handle, 0)) < 0)795 {796 Warn(QString("Mixer device open error %1: %2")797 .arg(err).arg(snd_strerror(err)));798 mixer_handle = NULL;799 return;800 }801 802 QByteArray dev = device.toAscii();803 if ((err = snd_mixer_attach(mixer_handle, dev.constData())) < 0)804 {805 Warn(QString("Mixer attach error %1: %2"806 "\n\t\t\tCheck Mixer Name in Setup: '%3'")807 .arg(err).arg(snd_strerror(err)).arg(device));808 CloseMixer();809 return;810 }811 812 if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0)813 {814 Warn(QString("Mixer register error %1: %2")815 .arg(err).arg(snd_strerror(err)));816 CloseMixer();817 return;818 }819 820 if ((err = snd_mixer_load(mixer_handle)) < 0)821 {822 Warn(QString("Mixer load error %1: %2")823 .arg(err).arg(snd_strerror(err)));824 CloseMixer();825 return;826 }827 }828 829 ALSAVolumeInfo AudioOutputALSA::GetVolumeRange(snd_mixer_elem_t *elem) const830 {831 long volume_min, volume_max;832 833 int err = snd_mixer_selem_get_playback_volume_range(834 elem, &volume_min, &volume_max);835 836 if (err < 0)837 {838 static bool first_time = true;839 if (first_time)840 {841 VERBOSE(VB_IMPORTANT,842 "snd_mixer_selem_get_playback_volume_range()" + ENO);843 first_time = false;844 }845 }846 847 ALSAVolumeInfo vinfo(volume_min, volume_max);848 849 VERBOSE(VB_AUDIO, QString("Volume range is %1 to %2, mult=%3")850 .arg(vinfo.volume_min).arg(vinfo.volume_max)851 .arg(vinfo.range_multiplier));852 853 return vinfo;854 } -
libs/libmyth/audiooutputca.cpp
244 244 return false; 245 245 } 246 246 247 if (internal_vol && set_initial_vol)248 {249 QString controlLabel = gContext->GetSetting("MixerControl", "PCM");250 controlLabel += "MixerVolume";251 SetCurrentVolume(gContext->GetNumSetting(controlLabel, 80));252 }253 254 247 return true; 255 248 } 256 249 … … 399 392 return noErr; 400 393 } 401 394 402 int AudioOutputCA::GetVolumeChannel(int channel) const403 {404 // FIXME: this only returns global volume405 (void)channel;406 Float32 volume;407 408 if (!AudioUnitGetParameter(d->mOutputUnit,409 kHALOutputParam_Volume,410 kAudioUnitScope_Global, 0, &volume))411 return (int)lroundf(volume * 100.0);412 413 return 0; // error case414 }415 416 void AudioOutputCA::SetVolumeChannel(int channel, int volume)417 {418 // FIXME: this only sets global volume419 (void)channel;420 AudioUnitSetParameter(d->mOutputUnit, kHALOutputParam_Volume,421 kAudioUnitScope_Global, 0, (volume * 0.01), 0);422 }423 424 395 // IOProc style callback for SPDIF audio output 425 396 static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice, 426 397 const AudioTimeStamp *inNow, -
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 "mythcontext.h"11 12 VolumeBase::VolumeBase() :13 internal_vol(false), volume(80),14 current_mute_state(kMuteOff)15 {16 swvol = swvol_setting =17 (gContext->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 = gContext->GetSetting("MixerControl", "PCM");43 controlLabel += "MixerVolume";44 gContext->SaveSetting(controlLabel, volume);45 }46 47 void VolumeBase::AdjustCurrentVolume(int change)48 {49 SetCurrentVolume(volume + change);50 }51 52 MuteState VolumeBase::SetMuteState(MuteState mstate)53 {54 current_mute_state = mstate;55 UpdateVolume();56 return current_mute_state;57 }58 59 void VolumeBase::ToggleMute(void)60 {61 bool is_muted = GetMuteState() == kMuteAll;62 SetMuteState((is_muted) ? kMuteOff : kMuteAll);63 }64 65 MuteState VolumeBase::GetMuteState(void) const66 {67 return current_mute_state;68 }69 70 MuteState VolumeBase::NextMuteState(MuteState cur)71 {72 MuteState next = cur;73 74 switch (cur)75 {76 case kMuteOff:77 next = kMuteLeft;78 break;79 case kMuteLeft:80 next = kMuteRight;81 break;82 case kMuteRight:83 next = kMuteAll;84 break;85 case kMuteAll:86 next = kMuteOff;87 break;88 }89 90 return (next);91 }92 93 void VolumeBase::UpdateVolume(void)94 {95 int new_volume = volume;96 bool save = true;97 if (current_mute_state == kMuteAll)98 {99 new_volume = 0;100 save = false;101 }102 103 if (swvol)104 {105 SetSWVolume(new_volume, save);106 return;107 }108 109 // TODO: Avoid assumption that there are 2 channels!110 for (int i = 0; i < 2; i++)111 {112 SetVolumeChannel(i, new_volume);113 }114 115 // Individual channel muting is handled in GetAudioData,116 // this code demonstrates the old method.117 // if (current_mute_state == kMuteLeft)118 // {119 // SetVolumeChannel(0, 0);120 // }121 // else if (current_mute_state == kMuteRight)122 // {123 // SetVolumeChannel(1, 0);124 // }125 }126 127 void VolumeBase::SyncVolume(void)128 {129 // Read the volume from the audio driver and setup our internal state to match130 if (swvol)131 volume = GetSWVolume();132 else133 volume = GetVolumeChannel(0);134 }135 -
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); -
libs/libmyth/audiooutputjack.cpp
148 148 audio_buffer_unused = JACK_GetBytesFreeSpace(audioid); 149 149 JACK_SetPosition(audioid, BYTES, 0); 150 150 151 // Setup volume control152 if (internal_vol)153 VolumeInit();154 155 151 // Device opened successfully 156 152 return true; 157 153 } … … 206 202 207 203 return space; 208 204 } 209 210 void AudioOutputJACK::VolumeInit(void)211 {212 int volume = 100;213 if (set_initial_vol)214 volume = gContext->GetNumSetting("MasterMixerVolume", 80);215 216 JACK_SetAllVolume(audioid, volume);217 }218 219 int AudioOutputJACK::GetVolumeChannel(int channel) const220 {221 unsigned int vol = 0;222 223 if (!internal_vol)224 return 100;225 226 JACK_GetVolumeForChannel(audioid, channel, &vol);227 return vol;228 }229 230 void AudioOutputJACK::SetVolumeChannel(int channel, int volume)231 {232 if (internal_vol)233 JACK_SetVolumeForChannel(audioid, channel, volume);234 }235 -
libs/libmyth/audiooutputoss.h
12 12 AudioOutputOSS(const AudioSettings &settings); 13 13 virtual ~AudioOutputOSS(); 14 14 15 // Volume control16 virtual int GetVolumeChannel(int channel) const;17 virtual void SetVolumeChannel(int channel, int volume);18 19 15 protected: 20 16 // You need to implement the following functions 21 17 virtual bool OpenDevice(void); … … 26 22 vector<int> GetSupportedRates(void); 27 23 28 24 private: 29 void VolumeInit(void);30 void VolumeCleanup(void);31 32 25 void SetFragSize(void); 33 26 34 27 int audiofd; 35 28 mutable int numbadioctls; 36 37 // Volume related38 int mixerfd;39 int control;40 29 }; 41 30 42 31 #endif -
libs/libmyth/audiooutputbase.cpp
37 37 pauseaudio(false), audio_actually_paused(false), 38 38 was_paused(false), 39 39 40 set_initial_vol(settings.set_initial_vol),41 40 buffer_output_data_for_use(false), 42 41 43 42 // private … … 54 53 needs_upmix(false), 55 54 surround_mode(FreeSurround::SurroundModePassive), 56 55 old_audio_stretchfactor(1.0), 57 volume(80),58 56 59 57 blocking(false), 60 58 … … 109 107 110 108 allow_ac3_passthru = (orig_config_channels > 2) ? gContext->GetNumSetting("AC3PassThru", false) : false; 111 109 110 if (gContext->GetSetting("MixerDevice") == "Software:") 111 volume_control = VolumeControlManager::GetControl("Software:"); 112 112 113 // You need to call Reconfigure from your concrete class. 113 114 // Reconfigure(laudio_bits, laudio_channels, 114 115 // laudio_samplerate, laudio_passthru); … … 278 279 killaudio = false; 279 280 pauseaudio = false; 280 281 was_paused = true; 281 internal_vol = gContext->GetNumSetting("MythControlsVolume", 0);282 282 283 283 numlowbuffer = 0; 284 284 … … 359 359 return; 360 360 } 361 361 362 // Only used for software volume363 if (set_initial_vol && internal_vol)364 volume = gContext->GetNumSetting("PCMMixerVolume", 80);365 {366 QString controlLabel = gContext->GetSetting("MixerControl", "PCM");367 controlLabel += "MixerVolume";368 volume = gContext->GetNumSetting(controlLabel, 80);369 }370 371 SyncVolume();372 VolumeBase::UpdateVolume();373 374 362 VERBOSE(VB_AUDIO, LOC + QString("Audio fragment size: %1") 375 363 .arg(fragment_size)); 376 364 … … 664 652 return audbuf_timecode - GetAudiotime(); 665 653 } 666 654 667 void AudioOutputBase::SetSWVolume(int new_volume, bool save)668 {669 volume = new_volume;670 if (save)671 {672 QString controlLabel = gContext->GetSetting("MixerControl", "PCM");673 controlLabel += "MixerVolume";674 gContext->SaveSetting(controlLabel, volume);675 }676 }677 678 int AudioOutputBase::GetSWVolume()679 {680 return volume;681 }682 683 655 void AudioOutputBase::AdjustVolume(void *buffer, int len, bool music) 684 656 { 685 657 if (audio_bits == 8) … … 691 663 template <class AudioDataType> 692 664 void AudioOutputBase::_AdjustVolume(AudioDataType *buffer, int len, bool music) 693 665 { 666 int volume = volume_control->mute() ? 0 : volume_control->volume(); 667 694 668 float g = volume / 100.0; 695 669 696 670 // Should probably be exponential - this'll do … … 1099 1073 } 1100 1074 } 1101 1075 1102 if ( internal_vol && SWVolume())1076 if (volume_control) 1103 1077 { 1104 1078 int bdiff = kAudioRingBufferSize - waud; 1105 1079 bool music = (timecode < 1); … … 1360 1334 audio_buflock.unlock(); 1361 1335 1362 1336 // Mute individual channels through mono->stereo duplication 1363 MuteState mute_state = GetMuteState();1337 // MuteState mute_state = GetMuteState(); 1364 1338 if (written_size && 1365 audio_channels > 1 && 1366 (mute_state == kMuteLeft || mute_state == kMuteRight)) 1339 audio_channels > 1 //&& 1340 // (mute_state == kMuteLeft || mute_state == kMuteRight) 1341 ) 1367 1342 { 1368 1343 int offset_src = 0; 1369 1344 int offset_dst = 0; 1370 1345 1371 if (mute_state == kMuteLeft)1372 offset_src = audio_bits / 8; // copy channel 1 to channel 01373 else if (mute_state == kMuteRight)1374 offset_dst = audio_bits / 8; // copy channel 0 to channel 11346 // if (mute_state == kMuteLeft) 1347 // offset_src = audio_bits / 8; // copy channel 1 to channel 0 1348 // else if (mute_state == kMuteRight) 1349 // offset_dst = audio_bits / 8; // copy channel 0 to channel 1 1375 1350 1376 1351 for (int i = 0; i < written_size; i += audio_bytes_per_sample) 1377 1352 { -
libs/libmyth/audiooutput.cpp
34 34 int audio_bits, int audio_channels, 35 35 int audio_codec, int audio_samplerate, 36 36 AudioOutputSource source, 37 bool set_initial_vol, boolaudio_passthru,37 bool audio_passthru, 38 38 int upmixer_startup) 39 39 { 40 40 AudioSettings settings( 41 41 main_device, passthru_device, audio_bits, 42 42 audio_channels, audio_codec, audio_samplerate, source, 43 set_initial_vol,audio_passthru, upmixer_startup);43 audio_passthru, upmixer_startup); 44 44 45 45 settings.FixPassThrough(); 46 46 -
libs/libmyth/libmyth.pro
23 23 HEADERS += output.h 24 24 HEADERS += settings.h 25 25 HEADERS += uilistbtntype.h uitypes.h util.h mythuifilebrowser.h 26 HEADERS += volumebase.h visual.h xmlparse.h 26 HEADERS += volumecontrol.h volumecontrolmanager.h volumecontrolsoftware.h 27 HEADERS += visual.h xmlparse.h 27 28 HEADERS += mythhdd.h mythcdrom.h storagegroup.h dbutil.h 28 29 HEADERS += mythcommandlineparser.h mythterminal.h 29 30 HEADERS += mythhttppool.h mythhttphandler.h … … 47 48 SOURCES += output.cpp 48 49 SOURCES += settings.cpp 49 50 SOURCES += uilistbtntype.cpp uitypes.cpp util.cpp mythuifilebrowser.cpp 50 SOURCES += volumebase.cpp xmlparse.cpp 51 SOURCES += volumecontrolmanager.cpp volumecontrolsoftware.cpp 52 SOURCES += xmlparse.cpp 51 53 SOURCES += mythhdd.cpp mythcdrom.cpp storagegroup.cpp dbutil.cpp 52 54 SOURCES += mythcommandlineparser.cpp mythterminal.cpp 53 55 SOURCES += mythhttppool.cpp mythhttphandler.cpp … … 87 89 # Install headers so that plugins can compile independently 88 90 inc.path = $${PREFIX}/include/mythtv/ 89 91 inc.files = dialogbox.h mythcontext.h 90 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h92 inc.files += mythwidgets.h remotefile.h oldsettings.h 91 93 inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h 92 94 inc.files += audiooutput.h audiosettings.h util.h 93 95 inc.files += inetcomms.h mythmedia.h mythwizard.h schemawizard.h dbutil.h 94 96 inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h 95 inc.files += visual.h volume base.h output.h langsettings.h97 inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h 96 98 inc.files += mythexp.h mythpluginapi.h storagegroup.h 97 99 inc.files += mythconfigdialogs.h mythconfiggroups.h 98 100 inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h … … 107 109 108 110 using_oss { 109 111 DEFINES += USING_OSS 110 SOURCES += audiooutputoss.cpp 111 HEADERS += audiooutputoss.h 112 SOURCES += audiooutputoss.cpp volumecontroloss.cpp 113 HEADERS += audiooutputoss.h volumecontroloss.h 112 114 LIBS += $$OSS_LIBS 113 115 } 114 116 … … 136 138 137 139 mingw { 138 140 DEFINES += USING_MINGW 139 SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp 140 HEADERS += mediamonitor-windows.h audiooutputwin.h audiooutputdx.h 141 LIBS += -lpthread -lwinmm -lws2_32 141 SOURCES += mediamonitor-windows.cpp 142 HEADERS += mediamonitor-windows.h 143 SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp 144 HEADERS += audiooutputwin.h audiooutputdx.h volumecontrolendpoint.h 145 LIBS += -lpthread -lwinmm -lws2_32 -lole32 142 146 } 143 147 144 148 macx { 145 HEADERS += audiooutputca.h 146 SOURCES += audiooutputca.cpp 149 DEFINES += USE_COREAUDIO 150 HEADERS += audiooutputca.h volumecontrolcoreaudio.h 151 SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp 147 152 HEADERS += mythcdrom-darwin.h 148 153 SOURCES += mythcdrom-darwin.cpp 149 154 … … 183 188 184 189 using_alsa { 185 190 DEFINES += USE_ALSA 186 HEADERS += audiooutputalsa.h 187 SOURCES += audiooutputalsa.cpp 191 HEADERS += audiooutputalsa.h volumecontrolalsa.h 192 SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp 188 193 LIBS += $$ALSA_LIBS 189 194 } 190 195 -
libs/libmyth/audiosettings.h
32 32 int audio_codec, 33 33 int audio_samplerate, 34 34 AudioOutputSource audio_source, 35 bool audio_set_initial_vol,36 35 bool audio_use_passthru, 37 36 int upmixer_startup = 0); 38 37 … … 58 57 int channels; 59 58 int codec; 60 59 int samplerate; 61 bool set_initial_vol;62 60 bool use_passthru; 63 61 AudioOutputSource source; 64 62 int upmixer; -
libs/libmyth/audiooutputca.h
25 25 bool RenderAudio(unsigned char *aubuf, int size, 26 26 unsigned long long timestamp); 27 27 28 // Volume control29 virtual int GetVolumeChannel(int channel) const;30 virtual void SetVolumeChannel(int channel, int volume);31 32 28 void Debug(QString msg) 33 29 { VERBOSE(VB_AUDIO, "AudioOutputCA::" + msg); } 34 30 … … 37 33 38 34 void Warn(QString msg) 39 35 { VERBOSE(VB_IMPORTANT, "AudioOutputCA Warning: " + msg); } 36 bool internal_vol; 40 37 41 38 protected: 42 39 -
libs/libmyth/audiooutputoss.cpp
30 30 31 31 AudioOutputOSS::AudioOutputOSS(const AudioSettings &settings) : 32 32 AudioOutputBase(settings), 33 audiofd(-1), numbadioctls(0), 34 mixerfd(-1), control(SOUND_MIXER_VOLUME) 33 audiofd(-1), numbadioctls(0) 35 34 { 36 35 // Set everything up 37 36 Reconfigure(settings); … … 194 193 " the error was: %1").arg(strerror(errno))); 195 194 } 196 195 197 // Setup volume control198 if (internal_vol)199 VolumeInit();200 201 196 // Device opened successfully 202 197 return true; 203 198 } … … 242 237 close(audiofd); 243 238 244 239 audiofd = -1; 245 246 VolumeCleanup();247 240 } 248 241 249 242 … … 310 303 311 304 return space; 312 305 } 313 314 void AudioOutputOSS::VolumeInit()315 {316 mixerfd = -1;317 int volume = 0;318 319 QString device = gContext->GetSetting("MixerDevice", "/dev/mixer");320 if (device.toLower() == "software")321 return;322 323 QByteArray dev = device.toAscii();324 mixerfd = open(dev.constData(), O_RDONLY);325 326 QString controlLabel = gContext->GetSetting("MixerControl", "PCM");327 328 if (controlLabel == "Master")329 {330 control = SOUND_MIXER_VOLUME;331 }332 else333 {334 control = SOUND_MIXER_PCM;335 }336 337 if (mixerfd < 0)338 {339 VERBOSE(VB_IMPORTANT, LOC +340 QString("Unable to open mixer: '%1'").arg(device));341 return;342 }343 344 if (set_initial_vol)345 {346 int tmpVol;347 volume = gContext->GetNumSetting("MasterMixerVolume", 80);348 tmpVol = (volume << 8) + volume;349 int ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);350 if (ret < 0)351 {352 VERBOSE(VB_IMPORTANT, LOC_ERR +353 QString("Error Setting initial Master Volume") + ENO);354 }355 356 volume = gContext->GetNumSetting("PCMMixerVolume", 80);357 tmpVol = (volume << 8) + volume;358 ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);359 if (ret < 0)360 {361 VERBOSE(VB_IMPORTANT, LOC_ERR +362 QString("Error setting initial PCM Volume") + ENO);363 }364 }365 }366 367 void AudioOutputOSS::VolumeCleanup()368 {369 if (mixerfd >= 0)370 {371 close(mixerfd);372 mixerfd = -1;373 }374 }375 376 int AudioOutputOSS::GetVolumeChannel(int channel) const377 {378 int volume=0;379 int tmpVol=0;380 381 if (mixerfd <= 0)382 return 100;383 384 int ret = ioctl(mixerfd, MIXER_READ(control), &tmpVol);385 if (ret < 0) {386 VERBOSE(VB_IMPORTANT, QString("Error reading volume for channel %1")387 .arg(channel));388 perror("Reading PCM volume: ");389 return 0;390 }391 392 if (channel == 0) {393 volume = tmpVol & 0xff; // left394 } else if (channel == 1) {395 volume = (tmpVol >> 8) & 0xff; // right396 } else {397 VERBOSE(VB_IMPORTANT, QString("Invalid channel. Only stereo volume supported"));398 }399 400 return volume;401 }402 403 void AudioOutputOSS::SetVolumeChannel(int channel, int volume)404 {405 if (channel > 1) {406 // Don't support more than two channels!407 VERBOSE(VB_IMPORTANT, QString("Error setting channel: %1. Only stereo volume supported")408 .arg(channel));409 return;410 }411 412 if (volume > 100)413 volume = 100;414 if (volume < 0)415 volume = 0;416 417 if (mixerfd >= 0)418 {419 int tmpVol = 0;420 if (channel == 0)421 tmpVol = (GetVolumeChannel(1) << 8) + volume;422 else423 tmpVol = (volume << 8) + GetVolumeChannel(0);424 425 int ret = ioctl(mixerfd, MIXER_WRITE(control), &tmpVol);426 if (ret < 0)427 {428 VERBOSE(VB_IMPORTANT, QString("Error setting volume on channel: %1").arg(channel));429 perror("Setting volume: ");430 }431 }432 }433 -
libs/libmyth/volumebase.h
1 #ifndef __VOLUME_BASE__2 #define __VOLUME_BASE__3 4 #include "mythexp.h"5 6 typedef enum {7 kMuteOff = 0,8 kMuteLeft,9 kMuteRight,10 kMuteAll,11 } MuteState;12 13 class MPUBLIC VolumeBase14 {15 public:16 VolumeBase();17 virtual ~VolumeBase() {};18 19 void SWVolume(bool set);20 bool SWVolume(void);21 virtual uint GetCurrentVolume(void) const;22 virtual void SetCurrentVolume(int value);23 virtual void AdjustCurrentVolume(int change);24 virtual void ToggleMute(void);25 26 virtual MuteState GetMuteState(void) const;27 virtual MuteState SetMuteState(MuteState);28 29 static MuteState NextMuteState(MuteState);30 31 protected:32 33 virtual int GetVolumeChannel(int channel) const = 0; // Returns 0-10034 virtual void SetVolumeChannel(int channel, int volume) = 0; // range 0-100 for vol35 virtual void SetSWVolume(int new_volume, bool save) = 0;36 virtual int GetSWVolume(void) = 0;37 38 void UpdateVolume(void);39 void SyncVolume(void);40 41 bool internal_vol;42 43 private:44 45 int volume;46 MuteState current_mute_state;47 bool swvol;48 bool swvol_setting;49 50 };51 52 #endif // __VOLUME_BASE__ -
libs/libmyth/audiooutputdx.cpp
369 369 dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */ 370 370 | DSBCAPS_GLOBALFOCUS /* Allows background playing */ 371 371 | DSBCAPS_LOCHARDWARE; /* Needed for 5.1 on emu101k */ 372 if (!m_UseSPDIF)373 dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME; /* Allow volume control */374 372 dsbdesc.dwBufferBytes = soundcard_buffer_size; /* buffer size */ 375 373 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf; 376 374 … … 517 515 return buffered; 518 516 } 519 517 520 int AudioOutputDX::GetVolumeChannel(int channel) const521 {522 HRESULT dsresult;523 long dxVolume = 0;524 int volume;525 526 if (m_UseSPDIF)527 return 100;528 529 dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);530 volume = (int)(pow(10,(float)dxVolume/20)*100);531 532 if (dsresult != DS_OK)533 {534 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Failed to get volume %1")535 .arg(dxVolume));536 return volume;537 }538 539 VERBOSE(VB_AUDIO, LOC + QString("Got volume %1").arg(volume));540 return volume;541 }542 543 void AudioOutputDX::SetVolumeChannel(int channel, int volume)544 {545 HRESULT dsresult;546 float dbAtten = 20 * log10((float)volume/100);547 long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);548 549 if (m_UseSPDIF)550 return;551 552 // dxVolume is attenuation in 100ths of a decibel553 dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);554 555 if (dsresult != DS_OK)556 {557 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Failed to set volume %1")558 .arg(dxVolume));559 return;560 }561 562 VERBOSE(VB_AUDIO, LOC + QString("Set volume %1").arg(dxVolume));563 }564 565 518 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
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: -
libs/libmyth/audiooutput.h
5 5 6 6 #include "audiosettings.h" 7 7 #include "mythcontext.h" 8 #include "volumebase.h"9 8 #include "output.h" 10 9 11 class MPUBLIC AudioOutput : public VolumeBase, publicOutputListeners10 class MPUBLIC AudioOutput : public OutputListeners 12 11 { 13 12 public: 14 13 // opens one of the concrete subclasses … … 18 17 int audio_bits, int audio_channels, 19 18 int audio_codec, int audio_samplerate, 20 19 AudioOutputSource source, 21 bool set_initial_vol, boolaudio_passthru,20 bool audio_passthru, 22 21 int upmixer_startup = 0); 23 22 24 23 AudioOutput() : 25 VolumeBase(),OutputListeners(),24 OutputListeners(), 26 25 lastError(QString::null), lastWarn(QString::null) {} 27 26 28 27 virtual ~AudioOutput() { }; -
libs/libmyth/audiooutputpulse.h
30 30 AudioOutputPulseAudio(const AudioSettings &settings); 31 31 ~AudioOutputPulseAudio(); 32 32 33 int GetVolumeChannel(int channel) const;34 void SetVolumeChannel(int channel, int volume);35 33 void Pause(bool paused); 36 34 void Reset(void); 37 35 void Drain(void); -
libs/libmyth/audiooutputdx.h
13 13 AudioOutputDX(const AudioSettings &settings); 14 14 virtual ~AudioOutputDX(); 15 15 16 virtual int GetVolumeChannel(int channel) const;17 virtual void SetVolumeChannel(int channel, int volume);18 19 16 protected: 20 17 virtual bool OpenDevice(void); 21 18 virtual void CloseDevice(void); -
libs/libmyth/audiooutputalsa.h
9 9 10 10 using namespace std; 11 11 12 class ALSAVolumeInfo13 {14 public:15 ALSAVolumeInfo(long playback_vol_min,16 long playback_vol_max) :17 range_multiplier(1.0f),18 volume_min(playback_vol_min), volume_max(playback_vol_max)19 {20 float range = (float) (volume_max - volume_min);21 if (range > 0.0f)22 range_multiplier = 100.0f / range;23 range_multiplier_inv = 1.0f / range_multiplier;24 }25 26 int ToMythRange(long alsa_volume)27 {28 long toz = alsa_volume - volume_min;29 int val = (int) (toz * range_multiplier);30 val = (val < 0) ? 0 : val;31 val = (val > 100) ? 100 : val;32 return val;33 }34 35 long ToALSARange(int myth_volume)36 {37 float tos = myth_volume * range_multiplier_inv;38 long val = (long) (tos + volume_min + 0.5);39 val = (val < volume_min) ? volume_min : val;40 val = (val > volume_max) ? volume_max : val;41 return val;42 }43 44 float range_multiplier;45 float range_multiplier_inv;46 long volume_min;47 long volume_max;48 };49 50 12 class AudioOutputALSA : public AudioOutputBase 51 13 { 52 14 public: 53 15 AudioOutputALSA(const AudioSettings &settings); 54 16 virtual ~AudioOutputALSA(); 55 17 56 // Volume control57 virtual int GetVolumeChannel(int channel) const; // Returns 0-10058 virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol59 60 61 18 protected: 62 19 // You need to implement the following functions 63 20 virtual bool OpenDevice(void); … … 77 34 void ReorderSmpteToAlsa6ch(void *buf, int frames); 78 35 template <class AudioDataType> 79 36 void _ReorderSmpteToAlsa6ch(AudioDataType *buf, int frames); 80 // Volume related81 void SetCurrentVolume(QString control, int channel, int volume);82 void OpenMixer(bool setstartingvolume);83 void CloseMixer(void);84 void SetupMixer(void);85 ALSAVolumeInfo GetVolumeRange(snd_mixer_elem_t *elem) const;86 37 87 38 private: 88 39 snd_pcm_t *pcm_handle; 89 40 int numbadioctls; 90 41 QMutex killAudioLock; 91 snd_mixer_t *mixer_handle;92 QString mixer_control; // e.g. "PCM"93 42 snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*, 94 43 snd_pcm_uframes_t); 95 44 }; -
libs/libmyth/audiooutputpulse.cpp
268 268 return writable; 269 269 } 270 270 271 int AudioOutputPulseAudio::GetVolumeChannel(int channel) const272 {273 return (float)volume_control.values[channel]274 / (float)PA_VOLUME_NORM * 100.0f;275 }276 277 void AudioOutputPulseAudio::SetVolumeChannel(int channel, int volume)278 {279 QString fn_log_tag = "SetVolumeChannel, ";280 if (channel < 0 || channel > PULSE_MAX_CHANNELS || volume < 0)281 {282 VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +283 QString("bad volume params, channel %1, volume %2")284 .arg(channel).arg(volume));285 return;286 }287 volume_control.values[channel] =288 (float)volume / 100.0f * (float)PA_VOLUME_NORM;289 volume = min(100, volume);290 volume = max(0, volume);291 uint32_t sink_index = pa_stream_get_device_index(pstream);292 pa_threaded_mainloop_lock(mainloop);293 pa_operation *op =294 pa_context_set_sink_volume_by_index(pcontext, sink_index,295 &volume_control,296 OpCompletionCallback, this);297 pa_threaded_mainloop_unlock(mainloop);298 if (op)299 pa_operation_unref(op);300 else301 VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +302 QString("set sink volume operation failed, sink: %1, "303 "error: %2 ")304 .arg(sink_index)305 .arg(pa_strerror(pa_context_errno(pcontext))));306 }307 308 271 void AudioOutputPulseAudio::Pause(bool paused) 309 272 { 310 273 pa_operation *op; … … 545 508 pa_stream_set_overflow_callback(pstream, BufferFlowCallback, (char*)"over"); 546 509 pa_stream_set_underflow_callback(pstream, BufferFlowCallback, 547 510 (char*)"under"); 548 if (set_initial_vol) 549 { 550 int volume = gContext->GetNumSetting("MasterMixerVolume", 80); 551 pa_cvolume_set(&volume_control, audio_channels, 552 (float)volume * (float)PA_VOLUME_NORM / 100.0f); 553 } 554 else 555 pa_cvolume_reset(&volume_control, audio_channels); 511 pa_cvolume_reset(&volume_control, audio_channels); 556 512 557 513 // set myth sizes and pa buffer metrics 558 514 fragment_size = (float)sample_rate * 0.020f * // 20msec -
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" … … 179 180 return gc; 180 181 } 181 182 182 static HostCheckBox *MythControlsVolume()183 {184 HostCheckBox *gc = new HostCheckBox("MythControlsVolume");185 gc->setLabel(QObject::tr("Use internal volume controls"));186 gc->setValue(true);187 gc->setHelpText(QObject::tr("MythTV can control the PCM and master "188 "mixer volume. If you prefer to control the volume externally "189 "(like your amplifier) or use an external mixer "190 "program, disable this option."));191 return gc;192 }193 194 183 static HostComboBox *MixerDevice() 195 184 { 196 185 HostComboBox *gc = new HostComboBox("MixerDevice", true); 197 186 gc->setLabel(QObject::tr("Mixer Device")); 187 gc->addSelection(QObject::tr("Disabled"), QString()); 198 188 199 #ifdef USING_OSS 200 QDir dev("/dev", "mixer*", QDir::Name, QDir::System); 201 gc->fillSelectionsFromDir(dev); 189 QHash<QString, QString> controls = VolumeControlManager::Enumerate(); 202 190 203 dev.setPath("/dev/sound");204 if (dev.exists())191 for (QHash<QString, QString>::const_iterator control = controls.begin(); 192 control != controls.end(); ++control) 205 193 { 206 gc-> fillSelectionsFromDir(dev);194 gc->addSelection(control.value(), control.key()); 207 195 } 208 #endif209 #ifdef USING_ALSA210 gc->addSelection("ALSA:default", "ALSA:default");211 #endif212 #ifdef USING_MINGW213 gc->addSelection("DirectX:", "DirectX:");214 gc->addSelection("Windows:", "Windows:");215 #endif216 #if !defined(USING_MINGW)217 gc->addSelection("software", "software");218 gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" lets MythTV control "219 "the volume of all audio at the expense of a slight quality loss."));220 #endif221 196 222 197 return gc; 223 198 } 224 199 225 static const char* MixerControlControls[] = { "PCM",226 "Master" };227 228 static HostComboBox *MixerControl()229 {230 HostComboBox *gc = new HostComboBox("MixerControl", true);231 gc->setLabel(QObject::tr("Mixer Controls"));232 for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);233 ++i)234 {235 gc->addSelection(QObject::tr(MixerControlControls[i]),236 MixerControlControls[i]);237 }238 239 gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));240 return gc;241 }242 243 static HostSlider *MixerVolume()244 {245 HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);246 gs->setLabel(QObject::tr("Master Mixer Volume"));247 gs->setValue(70);248 gs->setHelpText(QObject::tr("Initial volume for the Master Mixer. "249 "This affects all sound created by the sound card. "250 "Note: Do not set this too low."));251 return gs;252 }253 254 static HostSlider *PCMVolume()255 {256 HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);257 gs->setLabel(QObject::tr("PCM Mixer Volume"));258 gs->setValue(70);259 gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "260 "volume keys in MythTV will adjust this parameter."));261 return gs;262 }263 264 200 static HostCheckBox *IndividualMuteControl() 265 201 { 266 202 HostCheckBox *gc = new HostCheckBox("IndividualMuteControl"); … … 3497 3433 group2->addChild(AggressiveBuffer()); 3498 3434 3499 3435 return vcg; 3500 3501 3436 } 3502 3437 3503 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup 3438 static ConfigurationGroup *AudioMixerSettingsGroup() 3504 3439 { 3505 public: 3506 AudioMixerSettingsGroup() : 3507 TriggeredConfigurationGroup(false, true, false, false) 3508 { 3509 setLabel(QObject::tr("Audio Mixer")); 3510 setUseLabel(false); 3440 ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false); 3441 3442 vcg->setLabel(QObject::tr("Audio Mixer")); 3443 vcg->setUseLabel(false); 3511 3444 3512 Setting *volumeControl = MythControlsVolume(); 3513 addChild(volumeControl); 3445 vcg->addChild(MixerDevice()); 3514 3446 3515 // Mixer settings 3516 ConfigurationGroup *settings = 3517 new VerticalConfigurationGroup(false, true, false, false); 3518 settings->addChild(MixerDevice()); 3519 settings->addChild(MixerControl()); 3520 settings->addChild(MixerVolume()); 3521 settings->addChild(PCMVolume()); 3522 settings->addChild(IndividualMuteControl()); 3447 return vcg; 3448 } 3523 3449 3524 ConfigurationGroup *dummy =3525 new VerticalConfigurationGroup(false, true, false, false);3526 3527 // Show Mixer config only if internal volume controls enabled3528 setTrigger(volumeControl);3529 addTarget("0", dummy);3530 addTarget("1", settings);3531 }3532 };3533 3534 3450 static HostComboBox *MythLanguage() 3535 3451 { 3536 3452 HostComboBox *gc = new HostComboBox("Language"); … … 4214 4130 4215 4131 addChild(AudioSystemSettingsGroup()); 4216 4132 4217 addChild( newAudioMixerSettingsGroup());4133 addChild(AudioMixerSettingsGroup()); 4218 4134 4219 4135 VerticalConfigurationGroup *general = 4220 4136 new VerticalConfigurationGroup(false, true, false, false); -
programs/mythtranscode/transcode.cpp
166 166 return last_audiotime; 167 167 } 168 168 169 virtual int GetVolumeChannel(int) const170 {171 // Do nothing172 return 100;173 }174 virtual void SetVolumeChannel(int, int)175 {176 // Do nothing177 }178 virtual void SetVolumeAll(int)179 {180 // Do nothing181 }182 virtual uint GetCurrentVolume(void) const183 {184 // Do nothing185 return 100;186 }187 virtual void SetCurrentVolume(int)188 {189 // Do nothing190 }191 virtual void AdjustCurrentVolume(int)192 {193 // Do nothing194 }195 virtual void SetMute(bool)196 {197 // Do nothing198 }199 virtual void ToggleMute(void)200 {201 // Do nothing202 }203 virtual MuteState GetMuteState(void) const204 {205 // Do nothing206 return kMuteOff;207 }208 virtual MuteState IterateMutedChannels(void)209 {210 // Do nothing211 return kMuteOff;212 }213 169 virtual bool ToggleUpmix(void) 214 170 { 215 171 // Do nothing 216 172 return false; 217 173 } 218 174 219 virtual void SetSWVolume(int new_volume, bool save)220 {221 // Do nothing222 return;223 }224 virtual int GetSWVolume(void)225 {226 // Do nothing227 return 100;228 }229 230 175 // These are pure virtual in AudioOutput, but we don't need them here 231 176 virtual void bufferOutputData(bool){ return; } 232 177 virtual int readOutputData(unsigned char*, int ){ return 0; }
