Ticket #7517: volume_control_mythtv_r22764.patch

File volume_control_mythtv_r22764.patch, 128.7 KB (added by mythtv@…, 16 years ago)
  • configure

     
    596596    eval "$var=\"\$$var $*\""
    597597}
    598598
     599prepend(){
     600    var=$1
     601    shift
     602    flags_saved && eval "SAVE_$var=\"$* \$SAVE_$var\""
     603    eval "$var=\"$* \$$var\""
     604}
     605
    599606add_cflags(){
    600607    append CFLAGS "$@"
    601608}
     
    33293336    enable  audio_alsa ||
    33303337    disable audio_alsa
    33313338
     3339# OSS probe
     3340if ! disabled audio_oss ; then
     3341    if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h &&
     3342       check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then
     3343        disable soundcard_h
     3344        enable sys_soundcard_h
     3345        prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include"
     3346    elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h &&
     3347       check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then
     3348        disable soundcard_h
     3349        enable sys_soundcard_h
     3350        prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include"
     3351    else
     3352        if enabled soundcard_h ; then
     3353            check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" &&
     3354            enable  audio_oss ||
     3355            disable audio_oss
     3356        elif enabled sys_soundcard_h ; then
     3357            check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" &&
     3358            enable  audio_oss ||
     3359            disable audio_oss
     3360        fi
     3361    fi
     3362fi
     3363
    33323364# JACK probe
    33333365! disabled audio_jack &&
    33343366    check_lib jack/jack.h jack_client_new $audio_jack_libs &&
     
    40274059if enabled audio_oss; then
    40284060    append CCONFIG "using_oss"
    40294061fi
     4062
    40304063if enabled audio_alsa; then
    40314064    append CCONFIG "using_alsa"
    40324065  echo "CONFIG_AUDIO_ALSA_LIBS=$audio_alsa_libs" >> $MYTH_CONFIG_MAK
  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    147147    kDisplayNUVTeletextCaptions,
    148148};
    149149
    150 NuppelVideoPlayer::NuppelVideoPlayer(bool muted)
     150NuppelVideoPlayer::NuppelVideoPlayer()
    151151    : decoder(NULL),                decoder_change_lock(QMutex::Recursive),
    152152      videoOutput(NULL),            player_ctx(NULL),
    153153      no_hardware_decoders(false),
     
    215215      audio_channels(2),            audio_codec(0),
    216216      audio_bits(-1),               audio_samplerate(44100),
    217217      audio_stretchfactor(1.0f),    audio_lock(QMutex::Recursive),
    218       audio_muted_on_creation(muted),
    219218      // Picture-in-Picture stuff
    220219      pip_active(false),            pip_visible(true),
    221220      // Preview window support
     
    408407    audio_samplerate      = (int)samplerate;
    409408}
    410409
    411 uint NuppelVideoPlayer::GetVolume(void)
    412 {
    413     QMutexLocker lock(&audio_lock);
    414     if (audioOutput)
    415         return audioOutput->GetCurrentVolume();
    416     return 0;
    417 }
    418 
    419 bool NuppelVideoPlayer::SetMuted(bool mute)
    420 {
    421     QMutexLocker lock(&audio_lock);
    422     bool is_muted = IsMuted();
    423 
    424     if (audioOutput && !is_muted && mute &&
    425         (kMuteAll == SetMuteState(kMuteAll)))
    426     {
    427         VERBOSE(VB_AUDIO, "muting sound " <<IsMuted());
    428         return true;
    429     }
    430     else if (audioOutput && is_muted && !mute &&
    431              (kMuteOff == SetMuteState(kMuteOff)))
    432     {
    433         VERBOSE(VB_AUDIO, "unmuting sound "<<IsMuted());
    434         return true;
    435     }
    436 
    437     VERBOSE(VB_AUDIO, "not changing sound mute state "<<IsMuted());
    438 
    439     return false;
    440 }
    441 
    442 MuteState NuppelVideoPlayer::SetMuteState(MuteState mstate)
    443 {
    444     QMutexLocker lock(&audio_lock);
    445     if (audioOutput)
    446         return audioOutput->SetMuteState(mstate);
    447     return kMuteAll;
    448 }
    449 
    450 MuteState NuppelVideoPlayer::IncrMuteState(void)
    451 {
    452     QMutexLocker lock(&audio_lock);
    453     MuteState mstate = kMuteAll;
    454     if (audioOutput)
    455         mstate = SetMuteState(VolumeBase::NextMuteState(GetMuteState()));
    456     return mstate;
    457 }
    458 
    459 MuteState NuppelVideoPlayer::GetMuteState(void)
    460 {
    461     QMutexLocker lock(&audio_lock);
    462     if (audioOutput)
    463         return audioOutput->GetMuteState();
    464     return kMuteAll;
    465 }
    466 
    467 uint NuppelVideoPlayer::AdjustVolume(int change)
    468 {
    469     QMutexLocker lock(&audio_lock);
    470     if (audioOutput)
    471         audioOutput->AdjustCurrentVolume(change);
    472     return GetVolume();
    473 }
    474 
    475410void NuppelVideoPlayer::PauseDecoder(void)
    476411{
    477412    decoder_lock.lock();
     
    907842
    908843    if (!audioOutput && !using_null_videoout && player_ctx->IsAudioNeeded())
    909844    {
    910         bool setVolume = gContext->GetNumSetting("MythControlsVolume", 1);
    911845        audioOutput = AudioOutput::OpenAudio(audio_main_device,
    912846                                             audio_passthru_device,
    913847                                             audio_bits, audio_channels,
    914848                                             audio_codec, audio_samplerate,
    915849                                             AUDIOOUTPUT_VIDEO,
    916                                              setVolume, audio_passthru);
     850                                             audio_passthru);
    917851        if (!audioOutput)
    918852            errMsg = QObject::tr("Unable to create AudioOutput.");
    919853        else
     
    935869            VERBOSE(VB_IMPORTANT, LOC + "Enabling Audio");
    936870            no_audio_out = false;
    937871        }
    938         if (audio_muted_on_creation)
    939         {
    940             SetMuteState(kMuteAll);
    941             audio_muted_on_creation = false;
    942         }
    943872    }
    944873
    945874    if (audioOutput)
  • libs/libmythtv/DetectLetterbox.cpp

     
    88#include "DetectLetterbox.h"
    99#include "NuppelVideoPlayer.h"
    1010#include "videoouttypes.h"
     11#include "mythcontext.h"
    1112
    1213DetectLetterbox::DetectLetterbox(NuppelVideoPlayer* const nvp)
    1314{
  • libs/libmythtv/avformatdecoder.cpp

     
    464464      audioSamples(NULL),           audioSamplesResampled(NULL),
    465465      reformat_ctx(NULL),           audio_src_fmt(SAMPLE_FMT_NONE),
    466466      allow_ac3_passthru(false),    allow_dts_passthru(false),
    467       internal_vol(false),
    468467      disable_passthru(false),      max_channels(2),
    469468      last_ac3_channels(0),         dummy_frame(NULL),
    470469      // DVD
     
    487486    max_channels = (uint) gContext->GetNumSetting("MaxChannels", 2);
    488487    allow_ac3_passthru = (max_channels > 2) ? gContext->GetNumSetting("AC3PassThru", false) : false;
    489488    allow_dts_passthru = (max_channels > 2) ? gContext->GetNumSetting("DTSPassThru", false) : false;
    490     internal_vol = gContext->GetNumSetting("MythControlsVolume", 0);
    491489
    492490    audioIn.sample_size = -32; // force SetupAudioStream to run once
    493491    itv = GetNVP()->GetInteractiveTV();
     
    43654363
    43664364    if (ctx->codec_id == CODEC_ID_AC3)
    43674365        passthru = allow_ac3_passthru &&
    4368                    ctx->channels >= (int)max_channels &&
    4369                    !internal_vol;
     4366                   ctx->channels >= (int)max_channels;
    43704367    else if (ctx->codec_id == CODEC_ID_DTS)
    4371         passthru = allow_dts_passthru && !internal_vol;
     4368        passthru = allow_dts_passthru;
    43724369
    43734370    passthru &= !transcoding && !disable_passthru;
    43744371    // Don't know any cards that support spdif clocked at < 44100
  • libs/libmythtv/tv_play.h

     
    2424#include "programlist.h"
    2525#include "channelutil.h"
    2626#include "videoouttypes.h"
    27 #include "volumebase.h"
     27#include "volumecontrolmanager.h"
    2828#include "inputinfo.h"
    2929#include "channelgroup.h"
    3030
     
    292292    void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*);
    293293    void ClearUDPNotifyEvents(void);
    294294
     295    void VolumeChanged(int volume);
     296    void MuteChanged(bool mute);
     297
    295298  protected:
    296299    void TreeMenuEntered(OSDListTreeItemEnteredEvent *e);
    297300    void TreeMenuSelected(OSDListTreeItemSelectedEvent *e);
     
    301304    virtual void run(void);
    302305    void TVEventThreadChecks(void);
    303306
    304     void SetMuteTimer(PlayerContext*, int timeout);
    305     bool MuteChannelChange(PlayerContext *ctx);
    306 
    307307    bool eventFilter(QObject *o, QEvent *e);
    308308    static QStringList lastProgramStringList;
    309309    static EMBEDRETURNPROGRAM RunPlaybackBoxPtr;
     
    493493
    494494    vector<long long> TeardownAllNVPs(PlayerContext*);
    495495    void RestartAllNVPs(PlayerContext *lctx,
    496                         const vector<long long> &pos,
    497                         MuteState mctx_mute);
     496                        const vector<long long> &pos);
    498497    void RestartMainNVP(PlayerContext *mctx);
    499498
    500499    void PxPToggleView(  PlayerContext *actx, bool wantPBP);
     
    654653    /// Picture attribute to modify (on arrow left or right)
    655654    PictureAttribute  adjustingPictureAttribute;
    656655
     656    QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface
     657
    657658    // Ask Allow state
    658659    AskAllowType                 askAllowType;
    659660    QMap<QString,AskProgramInfo> askAllowPrograms;
     
    811812    TimerContextMap      stateChangeTimerId;
    812813    TimerContextMap      signalMonitorTimerId;
    813814    TimerContextMap      tvchainUpdateTimerId;
    814     TimerContextMap      unmuteTimerId;
    815815
    816816    /// Condition to signal that the Event thread is up and running
    817817    QWaitCondition mainLoopCond;
     
    832832
    833833    ///< Timeout for entry modes in msec
    834834    static const uint kInputModeTimeout;
    835     /// Channel changing mute timeout in msec
    836     static const uint kMuteTimeout;
    837835    /// Timeout for updating LCD info in msec
    838836    static const uint kLCDTimeout;
    839837    /// Timeout for browse mode exit in msec
  • libs/libmythtv/playercontext.cpp

     
    1111#include "util-osx-cocoa.h"
    1212#include "videoouttypes.h"
    1313#include "storagegroup.h"
     14#include "mythcontext.h"
    1415
    1516#define LOC QString("playCtx: ")
    1617#define LOC_ERR QString("playCtx, Error: ")
     
    429430
    430431bool PlayerContext::CreateNVP(TV *tv, QWidget *widget,
    431432                              TVState desiredState,
    432                               WId embedwinid, const QRect *embedbounds,
    433                               bool muted)
     433                              WId embedwinid, const QRect *embedbounds)
    434434{
    435435    int exact_seeking = gContext->GetNumSetting("ExactSeeking", 0);
    436436
     
    441441        return false;
    442442    }
    443443
    444     NuppelVideoPlayer *_nvp = new NuppelVideoPlayer(muted);
     444    NuppelVideoPlayer *_nvp = new NuppelVideoPlayer();
    445445
    446446    if (nohardwaredecoders)
    447447        _nvp->DisableHardwareDecoders();
     
    491491            QString errMsg = nvp->ReinitAudio();
    492492        }
    493493    }
    494     else if (pipState == kPBPRight)
    495         nvp->SetMuted(true);
    496494
    497495    int maxWait = -1;
    498496    //if (isPIP())
  • libs/libmythtv/NuppelVideoPlayer.h

     
    44#include <sys/time.h>
    55
    66#include "playercontext.h"
    7 #include "volumebase.h"
    87#include "RingBuffer.h"
    98#include "osd.h"
    109#include "jitterometer.h"
     
    104103    friend class PlayerContext;
    105104
    106105  public:
    107     NuppelVideoPlayer(bool muted = false);
     106    NuppelVideoPlayer();
    108107   ~NuppelVideoPlayer();
    109108
    110109    // Initialization
     
    127126    void SetAudioInfo(const QString &main, const QString &passthru, uint rate);
    128127    void SetAudioParams(int bits, int channels, int codec, int samplerate, bool passthru);
    129128    void SetEffDsp(int dsprate);
    130     uint AdjustVolume(int change);
    131     bool SetMuted(bool mute);
    132     MuteState SetMuteState(MuteState);
    133     MuteState IncrMuteState(void);
    134129    void SetAudioCodec(void *ac);
    135130
    136131    // Sets
     
    187182    float   GetVideoAspect(void) const        { return video_aspect; }
    188183    float   GetFrameRate(void) const          { return video_frame_rate; }
    189184
    190     uint    GetVolume(void);
    191185    int     GetSecondsBehind(void) const;
    192186    AspectOverrideMode GetAspectOverride(void) const;
    193187    AdjustFillMode     GetAdjustFill(void) const;
    194     MuteState          GetMuteState(void);
    195188    CommSkipMode       GetAutoCommercialSkip(void) const;
    196189
    197190    int     GetFFRewSkip(void) const          { return ffrew_skip; }
     
    227220    bool    HasAudioOut(void) const           { return !no_audio_out; }
    228221    bool    IsPIPActive(void) const           { return pip_active; }
    229222    bool    IsPIPVisible(void) const          { return pip_visible; }
    230     bool    IsMuted(void)              { return GetMuteState() == kMuteAll; }
    231223    bool    IsIVTVDecoder(void) const;
    232224    bool    UsingNullVideo(void) const { return using_null_videoout; }
    233225    bool    HasTVChainNext(void) const;
     
    721713    float    audio_stretchfactor;
    722714    bool     audio_passthru;
    723715    QMutex   audio_lock;
    724     bool     audio_muted_on_creation;
    725716
    726717    // Picture-in-Picture
    727718    mutable QMutex pip_players_lock;
  • libs/libmythtv/tv_play.cpp

     
    8383
    8484
    8585const uint TV::kInputModeTimeout             = 5000;
    86 const uint TV::kMuteTimeout                  = 800;
    8786const uint TV::kLCDTimeout                   = 1000;
    8887const uint TV::kBrowseTimeout                = 30000;
    8988const uint TV::kKeyRepeatTimeout             = 300;
     
    894893    player.push_back(new PlayerContext("player"));
    895894    playerActive = 0;
    896895    playerLock.unlock();
     896
     897    volumeControl = VolumeControlManager::GetControl(gContext->GetSetting("MixerDevice"));
     898    if (volumeControl)
     899    {
     900        connect(volumeControl.data(), SIGNAL(changedVolume(int)),
     901                this, SLOT(VolumeChanged(int)), Qt::QueuedConnection);
     902        connect(volumeControl.data(), SIGNAL(changedMute(bool)),
     903                this, SLOT(MuteChanged(bool)), Qt::QueuedConnection);
     904    }
    897905}
    898906
    899907/** \fn TV::Init(bool)
     
    27872795    if (handled)
    27882796        return;
    27892797
    2790     // Check unmute..
    2791     ctx = NULL;
    2792     {
    2793         QMutexLocker locker(&timerIdLock);
    2794         TimerContextMap::iterator it = unmuteTimerId.find(timer_id);
    2795         if (it != unmuteTimerId.end())
    2796         {
    2797             KillTimer(timer_id);
    2798             ctx = *it;
    2799             unmuteTimerId.erase(it);
    2800         }
    2801     }
    2802 
    2803     if (ctx)
    2804     {
    2805         PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__);
    2806         if (find_player_index(ctx) >= 0)
    2807         {
    2808             ctx->LockDeleteNVP(__FILE__, __LINE__);
    2809             if (ctx->nvp && ctx->nvp->IsMuted())
    2810                 ctx->nvp->SetMuted(false);
    2811             ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    2812         }
    2813         ReturnPlayerLock(mctx);
    2814         handled = true;
    2815     }
    2816 
    28172798    if (handled)
    28182799        return;
    28192800
     
    53755356        }
    53765357    }
    53775358
    5378     MuteState mctx_mute = kMuteOff;
    5379     mctx->LockDeleteNVP(__FILE__, __LINE__);
    5380     if (mctx->nvp)
    5381         mctx_mute = mctx->nvp->GetMuteState();
    5382     mctx->UnlockDeleteNVP(__FILE__, __LINE__);
    5383 
    53845359    vector<long long> pos = TeardownAllNVPs(mctx);
    53855360
    53865361    if (wantPBP)
     
    53985373        }
    53995374    }
    54005375
    5401     RestartAllNVPs(mctx, pos, mctx_mute);
     5376    RestartAllNVPs(mctx, pos);
    54025377
    54035378    VERBOSE(VB_PLAYBACK, LOC +
    54045379            QString("PxPToggleType() converting from %1 to %2 -- end")
     
    55425517* \brief Recreate Main and PIP windows. Could be either PIP or PBP views.
    55435518*/
    55445519void TV::RestartAllNVPs(PlayerContext *lctx,
    5545                         const vector<long long> &pos,
    5546                         MuteState mctx_mute)
     5520                        const vector<long long> &pos)
    55475521{
    55485522    QString loc = LOC + QString("RestartAllNVPs(): ");
    55495523
     
    55905564            pipctx->LockDeleteNVP(__FILE__, __LINE__);
    55915565            if (pipctx->nvp)
    55925566            {
    5593                 pipctx->nvp->SetMuted(true);
    55945567                pipctx->nvp->JumpToFrame(pos[i]);
    55955568            }
    55965569            pipctx->UnlockDeleteNVP(__FILE__, __LINE__);
     
    56025575            ForceNextStateNone(pipctx);
    56035576        }
    56045577    }
    5605 
    5606     // If old main player had a kMuteAll | kMuteOff setting,
    5607     // apply old main player's mute setting to new main player.
    5608     mctx->LockDeleteNVP(__FILE__, __LINE__);
    5609     if (mctx->nvp && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))
    5610         mctx->nvp->SetMuteState(mctx_mute);
    5611     mctx->UnlockDeleteNVP(__FILE__, __LINE__);
    56125578}
    56135579
    56145580void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx)
     
    56365602        return;
    56375603    }
    56385604
    5639     MuteState mctx_mute = mctx->nvp->GetMuteState();
    56405605    mctx->deleteNVPLock.unlock();
    56415606    pipctx->deleteNVPLock.unlock();
    56425607
     
    56505615    playerActive = (ctx_index == playerActive) ?
    56515616        0 : ((ctx_index == 0) ? ctx_index : playerActive);
    56525617
    5653     RestartAllNVPs(mctx, pos, mctx_mute);
     5618    RestartAllNVPs(mctx, pos);
    56545619
    56555620    SetActive(mctx, playerActive, false);
    56565621
     
    56715636        mctx->deleteNVPLock.unlock();
    56725637        return;
    56735638    }
    5674 
    5675     MuteState mctx_mute = mctx->nvp->GetMuteState();
    5676 
    5677     // HACK - FIXME
    5678     // workaround muted audio when NVP is re-created
    5679     mctx_mute = kMuteOff;
    5680     // FIXME - end
    56815639    mctx->deleteNVPLock.unlock();
    56825640
    56835641    vector<long long> pos = TeardownAllNVPs(mctx);
    5684     RestartAllNVPs(mctx, pos, mctx_mute);
     5642    RestartAllNVPs(mctx, pos);
    56855643    SetActive(mctx, playerActive, false);
    56865644
    56875645    VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end");
     
    58065764
    58075765    VERBOSE(VB_PLAYBACK, LOC + "DoNVPSeek() -- begin");
    58085766
    5809     bool muted = false;
    5810 
    58115767    ctx->LockDeleteNVP(__FILE__, __LINE__);
    58125768    if (!ctx->nvp)
    58135769    {
     
    58155771        return false;
    58165772    }
    58175773
    5818     if (ctx == GetPlayer(ctx, 0))
    5819         muted = MuteChannelChange(ctx);
    5820 
    58215774    bool res = false;
    58225775
    58235776    if (LONG_LONG_MIN != audiosyncBaseline)
     
    58385791    }
    58395792    ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    58405793
    5841     if (muted)
    5842         SetMuteTimer(ctx, kMuteTimeout);
    5843 
    58445794    VERBOSE(VB_PLAYBACK, LOC + "DoNVPSeek() -- end");
    58455795
    58465796    return res;
     
    61216071    if (StateIsLiveTV(GetState(ctx)))
    61226072        return;
    61236073
    6124     ctx->LockDeleteNVP(__FILE__, __LINE__);
    6125     bool muted = MuteChannelChange(ctx);
    6126     ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    6127 
    61286074    struct StatusPosInfo posInfo;
    61296075    ctx->CalcNVPSliderPosition(posInfo);
    61306076
     
    61436089    if (ctx->nvp)
    61446090        ctx->nvp->SkipCommercials(direction);
    61456091    ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    6146 
    6147     if (muted)
    6148         SetMuteTimer(ctx, kMuteTimeout);
    61496092}
    61506093
    61516094void TV::SwitchSource(uint source_direction)
     
    63156258        if (mctx != ctx)
    63166259            PIPRemovePlayer(mctx, ctx);
    63176260
    6318         bool muted = false;
    6319         ctx->LockDeleteNVP(__FILE__, __LINE__);
    6320         if (ctx->nvp && ctx->nvp->IsMuted())
    6321             muted = true;
    6322         ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    6323 
    63246261        // pause the decoder first, so we're not reading too close to the end.
    63256262        ctx->buffer->IgnoreLiveEOF(true);
    63266263        ctx->buffer->StopReads();
     
    63726309
    63736310            if (ctx->CreateNVP(
    63746311                    this, gContext->GetMainWindow(), ctx->GetState(),
    6375                     mctx->embedWinID, &mctx->embedBounds, muted))
     6312                    mctx->embedWinID, &mctx->embedBounds))
    63766313            {
    63776314                ScheduleStateChange(ctx);
    63786315                ok = true;
     
    67296666
    67306667void TV::ChangeChannel(PlayerContext *ctx, int direction)
    67316668{
    6732     bool muted = false;
    6733 
    67346669    if ((browse_changrp || (direction == CHANNEL_DIRECTION_FAVORITE)) &&
    67356670        (channel_group_id > -1))
    67366671    {
     
    67616696
    67626697    QString oldinputname = ctx->recorder->GetInput();
    67636698
    6764     muted = MuteChannelChange(ctx);
    6765 
    67666699    if (ctx->paused)
    67676700    {
    67686701        OSD *osd = GetOSDLock(ctx);
     
    67906723    ctx->recorder->ChangeChannel(direction);
    67916724    ClearInputQueues(ctx, false);
    67926725
    6793     if (muted)
    6794         SetMuteTimer(ctx, kMuteTimeout * 2);
    6795 
    67966726    UnpauseLiveTV(ctx);
    67976727
    67986728    if (oldinputname != ctx->recorder->GetInput())
     
    68096739
    68106740    QString channum = chan;
    68116741    QStringList reclist;
    6812     bool muted = false;
    68136742
    68146743    QString oldinputname = ctx->recorder->GetInput();
    68156744
     
    68796808    if (getit || !ctx->recorder || !ctx->recorder->CheckChannel(channum))
    68806809        return;
    68816810
    6882     muted = MuteChannelChange(ctx);
    6883 
    68846811    OSD *osd = GetOSDLock(ctx);
    68856812    if (osd && ctx->paused)
    68866813    {
     
    69066833
    69076834    ctx->recorder->SetChannel(channum);
    69086835
    6909     if (muted)
    6910         SetMuteTimer(ctx, kMuteTimeout * 2);
    6911 
    69126836    UnpauseLiveTV(ctx);
    69136837
    69146838    if (oldinputname != ctx->recorder->GetInput())
     
    80197943
    80207944void TV::ChangeVolume(PlayerContext *ctx, bool up)
    80217945{
    8022     ctx->LockDeleteNVP(__FILE__, __LINE__);
    8023     if (!ctx->nvp)
     7946    if (volumeControl)
    80247947    {
    8025         ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    8026         return;
     7948        if (up)
     7949            volumeControl->increaseVolume();
     7950        else
     7951            volumeControl->decreaseVolume();
    80277952    }
    8028     uint curvol = ctx->nvp->AdjustVolume((up) ? +2 : -2);
    8029     ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    8030 
    8031     QString text = tr("Volume %1 %").arg(curvol);
    8032 
    8033     OSD *osd = GetOSDLock(ctx);
    8034     if (osd && !browsemode)
    8035     {
    8036         osd->ShowStatus(curvol * 10, true, tr("Adjust Volume"), text, 5,
    8037                         kOSDFunctionalType_PictureAdjust);
    8038         SetUpdateOSDPosition(false);
    8039     }
    8040     ReturnOSDLock(ctx, osd);
    80417953}
    80427954
    80437955void TV::ToggleTimeStretch(PlayerContext *ctx)
     
    81868098
    81878099void TV::ToggleMute(PlayerContext *ctx)
    81888100{
    8189     ctx->LockDeleteNVP(__FILE__, __LINE__);
    8190     if (!ctx->nvp || !ctx->nvp->HasAudioOut())
    8191     {
    8192         ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    8193         return;
    8194     }
    8195 
    8196     MuteState mute_status;
    8197 
    8198     if (!MuteIndividualChannels)
    8199     {
    8200         ctx->nvp->SetMuted(!ctx->nvp->IsMuted());
    8201         mute_status = (ctx->nvp->IsMuted()) ? kMuteAll : kMuteOff;
    8202     }
    8203     else
    8204     {
    8205         mute_status = ctx->nvp->IncrMuteState();
    8206     }
    8207     ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    8208 
    8209     QString text;
    8210 
    8211     switch (mute_status)
    8212     {
    8213         case kMuteOff:   text = tr("Mute Off"); break;
    8214         case kMuteAll:   text = tr("Mute On"); break;
    8215         case kMuteLeft:  text = tr("Left Channel Muted"); break;
    8216         case kMuteRight: text = tr("Right Channel Muted"); break;
    8217     }
    8218 
    8219     OSD *osd = GetOSDLock(ctx);
    8220     if (osd && !browsemode)
    8221         osd->SetSettingsText(text, 5);
    8222     ReturnOSDLock(ctx, osd);
     8101    if (volumeControl)
     8102        volumeControl->setMute(!volumeControl->mute());
    82238103}
    82248104
    82258105void TV::ToggleSleepTimer(const PlayerContext *ctx)
     
    83798259    ReturnOSDLock(ctx, osd);
    83808260}
    83818261
    8382 void TV::SetMuteTimer(PlayerContext *ctx, int timeout)
    8383 {
    8384     // message to set the timer will be posted to the main UI thread
    8385     // where it will be caught in eventFilter and processed as CustomEvent
    8386     // this will properly set the mute timer
    8387     // otherwise it never fires on Win32
    8388     QString message = QString("UNMUTE %1 %2").arg((long long)ctx).arg(timeout);
    8389     qApp->postEvent(gContext->GetMainWindow(), new MythEvent(message));
    8390 }
    8391 
    8392 bool TV::MuteChannelChange(PlayerContext *ctx)
    8393 {
    8394     if (!ctx)
    8395         return false;
    8396 
    8397     bool muted = false;
    8398     ctx->LockDeleteNVP(__FILE__, __LINE__);
    8399     if (ctx->nvp && !ctx->nvp->IsMuted())
    8400         muted = ctx->nvp->SetMuted(true);
    8401     ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    8402 
    8403     return muted;
    8404 }
    8405 
    84068262void TV::customEvent(QEvent *e)
    84078263{
    84088264    if ((MythEvent::Type)(e->type()) == kOSDClosedEventType)
     
    86788534        }
    86798535    }
    86808536
    8681     if (message.left(6) == "UNMUTE")
    8682     {
    8683         if (tokens.size() >= 3)
    8684         {
    8685             long long target = tokens[1].toLongLong();
    8686             PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__);
    8687             for (uint i = 0; i < player.size(); i++)
    8688             {
    8689                 PlayerContext *ctx = GetPlayer(mctx, i);
    8690                 if (((long long)ctx) == target)
    8691                 {
    8692                     QMutexLocker locker(&timerIdLock);
    8693                     unmuteTimerId[StartTimer(tokens[2].toUInt(), __LINE__)] = ctx;
    8694                 }
    8695             }
    8696             ReturnPlayerLock(mctx);
    8697         }
    8698     }
    8699 
    87008537    if (message.left(9) == "START_EPG")
    87018538    {
    87028539        int editType = tokens[1].toInt();
     
    91709007        {
    91719008            value = ctx->nvp->getVideoOutput()->GetPictureAttribute(attr);
    91729009        }
    9173         else if (ctx->nvp->HasAudioOut())
     9010        else if (ctx->nvp->HasAudioOut() && volumeControl)
    91749011        {
    9175             value = ctx->nvp->GetVolume();
     9012            value = volumeControl->volume();
    91769013            title = tr("Adjust Volume");
    91779014        }
    91789015    }
     
    1167611513    ReturnPlayerLock(mctx);
    1167711514}
    1167811515
     11516void TV::VolumeChanged(int volume)
     11517{
     11518    OSD *osd = GetOSDL(__FILE__, __LINE__);
     11519    if (osd && !browsemode)
     11520    {
     11521        osd->ShowStatus(volume * 10, true, tr("Adjust Volume"),
     11522                        tr("Volume %1 %").arg(volume), 5,
     11523                        kOSDFunctionalType_PictureAdjust);
     11524        SetUpdateOSDPosition(false);
     11525    }
     11526    ReturnOSDLock(osd);
     11527}
     11528
     11529void TV::MuteChanged(bool mute)
     11530{
     11531    OSD *osd = GetOSDL(__FILE__, __LINE__);
     11532    if (osd && !browsemode)
     11533        osd->SetSettingsText(mute ? tr("Mute On") : tr("Mute Off"), 5);
     11534    ReturnOSDLock(osd);
     11535}
     11536
     11537
    1167911538OSD *TV::GetOSDL(const char *file, int location)
    1168011539{
    1168111540    PlayerContext *actx = GetPlayerReadLock(-1, file, location);
  • libs/libmythtv/playercontext.h

     
    4848    // Actions
    4949    bool CreateNVP(TV *tv, QWidget *widget,
    5050                   TVState desiredState,
    51                    WId embedwinid, const QRect *embedBounds,
    52                    bool muted = false);
     51                   WId embedwinid, const QRect *embedBounds);
    5352    void TeardownPlayer(void);
    5453    bool StartDecoderThread(int maxWait = -1);
    5554    bool StartOSD(TV *tv);
  • libs/libmythtv/avformatdecoder.h

     
    264264
    265265    bool              allow_ac3_passthru;
    266266    bool              allow_dts_passthru;
    267     bool              internal_vol;
    268267    bool              disable_passthru;
    269268    uint              max_channels;
    270269    uint              last_ac3_channels;
  • libs/libmyth/audiooutputwin.cpp

     
    270270{
    271271    return m_nPkts * fragment_size;
    272272}
    273 
    274 int AudioOutputWin::GetVolumeChannel(int channel) const
    275 {
    276     DWORD dwVolume = 0xffffffff;
    277     int Volume = 100;
    278     if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))
    279     {
    280         Volume = (channel == 0) ?
    281             (LOWORD(dwVolume) / (0xffff / 100)) :
    282             (HIWORD(dwVolume) / (0xffff / 100));
    283     }
    284 
    285     VERBOSE(VB_AUDIO, "GetVolume(" << channel << ") "
    286             << Volume << "(" << dwVolume << ")");
    287 
    288     return Volume;
    289 }
    290 
    291 void AudioOutputWin::SetVolumeChannel(int channel, int volume)
    292 {
    293     if (channel > 1)
    294     {
    295         Error(QString("Error setting channel: %1. "
    296                       "Only stereo volume supported").arg(channel));
    297         return;
    298     }
    299 
    300     DWORD dwVolume = 0xffffffff;
    301     if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))
    302     {
    303         if (channel == 0)
    304             dwVolume = dwVolume & 0xffff0000 | volume * (0xffff / 100);
    305         else
    306             dwVolume = dwVolume & 0xffff | ((volume * (0xffff / 100)) << 16);
    307     }
    308     else
    309     {
    310         dwVolume = volume * (0xffff / 100);
    311         dwVolume |= (dwVolume << 16);
    312     }
    313 
    314     VERBOSE(VB_AUDIO, QString("SetVolume(%1) %2(%3)")
    315             .arg(channel).arg(volume).arg(dwVolume));
    316     waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, dwVolume);
    317 }
  • 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
     19QHash<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
     40QSharedPointer<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}
  • libs/libmyth/volumecontrolalsa.cpp

     
     1#include "volumecontrolalsa.h"
     2
     3#include "mythverbose.h"
     4#include <algorithm>
     5
     6QHash<QString, QString> VolumeControlALSA::Enumerate()
     7{
     8    QHash<QString, QString> result;
     9
     10    result.insert("ALSA:default", "Default ALSA device");
     11
     12    int card = -1;
     13    while (snd_card_next(&card) >= 0 && card >= 0)
     14    {
     15        snd_ctl_t* handle;
     16        if (!snd_ctl_open(&handle,
     17                          QString("hw:%1").arg(card).toAscii().constData(), 0))
     18        {
     19            snd_ctl_card_info_t *info;
     20            snd_ctl_card_info_alloca(&info);
     21
     22            if (!snd_ctl_card_info(handle, info))
     23            {
     24                result.insert(QString("ALSA:hw:%1")
     25                              .arg(snd_ctl_card_info_get_id(info)),
     26                              snd_ctl_card_info_get_name(info));
     27            }
     28            snd_ctl_close(handle);
     29        }
     30    }
     31
     32    return result;
     33}
     34
     35VolumeControlALSA::VolumeControlALSA(QString device) :
     36    m_MixerHandle(NULL),
     37    m_MixerElement(NULL),
     38    m_Range(1)
     39{
     40    if (snd_mixer_open(&m_MixerHandle, 0) < 0)
     41    {
     42        VERBOSE(VB_IMPORTANT,
     43                QString("VolumeControlALSA::VolumeControlALSA() - ERROR: "
     44                        "opening mixer"));
     45        return;
     46    }
     47
     48    if (snd_mixer_attach(m_MixerHandle, device.toAscii().constData()) < 0)
     49    {
     50        VERBOSE(VB_IMPORTANT,
     51                QString("VolumeControlALSA::VolumeControlALSA() - ERROR: "
     52                        "attaching mixer \"%1\"")
     53                .arg(device));
     54        return;
     55    }
     56
     57    if (snd_mixer_selem_register(m_MixerHandle, NULL, NULL) < 0)
     58    {
     59        VERBOSE(VB_IMPORTANT,
     60                QString("VolumeControlALSA::VolumeControlALSA() - ERROR: "
     61                        "registering mixer"));
     62        return;
     63    }
     64
     65    if (snd_mixer_load(m_MixerHandle) < 0)
     66    {
     67        VERBOSE(VB_IMPORTANT,
     68                QString("VolumeControlALSA::VolumeControlALSA() - ERROR: "
     69                        "loading mixer"));
     70        return;
     71    }
     72
     73    for (m_MixerElement = snd_mixer_first_elem(m_MixerHandle);
     74         m_MixerElement;
     75         m_MixerElement = snd_mixer_elem_next(m_MixerElement))
     76    {
     77        if (!snd_mixer_selem_is_active(m_MixerElement))
     78            continue;
     79
     80        if (!snd_mixer_selem_has_playback_volume(m_MixerElement))
     81           continue;
     82
     83        VERBOSE(VB_AUDIO,
     84                QString("VolumeControlALSA::VolumeControlALSA() - "
     85                        "Using \"%1\"")
     86                .arg(snd_mixer_selem_get_name(m_MixerElement)));
     87
     88        break;
     89    }
     90
     91    if (!m_MixerElement)
     92    {
     93        VERBOSE(VB_IMPORTANT,
     94                QString("VolumeControlALSA::VolumeControlALSA() - ERROR: "
     95                        "unable to find volume control"));
     96        return;
     97    }
     98
     99    long min, max;
     100    snd_mixer_selem_get_playback_volume_range(m_MixerElement, &min, &max);
     101    m_Range = std::min(std::max(1l, max - min), 100l);
     102
     103    snd_mixer_selem_set_playback_volume_range(m_MixerElement, 0, 100);
     104
     105    snd_mixer_elem_set_callback_private(m_MixerElement, this);
     106    snd_mixer_elem_set_callback(m_MixerElement, &event);
     107
     108    if (!pipe(m_Exit))
     109        start();
     110}
     111
     112VolumeControlALSA::~VolumeControlALSA()
     113{
     114    if (isRunning())
     115    {
     116        write(m_Exit[1], "", 1);
     117
     118        wait();
     119
     120        close(m_Exit[0]);
     121        close(m_Exit[1]);
     122    }
     123
     124    if (m_MixerHandle)
     125        snd_mixer_close(m_MixerHandle);
     126}
     127
     128int VolumeControlALSA::volume() const
     129{
     130    long volume = 0;
     131    if (m_MixerElement)
     132    {
     133        if (snd_mixer_selem_has_playback_switch(m_MixerElement) || !mute())
     134            snd_mixer_selem_get_playback_volume(m_MixerElement,
     135                                                SND_MIXER_SCHN_MONO,
     136                                                &volume);
     137        else
     138            volume = m_Volume;
     139    }
     140
     141    VERBOSE(VB_AUDIO,
     142            QString("VolumeControlALSA::volume() = %1")
     143            .arg(volume));
     144
     145    return volume;
     146}
     147
     148void VolumeControlALSA::setVolume(int volume)
     149{
     150    VERBOSE(VB_AUDIO,
     151            QString("VolumeControlALSA::setVolume(%1)")
     152            .arg(volume));
     153
     154    volume = std::min(std::max(0, volume), 100);
     155
     156    if (mute() && volume > VolumeControlALSA::volume())
     157        setMute(false);
     158
     159    if (m_MixerElement)
     160        if (snd_mixer_selem_has_playback_switch(m_MixerElement) || !mute())
     161            snd_mixer_selem_set_playback_volume_all(m_MixerElement,
     162                                                    volume);
     163
     164    if (m_Volume.fetchAndStoreRelaxed(volume) != volume)
     165        emit changedVolume(volume);
     166}
     167
     168void VolumeControlALSA::increaseVolume()
     169{
     170    setVolume((volume() * m_Range + 100) / m_Range);
     171}
     172
     173void VolumeControlALSA::decreaseVolume()
     174{
     175    setVolume((volume() * m_Range - 100) / m_Range);
     176}
     177
     178bool VolumeControlALSA::mute() const
     179{
     180    union {
     181        int _switch;
     182        long int _volume;
     183    } playback;
     184   
     185    playback._switch = true;
     186
     187    if (m_MixerElement)
     188    {
     189        if (snd_mixer_selem_has_playback_switch(m_MixerElement))
     190            snd_mixer_selem_get_playback_switch(m_MixerElement,
     191                                                SND_MIXER_SCHN_MONO,
     192                                                &playback._switch);
     193        else
     194            snd_mixer_selem_get_playback_volume(m_MixerElement,
     195                                                SND_MIXER_SCHN_MONO,
     196                                                &playback._volume);
     197    }
     198
     199    VERBOSE(VB_AUDIO,
     200            QString("VolumeControlALSA::mute() = %1")
     201            .arg(!playback._switch ? "mute" : "unmute"));
     202
     203    return !playback._switch;
     204}
     205
     206void VolumeControlALSA::setMute(bool mute)
     207{
     208    VERBOSE(VB_AUDIO,
     209            QString("VolumeControlALSA::setMute(%1)")
     210            .arg(mute ? "mute" : "unmute"));
     211
     212    if (m_MixerElement)
     213    {
     214        if (snd_mixer_selem_has_playback_switch(m_MixerElement))
     215            snd_mixer_selem_set_playback_switch_all(m_MixerElement,
     216                                                    !mute);
     217        else
     218            snd_mixer_selem_set_playback_volume_all(m_MixerElement,
     219                                                    mute ? 0 : static_cast<int>(m_Volume));
     220    }
     221
     222    if (m_Mute.fetchAndStoreRelaxed(mute) != mute)
     223        emit changedMute(mute);
     224}
     225
     226// static
     227int VolumeControlALSA::event(snd_mixer_elem_t* elem, unsigned int mask)
     228{
     229    VERBOSE(VB_AUDIO,
     230            QString("VolumeControlALSA::event(%1)")
     231            .arg(mask));
     232
     233    VolumeControlALSA* that =
     234        static_cast<VolumeControlALSA*>(snd_mixer_elem_get_callback_private(elem));
     235
     236    if (mask == SND_CTL_EVENT_MASK_REMOVE)
     237    {
     238        that->m_MixerElement = NULL;
     239        return 0;
     240    }
     241
     242    if (mask & SND_CTL_EVENT_MASK_VALUE)
     243    {
     244        int volume = that->volume();
     245        if (that->m_Volume.fetchAndStoreRelaxed(volume) != volume)
     246            emit that->changedVolume(volume);
     247
     248        bool mute = that->mute();
     249        if (that->m_Mute.fetchAndStoreRelaxed(mute) != mute)
     250            emit that->changedMute(mute);
     251    }
     252
     253    return 0;
     254}
     255
     256void VolumeControlALSA::run()
     257{
     258    VERBOSE(VB_AUDIO,
     259            QString("VolumeControlALSA::run() - begin"));
     260
     261    m_Volume = volume();
     262    m_Mute = mute();
     263
     264    int poll_descriptors_count = -1;
     265    struct pollfd* poll_descriptors = NULL;
     266
     267    for(;;)
     268    {
     269        int poll_descriptors_count_new =
     270            snd_mixer_poll_descriptors_count(m_MixerHandle);
     271
     272        if (poll_descriptors_count_new < 0)
     273        {
     274            VERBOSE(VB_IMPORTANT,
     275                    QString("VolumeControlALSA::run() - ERROR: "
     276                            "snd_mixer_poll_descriptors_count"));
     277            break;
     278        }
     279
     280        if (poll_descriptors_count != poll_descriptors_count_new)
     281        {
     282            delete(poll_descriptors);
     283
     284            poll_descriptors_count = poll_descriptors_count_new;
     285            poll_descriptors = new struct pollfd[poll_descriptors_count + 1];
     286
     287            if (!poll_descriptors)
     288            {
     289                VERBOSE(VB_IMPORTANT,
     290                        QString("VolumeControlALSA::run() - ERROR: "
     291                                "malloc"));
     292                break;
     293            }
     294        }
     295
     296        bzero(poll_descriptors,
     297              poll_descriptors_count * sizeof (struct pollfd));
     298
     299        poll_descriptors->fd = m_Exit[0];
     300        poll_descriptors->events = POLLIN;
     301
     302        if (snd_mixer_poll_descriptors(m_MixerHandle,
     303                                       poll_descriptors + 1,
     304                                       poll_descriptors_count) !=
     305                                       poll_descriptors_count)
     306        {
     307            VERBOSE(VB_IMPORTANT,
     308                    QString("VolumeControlALSA::run() - ERROR: "
     309                            "snd_mixer_poll_descriptors"));
     310            break;
     311        }
     312
     313        if (poll(poll_descriptors, poll_descriptors_count + 1, -1) < 0)
     314        {
     315            VERBOSE(VB_IMPORTANT,
     316                    QString("VolumeControlALSA::run() - ERROR: "
     317                            "poll %1")
     318                    .arg(errno));
     319            break;
     320        }
     321
     322        if (poll_descriptors->revents & POLLIN)
     323            break;
     324
     325        unsigned short revents;
     326        if (snd_mixer_poll_descriptors_revents(m_MixerHandle,
     327                                               poll_descriptors + 1,
     328                                               poll_descriptors_count,
     329                                               &revents) < 0)
     330        {
     331            VERBOSE(VB_IMPORTANT,
     332                    QString("VolumeControlALSA::run() - ERROR: "
     333                            "snd_mixer_poll_descriptors_revents"));
     334            break;
     335        }
     336
     337        if (revents & (POLLNVAL | POLLERR))
     338        {
     339            VERBOSE(VB_IMPORTANT,
     340                    QString("VolumeControlALSA::run() - ERROR: "
     341                            "snd_mixer_poll_descriptors_revents"));
     342            break;
     343        }
     344
     345        if (snd_mixer_handle_events(m_MixerHandle) < 0)
     346        {
     347            VERBOSE(VB_IMPORTANT,
     348                    QString("VolumeControlALSA::run() - ERROR: "
     349                            "snd_mixer_handle_events"));
     350            break;
     351        }
     352    }
     353
     354    delete(poll_descriptors);
     355
     356    VERBOSE(VB_AUDIO,
     357            QString("VolumeControlALSA::run() - end"));
     358}
  • libs/libmyth/audiooutputbase.h

     
    1818#include "audiooutput.h"
    1919#include "samplerate.h"
    2020#include "mythverbose.h"
     21#include "volumecontrolmanager.h"
    2122
    2223namespace soundtouch {
    2324class SoundTouch;
     
    4748
    4849    virtual void Reset(void);
    4950
    50     void SetSWVolume(int new_volume, bool save);
    51     int GetSWVolume(void);
    52 
    5351    // timecode is in milliseconds.
    5452    virtual bool AddSamples(char *buffer, int samples, long long timecode);
    5553    virtual bool AddSamples(char *buffers[], int samples, long long timecode);
     
    113111    int audiolen(bool use_lock); // number of valid bytes in audio buffer
    114112    int audiofree(bool use_lock); // number of free bytes in audio buffer
    115113
    116     void UpdateVolume(void);
    117 
    118114    void SetStretchFactorLocked(float factor);
    119115
    120116    int GetBaseAudioTime()                    const { return audiotime;       }
     
    148144    bool killaudio;
    149145
    150146    bool pauseaudio, audio_actually_paused, was_paused;
    151     bool set_initial_vol;
    152147    bool buffer_output_data_for_use; //  used by AudioOutputNULL
    153148
    154149    int configured_audio_channels;
     
    181176    int surround_mode;
    182177    bool allow_ac3_passthru;
    183178    float old_audio_stretchfactor;
    184     int volume;
     179    QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface
    185180
    186181    bool blocking; // do AddSamples calls block?
    187182
  • libs/libmyth/audiooutputalsa.cpp

     
    2121AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
    2222    AudioOutputBase(settings),
    2323    pcm_handle(NULL),
    24     numbadioctls(0),
    25     mixer_handle(NULL),
    26     mixer_control(QString::null)
     24    numbadioctls(0)
    2725{
    2826    // Set everything up
    2927    Reconfigure(settings);
     
    249247    // it really is
    250248    audio_buffer_unused = soundcard_buffer_size - (fragment_size * 4);
    251249
    252     if (internal_vol)
    253         OpenMixer(set_initial_vol);
    254    
    255250    // Device opened successfully
    256251    return true;
    257252}
    258253
    259254void AudioOutputALSA::CloseDevice()
    260255{
    261     CloseMixer();
    262256    if (pcm_handle != NULL)
    263257    {
    264258        snd_pcm_close(pcm_handle);
     
    617611
    618612    return 0;
    619613}
    620 
    621 
    622 int AudioOutputALSA::GetVolumeChannel(int channel) const
    623 {
    624     long actual_volume;
    625 
    626     if (mixer_handle == NULL)
    627         return 100;
    628 
    629     QByteArray mix_ctl = mixer_control.toAscii();
    630     snd_mixer_selem_id_t *sid;
    631     snd_mixer_selem_id_alloca(&sid);
    632     snd_mixer_selem_id_set_index(sid, 0);
    633     snd_mixer_selem_id_set_name(sid, mix_ctl.constData());
    634 
    635     snd_mixer_elem_t *elem = snd_mixer_find_selem(mixer_handle, sid);
    636     if (!elem)
    637     {
    638         VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1")
    639                 .arg(mixer_control));
    640         return 100;
    641     }
    642 
    643     snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
    644     if (!snd_mixer_selem_has_playback_channel(elem, chan))
    645     {
    646         snd_mixer_selem_id_set_index(sid, channel);
    647         if ((elem = snd_mixer_find_selem(mixer_handle, sid)) == NULL)
    648         {
    649             VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1 %2")
    650                     .arg(mixer_control).arg(channel));
    651             return 100;
    652         }
    653     }
    654 
    655     ALSAVolumeInfo vinfo = GetVolumeRange(elem);
    656 
    657     snd_mixer_selem_get_playback_volume(
    658         elem, (snd_mixer_selem_channel_id_t)channel, &actual_volume);
    659 
    660     return vinfo.ToMythRange(actual_volume);
    661 }
    662 
    663 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)
    664 {
    665     SetCurrentVolume(mixer_control, channel, volume);
    666 }
    667 
    668 void AudioOutputALSA::SetCurrentVolume(QString control, int channel, int volume)
    669 {
    670     VERBOSE(VB_AUDIO, QString("Setting %1 volume to %2")
    671             .arg(control).arg(volume));
    672 
    673     if (!mixer_handle)
    674         return; // no mixer, nothing to do
    675 
    676     QByteArray ctl = control.toAscii();
    677     snd_mixer_selem_id_t *sid;
    678     snd_mixer_selem_id_alloca(&sid);
    679     snd_mixer_selem_id_set_index(sid, 0);
    680     snd_mixer_selem_id_set_name(sid, ctl.constData());
    681 
    682     snd_mixer_elem_t *elem = snd_mixer_find_selem(mixer_handle, sid);
    683     if (!elem)
    684     {
    685         VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1")
    686                 .arg(control));
    687         return;
    688     }
    689 
    690     snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
    691     if (!snd_mixer_selem_has_playback_channel(elem, chan))
    692     {
    693         snd_mixer_selem_id_set_index(sid, channel);
    694         if ((elem = snd_mixer_find_selem(mixer_handle, sid)) == NULL)
    695         {
    696             VERBOSE(VB_IMPORTANT,
    697                     QString("mixer unable to find control %1 %2")
    698                     .arg(control).arg(channel));
    699             return;
    700         }
    701     }
    702 
    703     ALSAVolumeInfo vinfo = GetVolumeRange(elem);
    704 
    705     long set_vol = vinfo.ToALSARange(volume);
    706 
    707     int err = snd_mixer_selem_set_playback_volume(elem, chan, set_vol);
    708     if (err < 0)
    709     {
    710         VERBOSE(VB_IMPORTANT, QString("mixer set channel %1 err %2: %3")
    711                 .arg(channel).arg(err).arg(snd_strerror(err)));
    712     }
    713     else
    714     {
    715         VERBOSE(VB_AUDIO, QString("channel %1 vol set to %2")
    716                 .arg(channel).arg(set_vol));
    717     }
    718 
    719     if (snd_mixer_selem_has_playback_switch(elem))
    720     {
    721         int unmute = (0 != set_vol);
    722         if (snd_mixer_selem_has_playback_switch_joined(elem))
    723         {
    724             // Only mute if all the channels should be muted.
    725             for (int i = 0; i < audio_channels; i++)
    726             {
    727                 if (0 != GetVolumeChannel(i))
    728                     unmute = 1;
    729             }
    730         }
    731 
    732         err = snd_mixer_selem_set_playback_switch(elem, chan, unmute);
    733         if (err < 0)
    734         {
    735             VERBOSE(VB_IMPORTANT, LOC_ERR +
    736                     QString("Mixer set playback switch %1 err %2: %3")
    737                     .arg(channel).arg(err).arg(snd_strerror(err)));
    738         }
    739         else
    740         {
    741             VERBOSE(VB_AUDIO, LOC +
    742                     QString("channel %1 playback switch set to %2")
    743                     .arg(channel).arg(unmute));
    744         }
    745     }
    746 }
    747 
    748 void AudioOutputALSA::OpenMixer(bool setstartingvolume)
    749 {
    750     int volume;
    751 
    752     mixer_control = gContext->GetSetting("MixerControl", "PCM");
    753 
    754     SetupMixer();
    755 
    756     if (mixer_handle != NULL && setstartingvolume)
    757     {
    758         volume = gContext->GetNumSetting("MasterMixerVolume", 80);
    759         SetCurrentVolume("Master", 0, volume);
    760         SetCurrentVolume("Master", 1, volume);
    761 
    762         volume = gContext->GetNumSetting("PCMMixerVolume", 80);
    763         SetCurrentVolume("PCM", 0, volume);
    764         SetCurrentVolume("PCM", 1, volume);
    765     }
    766 }
    767 
    768 void AudioOutputALSA::CloseMixer(void)
    769 {
    770     if (mixer_handle != NULL)
    771         snd_mixer_close(mixer_handle);
    772     mixer_handle = NULL;
    773 }
    774 
    775 void AudioOutputALSA::SetupMixer(void)
    776 {
    777     int err;
    778 
    779     QString alsadevice = gContext->GetSetting("MixerDevice", "default");
    780     QString device = alsadevice.remove(QString("ALSA:"));
    781 
    782     if (mixer_handle != NULL)
    783         CloseMixer();
    784 
    785     if (alsadevice.toLower() == "software")
    786         return;
    787 
    788     VERBOSE(VB_AUDIO, QString("Opening mixer %1").arg(device));
    789 
    790     // TODO: This is opening card 0. Fix for case of multiple soundcards
    791     if ((err = snd_mixer_open(&mixer_handle, 0)) < 0)
    792     {
    793         Warn(QString("Mixer device open error %1: %2")
    794              .arg(err).arg(snd_strerror(err)));
    795         mixer_handle = NULL;
    796         return;
    797     }
    798 
    799     QByteArray dev = device.toAscii();
    800     if ((err = snd_mixer_attach(mixer_handle, dev.constData())) < 0)
    801     {
    802         Warn(QString("Mixer attach error %1: %2"
    803                      "\n\t\t\tCheck Mixer Name in Setup: '%3'")
    804              .arg(err).arg(snd_strerror(err)).arg(device));
    805         CloseMixer();
    806         return;
    807     }
    808 
    809     if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0)
    810     {
    811         Warn(QString("Mixer register error %1: %2")
    812              .arg(err).arg(snd_strerror(err)));
    813         CloseMixer();
    814         return;
    815     }
    816 
    817     if ((err = snd_mixer_load(mixer_handle)) < 0)
    818     {
    819         Warn(QString("Mixer load error %1: %2")
    820              .arg(err).arg(snd_strerror(err)));
    821         CloseMixer();
    822         return;
    823     }
    824 }
    825 
    826 ALSAVolumeInfo AudioOutputALSA::GetVolumeRange(snd_mixer_elem_t *elem) const
    827 {
    828     long volume_min, volume_max;
    829 
    830     int err = snd_mixer_selem_get_playback_volume_range(
    831         elem, &volume_min, &volume_max);
    832 
    833     if (err < 0)
    834     {
    835         static bool first_time = true;
    836         if (first_time)
    837         {
    838             VERBOSE(VB_IMPORTANT,
    839                     "snd_mixer_selem_get_playback_volume_range()" + ENO);
    840             first_time = false;
    841         }
    842     }
    843 
    844     ALSAVolumeInfo vinfo(volume_min, volume_max);
    845 
    846     VERBOSE(VB_AUDIO, QString("Volume range is %1 to %2, mult=%3")
    847             .arg(vinfo.volume_min).arg(vinfo.volume_max)
    848             .arg(vinfo.range_multiplier));
    849 
    850     return vinfo;
    851 }
  • libs/libmyth/volumebase.cpp

     
    1 #include <qstring.h>
    2 #include <cstdio>
    3 #include <cstdlib>
    4 
    5 #include <algorithm>
    6 using namespace std;
    7 #include "volumebase.h"
    8 
    9 VolumeBase::VolumeBase() :
    10     internal_vol(false), volume(80),
    11     current_mute_state(kMuteOff)
    12 {
    13     swvol = swvol_setting =
    14         (gContext->GetSetting("MixerDevice", "default").toLower() == "software");
    15 }
    16 
    17 bool VolumeBase::SWVolume(void)
    18 {
    19     return swvol;
    20 }
    21 
    22 void VolumeBase::SWVolume(bool set)
    23 {
    24     if (swvol_setting)
    25         return;
    26     swvol = set;
    27 }
    28 
    29 uint VolumeBase::GetCurrentVolume(void) const
    30 {
    31     return volume;
    32 }
    33 
    34 void VolumeBase::SetCurrentVolume(int value)
    35 {
    36     volume = max(min(value, 100), 0);
    37     UpdateVolume();
    38 
    39     QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
    40     controlLabel += "MixerVolume";
    41     gContext->SaveSetting(controlLabel, volume);   
    42 }
    43 
    44 void VolumeBase::AdjustCurrentVolume(int change)
    45 {
    46     SetCurrentVolume(volume + change);
    47 }
    48 
    49 MuteState VolumeBase::SetMuteState(MuteState mstate)
    50 {
    51     current_mute_state = mstate;
    52     UpdateVolume();
    53     return current_mute_state;
    54 }
    55 
    56 void VolumeBase::ToggleMute(void)
    57 {
    58     bool is_muted = GetMuteState() == kMuteAll;
    59     SetMuteState((is_muted) ? kMuteOff : kMuteAll);
    60 }
    61 
    62 MuteState VolumeBase::GetMuteState(void) const
    63 {
    64     return current_mute_state;
    65 }
    66 
    67 MuteState VolumeBase::NextMuteState(MuteState cur)
    68 {
    69     MuteState next = cur;
    70 
    71     switch (cur)
    72     {
    73        case kMuteOff:
    74            next = kMuteLeft;
    75            break;
    76        case kMuteLeft:
    77            next = kMuteRight;
    78            break;
    79        case kMuteRight:
    80            next = kMuteAll;
    81            break;
    82        case kMuteAll:
    83            next = kMuteOff;
    84            break;
    85     }
    86 
    87     return (next);
    88 }
    89 
    90 void VolumeBase::UpdateVolume(void)
    91 {
    92     int new_volume = volume;
    93     bool save = true;
    94     if (current_mute_state == kMuteAll)
    95     {
    96         new_volume = 0;
    97         save = false;
    98     }
    99 
    100     if (swvol)
    101     {
    102         SetSWVolume(new_volume, save);
    103         return;
    104     }
    105    
    106     // TODO: Avoid assumption that there are 2 channels!
    107     for (int i = 0; i < 2; i++)
    108     {
    109         SetVolumeChannel(i, new_volume);
    110     }
    111    
    112     // Individual channel muting is handled in GetAudioData,
    113     // this code demonstrates the old method.
    114     // if (current_mute_state == kMuteLeft)
    115     // {
    116     //     SetVolumeChannel(0, 0);
    117     // }
    118     // else if (current_mute_state == kMuteRight)
    119     // {
    120     //     SetVolumeChannel(1, 0);
    121     // }
    122 }
    123 
    124 void VolumeBase::SyncVolume(void)
    125 {
    126     // Read the volume from the audio driver and setup our internal state to match
    127     if (swvol)
    128         volume = GetSWVolume();
    129     else
    130         volume = GetVolumeChannel(0);
    131 }
    132 
  • 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
     11class VolumeControlCoreAudio : public VolumeControl
     12{
     13public:
     14    static QHash<QString, QString> Enumerate();
     15
     16public:
     17    VolumeControlCoreAudio(QString device);
     18    virtual ~VolumeControlCoreAudio();
     19
     20public:
     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
     29protected:
     30    static OSStatus event(AudioDeviceID deviceId, UInt32 channel,
     31                          Boolean input, AudioDevicePropertyID property,
     32                          void* context);
     33
     34private:
     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
  • libs/libmyth/volumecontrolsoftware.h

     
     1#ifndef VOLUMECONTROLSOFTWARE
     2#define VOLUMECONTROLSOFTWARE
     3
     4#include "volumecontrol.h"
     5
     6#include <QHash>
     7#include <QAtomicInt>
     8
     9
     10class VolumeControlSoftware : public VolumeControl
     11{
     12public:
     13    static QHash<QString, QString> Enumerate();
     14
     15public:
     16    VolumeControlSoftware(QString device);
     17    virtual ~VolumeControlSoftware();
     18
     19public:
     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
     28private:
     29    static QAtomicInt m_Volume;         //< Volume state cache
     30    static QAtomicInt m_Mute;           //< Mute state cache
     31};
     32
     33#endif // VOLUMECONTROLSOFTWARE
  • 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
     9QHash<QString, QString> VolumeControlCoreAudio::Enumerate()
     10{
     11    QHash<QString, QString> result;
     12
     13    result.insert("CoreAudio:default", "Default Core Audio device");
     14
     15    UInt32 size;
     16    AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
     17                                 &size, NULL); 
     18    UInt32 count = size / sizeof(AudioDeviceID);
     19
     20    AudioDeviceID* devices = new AudioDeviceID[count];
     21    AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
     22                             &size, devices);
     23
     24    for (unsigned int index = 0; index < count; ++index)
     25    {
     26        bool output = false;
     27
     28        AudioDeviceGetPropertyInfo(devices[index], 0, 0,
     29                                   kAudioDevicePropertyStreamConfiguration,
     30                                   &size, NULL);
     31        if (!size)
     32            continue;
     33
     34        AudioBufferList* buffers = static_cast<AudioBufferList*>(malloc(size));
     35        AudioDeviceGetProperty(devices[index], 0, 0,
     36                               kAudioDevicePropertyStreamConfiguration,
     37                               &size, buffers);
     38        for (UInt32 buffer = 0; buffer < buffers->mNumberBuffers; ++buffer)
     39        {
     40            if (buffers->mBuffers[buffer].mNumberChannels)
     41            {
     42                output = true;
     43                break;
     44            }
     45        }
     46
     47        free(buffers);
     48
     49        if (!output)
     50            continue;
     51
     52        QString uid;
     53        CFStringRef uidcf;
     54        size = sizeof(CFStringRef);
     55        AudioDeviceGetProperty(devices[index], 0, 0,
     56                               kAudioDevicePropertyDeviceUID,
     57                               &size, &uidcf);
     58        if (uidcf)
     59        {
     60            char buffer[256];
     61            CFStringGetCString(uidcf, buffer, 256,
     62                               CFStringGetFastestEncoding(uidcf));
     63            uid = QString(buffer);
     64            CFRelease(uidcf);
     65        }
     66
     67        AudioDeviceGetPropertyInfo(devices[index], 0, 0,
     68                                   kAudioDevicePropertyDeviceName,
     69                                   &size, NULL);
     70        if (!size)
     71            continue;
     72
     73        char* name = static_cast<char*>(malloc(size));
     74        AudioDeviceGetProperty(devices[index], 0, 0,
     75                               kAudioDevicePropertyDeviceName,
     76                               &size, name);
     77
     78        result.insert(QString("CoreAudio:") + uid, name);
     79
     80        free(name);
     81    }
     82
     83    delete devices;
     84
     85    return result;
     86}
     87
     88VolumeControlCoreAudio::VolumeControlCoreAudio(QString device) :
     89    m_DeviceId(kAudioDeviceUnknown)
     90{
     91    if (device == QString("default"))
     92    {
     93        UInt32 size = sizeof(AudioDeviceID);
     94        AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
     95                                 &size, &m_DeviceId);       
     96    }
     97    else
     98    {
     99        CFStringRef cfString =
     100            CFStringCreateWithCharacters(kCFAllocatorDefault,
     101                reinterpret_cast<const UniChar*>(device.unicode()),
     102                device.length());
     103
     104        AudioValueTranslation translateUidToId = {
     105            mInputData:      &cfString,
     106            mInputDataSize:  sizeof(CFStringRef),
     107            mOutputData:     &m_DeviceId,
     108            mOutputDataSize: sizeof(AudioDeviceID)
     109        };
     110
     111        UInt32 translateUidToIdSize = sizeof(AudioValueTranslation);
     112        AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID,
     113                                 &translateUidToIdSize,
     114                                 &translateUidToId);
     115        CFRelease(cfString);
     116    }
     117
     118    AudioDeviceAddPropertyListener(m_DeviceId, 1, false,
     119                                   kAudioDevicePropertyVolumeScalar,
     120                                   &event,
     121                                   this);
     122
     123    AudioDeviceAddPropertyListener(m_DeviceId, 1, false,
     124                                   kAudioDevicePropertyVolumeDecibels,
     125                                   &event,
     126                                   this);
     127
     128    AudioDeviceAddPropertyListener(m_DeviceId, 0, false,
     129                                   kAudioDevicePropertyMute,
     130                                   &event,
     131                                   this);
     132
     133    m_Volume = volume();
     134    m_Mute = mute();
     135}
     136
     137VolumeControlCoreAudio::~VolumeControlCoreAudio()
     138{
     139    AudioDeviceRemovePropertyListener(m_DeviceId, 1, false,
     140                                      kAudioDevicePropertyVolumeScalar,
     141                                      &event);
     142
     143    AudioDeviceRemovePropertyListener(m_DeviceId, 1, false,
     144                                      kAudioDevicePropertyVolumeDecibels,
     145                                      &event);
     146
     147    AudioDeviceRemovePropertyListener(m_DeviceId, 0, false,
     148                                      kAudioDevicePropertyMute,
     149                                      &event);
     150}
     151
     152int VolumeControlCoreAudio::volume() const
     153{
     154    Float32 volume = 0;
     155
     156    if (!mute())
     157    {
     158        UInt32 size = sizeof(Float32);
     159        AudioDeviceGetProperty(m_DeviceId, 1, false,
     160                               kAudioDevicePropertyVolumeScalar,
     161                               &size, &volume);
     162    }
     163    else
     164        volume = static_cast<Float32>(m_Volume) / 100.0f;
     165
     166    VERBOSE(VB_AUDIO,
     167            QString("VolumeControlCoreAudio::volume() = %1")
     168            .arg(static_cast<int>(100.0f * volume)));
     169
     170    return static_cast<int>(100.0f * volume);
     171}
     172
     173void VolumeControlCoreAudio::setVolume(int volume)
     174{
     175    VERBOSE(VB_AUDIO,
     176            QString("VolumeControlCoreAudio::setVolume(%1)")
     177            .arg(volume));
     178
     179    volume = std::min(std::max(0, volume), 100);
     180
     181    if (mute() && volume > VolumeControlCoreAudio::volume())
     182        setMute(false);
     183
     184    if (!mute())
     185    {
     186        Float32 value = static_cast<Float32>(volume) / 100.0f;
     187        AudioDeviceSetProperty(m_DeviceId, NULL, 1, false,
     188                               kAudioDevicePropertyVolumeScalar,
     189                               sizeof(UInt32), &value);
     190    }
     191
     192    if (m_Volume.fetchAndStoreRelaxed(volume) != volume)
     193        emit changedVolume(volume);
     194}
     195
     196void VolumeControlCoreAudio::increaseVolume()
     197{
     198    setVolume(volume() + 10);
     199}
     200
     201void VolumeControlCoreAudio::decreaseVolume()
     202{
     203    setVolume(volume() - 10);
     204}
     205
     206bool VolumeControlCoreAudio::mute() const
     207{
     208    UInt32 mute = false;
     209
     210    UInt32 size = sizeof(UInt32);
     211    AudioDeviceGetProperty(m_DeviceId, 0, false,
     212                           kAudioDevicePropertyMute, &size, &mute);
     213
     214    VERBOSE(VB_AUDIO,
     215            QString("VolumeControlCoreAudio::mute() = %1")
     216            .arg(mute ? "mute" : "unmute"));
     217
     218    return mute;
     219}
     220
     221void VolumeControlCoreAudio::setMute(bool mute)
     222{
     223    VERBOSE(VB_AUDIO,
     224            QString("VolumeControlCoreAudio::setMute(%1)")
     225            .arg(mute ? "mute" : "unmute"));
     226
     227    if (VolumeControlCoreAudio::mute())
     228    {
     229        Float32 value = static_cast<Float32>(m_Volume) / 100.0f;
     230        AudioDeviceSetProperty(m_DeviceId, NULL, 1, false,
     231                               kAudioDevicePropertyVolumeScalar,
     232                               sizeof(UInt32), &value);   
     233    }
     234
     235    UInt32 value = mute;
     236    AudioDeviceSetProperty(m_DeviceId, NULL, 0, false,
     237                           kAudioDevicePropertyMute, sizeof(UInt32), &value);
     238
     239    if (m_Mute.fetchAndStoreRelaxed(mute) != mute)
     240        emit changedMute(mute);
     241}
     242
     243// static
     244OSStatus VolumeControlCoreAudio::event(AudioDeviceID deviceId, UInt32 channel,
     245                                       Boolean input,
     246                                       AudioDevicePropertyID property,
     247                                       void* context)
     248{
     249    VolumeControlCoreAudio* that =
     250        static_cast<VolumeControlCoreAudio*>(context);
     251
     252    if (deviceId == that->m_DeviceId && !input)
     253        switch(property)
     254        {
     255        case kAudioDevicePropertyVolumeScalar:
     256        case kAudioDevicePropertyVolumeDecibels:
     257            int volume = that->volume();
     258            if (that->m_Volume.fetchAndStoreRelaxed(volume) != volume)
     259                emit that->changedVolume(volume);
     260            break;
     261
     262        case kAudioDevicePropertyMute:
     263            bool mute = that->mute();
     264            if (that->m_Mute.fetchAndStoreRelaxed(mute) != mute)
     265                emit that->changedMute(mute);
     266            break;
     267        }
     268
     269    return noErr;
     270}
  • libs/libmyth/volumebase.h

     
    1 #ifndef VOLUMEBASE
    2 #define VOLUMEBASE
    3 
    4 #include <iostream>
    5 using namespace std;
    6 
    7 #include <qstring.h>
    8 #include "mythcontext.h"
    9 
    10 typedef enum {
    11     kMuteOff = 0,
    12     kMuteLeft,
    13     kMuteRight,
    14     kMuteAll,
    15 } MuteState;
    16 
    17 class MPUBLIC VolumeBase
    18 {
    19   public:
    20     VolumeBase();   
    21     virtual ~VolumeBase() {};
    22 
    23     void SWVolume(bool set);
    24     bool SWVolume(void);
    25     virtual uint GetCurrentVolume(void) const;
    26     virtual void SetCurrentVolume(int value);
    27     virtual void AdjustCurrentVolume(int change);
    28     virtual void ToggleMute(void);
    29 
    30     virtual MuteState GetMuteState(void) const;
    31     virtual MuteState SetMuteState(MuteState);
    32 
    33     static MuteState NextMuteState(MuteState);
    34 
    35   protected:
    36 
    37     virtual int GetVolumeChannel(int channel) const = 0; // Returns 0-100
    38     virtual void SetVolumeChannel(int channel, int volume) = 0; // range 0-100 for vol
    39     virtual void SetSWVolume(int new_volume, bool save) = 0;
    40     virtual int GetSWVolume(void) = 0;
    41 
    42     void UpdateVolume(void);
    43     void SyncVolume(void);
    44 
    45     bool internal_vol;
    46 
    47  private:
    48    
    49     int volume;
    50     MuteState current_mute_state;
    51     bool swvol;
    52     bool swvol_setting;
    53 
    54 };
    55 
    56 #endif
    57 
  • libs/libmyth/volumecontrol.h

     
     1#ifndef VOLUMECONTROL
     2#define VOLUMECONTROL
     3
     4#include <QObject>
     5#include <QString>
     6
     7class VolumeControl : public QObject
     8{
     9    Q_OBJECT
     10
     11public:
     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
     20signals:
     21    void changedVolume(int volume);
     22    void changedMute(bool mute);
     23};
     24
     25#endif // VOLUMECONTROL
  • libs/libmyth/volumecontrolsoftware.cpp

     
     1#include "volumecontrolsoftware.h"
     2
     3#include "mythcontext.h"
     4#include "mythverbose.h"
     5#include <algorithm>
     6
     7QHash<QString, QString> VolumeControlSoftware::Enumerate()
     8{
     9    QHash<QString, QString> result;
     10
     11    result.insert("Software:", "Software Volume Processing");
     12
     13    return result;
     14}
     15
     16VolumeControlSoftware::VolumeControlSoftware(QString device)
     17{
     18    int volume = gContext->GetNumSetting("SoftwareVolume", 80);
     19    m_Volume = std::min(std::max(0, volume), 100);
     20    m_Mute = gContext->GetNumSetting("SoftwareMute", false) ? true : false;
     21}
     22
     23VolumeControlSoftware::~VolumeControlSoftware()
     24{
     25
     26}
     27
     28int VolumeControlSoftware::volume() const
     29{
     30    int volume = m_Volume;
     31
     32    VERBOSE(VB_AUDIO,
     33            QString("VolumeControlSoftware::volume() = %1")
     34            .arg(volume));
     35
     36    return volume;
     37}
     38
     39void VolumeControlSoftware::setVolume(int volume)
     40{
     41    VERBOSE(VB_AUDIO,
     42            QString("VolumeControlSoftware::setVolume(%1)")
     43            .arg(volume));
     44
     45    volume = std::min(std::max(0, volume), 100);
     46
     47    if (m_Volume.fetchAndStoreRelaxed(volume) != volume)
     48    {
     49        gContext->SaveSetting("SoftwareVolume", volume);
     50        emit changedVolume(volume);
     51    }
     52}
     53
     54void VolumeControlSoftware::increaseVolume()
     55{
     56    setVolume(volume() + 1);
     57}
     58
     59void VolumeControlSoftware::decreaseVolume()
     60{
     61    setVolume(volume() - 1);
     62}
     63
     64bool VolumeControlSoftware::mute() const
     65{
     66    bool mute = m_Mute ? true : false;
     67
     68    VERBOSE(VB_AUDIO,
     69            QString("VolumeControlSoftware::mute() = %1")
     70            .arg(mute ? "mute" : "unmute"));
     71
     72    return mute;
     73}
     74
     75void VolumeControlSoftware::setMute(bool mute)
     76{
     77    VERBOSE(VB_AUDIO,
     78            QString("VolumeControlSoftware::setMute(%1)")
     79            .arg(mute ? "mute" : "unmute"));
     80
     81    if (m_Mute.fetchAndStoreRelaxed(mute) != mute)
     82    {
     83        gContext->SaveSetting("SoftwareMute", mute);
     84        emit changedMute(mute);
     85    }
     86}
     87
     88QAtomicInt VolumeControlSoftware::m_Volume;
     89QAtomicInt VolumeControlSoftware::m_Mute;
  • libs/libmyth/audiooutputpulse.h

     
    3333    AudioOutputPulseAudio(const AudioSettings &settings);
    3434   ~AudioOutputPulseAudio();
    3535
    36     int GetVolumeChannel(int channel) const;
    37     void SetVolumeChannel(int channel, int volume);
    3836    void Pause(bool paused);
    3937    void Reset(void);
    4038    void Drain(void);
  • 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
     11class VolumeControlOSS : public VolumeControl, protected QThread
     12{
     13public:
     14    static QHash<QString, QString> Enumerate();
     15
     16public:
     17    VolumeControlOSS(QString device);
     18    virtual ~VolumeControlOSS();
     19
     20public:
     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
     29protected:
     30    virtual void run();
     31
     32private:
     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
  • 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
     12class VolumeControlALSA : public VolumeControl, protected QThread
     13{
     14public:
     15    static QHash<QString, QString> Enumerate();
     16
     17public:
     18    VolumeControlALSA(QString device);
     19    virtual ~VolumeControlALSA();
     20
     21public:
     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
     30protected:
     31    virtual void run();
     32
     33    static int event(snd_mixer_elem_t* elem, unsigned int mask);
     34
     35private:
     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
  • libs/libmyth/audiooutputpulse.cpp

     
    266266    return writable;
    267267}
    268268
    269 int AudioOutputPulseAudio::GetVolumeChannel(int channel) const
    270 {
    271     return (float)volume_control.values[channel]
    272         / (float)PA_VOLUME_NORM * 100.0f;
    273 }
    274 
    275 void AudioOutputPulseAudio::SetVolumeChannel(int channel, int volume)
    276 {
    277     QString fn_log_tag = "SetVolumeChannel, ";
    278     if (channel < 0 || channel > PULSE_MAX_CHANNELS || volume < 0)
    279     {
    280         VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +
    281                 QString("bad volume params, channel %1, volume %2")
    282                 .arg(channel).arg(volume));
    283         return;
    284     }
    285     volume_control.values[channel] =
    286         (float)volume / 100.0f * (float)PA_VOLUME_NORM;
    287     volume = min(100, volume);
    288     volume = max(0, volume);
    289     uint32_t sink_index = pa_stream_get_device_index(pstream);
    290     pa_threaded_mainloop_lock(mainloop);
    291     pa_operation *op =
    292         pa_context_set_sink_volume_by_index(pcontext, sink_index,
    293                                             &volume_control,
    294                                             OpCompletionCallback, this);
    295     pa_threaded_mainloop_unlock(mainloop);
    296     if (op)
    297         pa_operation_unref(op);
    298     else
    299         VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +
    300                 QString("set sink volume operation failed, sink: %1, "
    301                         "error: %2 ")
    302                 .arg(sink_index)
    303                 .arg(pa_strerror(pa_context_errno(pcontext))));
    304 }
    305 
    306269void AudioOutputPulseAudio::Pause(bool paused)
    307270{
    308271    pa_operation *op;
     
    543506    pa_stream_set_overflow_callback(pstream, BufferFlowCallback, (char*)"over");
    544507    pa_stream_set_underflow_callback(pstream, BufferFlowCallback,
    545508                                     (char*)"under");
    546     if (set_initial_vol)
    547     {
    548         int volume = gContext->GetNumSetting("MasterMixerVolume", 80);
    549         pa_cvolume_set(&volume_control, audio_channels,
    550                        (float)volume * (float)PA_VOLUME_NORM / 100.0f);
    551     }
    552     else
    553         pa_cvolume_reset(&volume_control, audio_channels);
     509    pa_cvolume_reset(&volume_control, audio_channels);
    554510
    555511    // set myth sizes and pa buffer metrics
    556512    fragment_size = (float)sample_rate * 0.020f * // 20msec
  • libs/libmyth/volumecontrolendpoint.cpp

     
     1#include "volumecontrolendpoint.h"
     2
     3#include "mythverbose.h"
     4#include <algorithm>
     5#include <math.h>
     6
     7typedef struct _BYTE_BLOB
     8    {
     9    unsigned long clSize;
     10    byte abData[ 1 ];
     11    }   BYTE_BLOB;
     12
     13typedef struct _tagpropertykey
     14    {
     15    GUID fmtid;
     16    DWORD pid;
     17    }   PROPERTYKEY;
     18
     19#define REFPROPVARIANT const PROPVARIANT &
     20
     21inline void PropVariantInit ( PROPVARIANT * pvar )
     22{
     23    memset ( pvar, 0, sizeof(PROPVARIANT) );
     24}
     25WINOLEAPI PropVariantClear ( PROPVARIANT * pvar );
     26
     27EXTERN_C const CLSID CLSID_MMDeviceEnumerator = {0xBCDE0395,0xE52F,0x467C,{0x8E,0x3D,0xC4,0x57,0x92,0x91,0x69,0x2E}};
     28EXTERN_C const IID IID_IMMDeviceEnumerator = {0xA95664D2,0x9614,0x4F35,{0xA7,0x46,0xDE,0x8D,0xB6,0x36,0x17,0xE6}};
     29EXTERN_C const IID IID_IAudioEndpointVolume = {0x5CDF2C82,0x841E,0x4546,{0x97,0x22,0x0C,0xF7,0x40,0x78,0x22,0x9A}};
     30EXTERN_C const IID IID_IAudioEndpointVolumeCallback = {0x657804FA,0xD6AD,0x4496,{0x8A,0x60,0x35,0x27,0x52,0xAF,0x4F,0x89}};
     31EXTERN_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
     38QHash<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
     135VolumeControlEndpoint::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
     192VolumeControlEndpoint::~VolumeControlEndpoint()
     193{
     194    if (m_EndpointVolume)
     195    {
     196        m_EndpointVolume->UnregisterControlChangeNotify(this);
     197        m_EndpointVolume->Release();
     198    }
     199
     200    CoUninitialize();
     201}
     202
     203int 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
     226void 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
     246void 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
     255void 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
     264bool 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
     278void 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
     297ULONG STDMETHODCALLTYPE VolumeControlEndpoint::AddRef()
     298{
     299    return 1;
     300}
     301
     302ULONG STDMETHODCALLTYPE VolumeControlEndpoint::Release()
     303{
     304    return 0;
     305}
     306
     307HRESULT STDMETHODCALLTYPE
     308VolumeControlEndpoint::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
     328HRESULT STDMETHODCALLTYPE
     329VolumeControlEndpoint::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}
  • libs/libmyth/audiooutputjack.h

     
    1111    AudioOutputJACK(const AudioSettings &settings);
    1212    virtual ~AudioOutputJACK();
    1313   
    14     // Volume control
    15     virtual int GetVolumeChannel(int channel) const; // Returns 0-100
    16     virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol
    17  
    1814  protected:
    1915
    2016    // You need to implement the following functions
     
    2723
    2824  private:
    2925
    30     void VolumeInit(void);
    31 
    3226    int audioid;
    3327
    3428};
  • libs/libmyth/audiosettings.cpp

     
    1515    channels(-1),
    1616    codec(0),
    1717    samplerate(-1),
    18     set_initial_vol(false),
    1918    use_passthru(false),
    2019    source(AUDIOOUTPUT_UNKNOWN),
    2120    upmixer(0)
     
    2928    channels(other.channels),
    3029    codec(other.codec),
    3130    samplerate(other.samplerate),
    32     set_initial_vol(other.set_initial_vol),
    3331    use_passthru(other.use_passthru),
    3432    source(other.source),
    3533    upmixer(other.upmixer)
     
    4442    int audio_codec,
    4543    int audio_samplerate,
    4644    AudioOutputSource audio_source,
    47     bool audio_set_initial_vol,
    4845    bool audio_use_passthru,
    4946    int upmixer_startup) :
    5047    main_device(audio_main_device),
     
    5350    channels(audio_channels),
    5451    codec(audio_codec),
    5552    samplerate(audio_samplerate),
    56     set_initial_vol(audio_set_initial_vol),
    5753    use_passthru(audio_use_passthru),
    5854    source(audio_source),
    5955    upmixer(upmixer_startup)
     
    7369    channels(audio_channels),
    7470    codec(audio_codec),
    7571    samplerate(audio_samplerate),
    76     set_initial_vol(false),
    7772    use_passthru(audio_use_passthru),
    7873    source(AUDIOOUTPUT_UNKNOWN),
    7974    upmixer(upmixer_startup)
  • libs/libmyth/audiooutputca.cpp

     
    244244        return false;
    245245    }
    246246
    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 
    254247    return true;
    255248}
    256249
     
    399392    return noErr;
    400393}
    401394
    402 int AudioOutputCA::GetVolumeChannel(int channel) const
    403 {
    404     // FIXME: this only returns global volume
    405     (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 case
    414 }
    415 
    416 void AudioOutputCA::SetVolumeChannel(int channel, int volume)
    417 {
    418     // FIXME: this only sets global volume
    419     (void)channel;
    420      AudioUnitSetParameter(d->mOutputUnit, kHALOutputParam_Volume,
    421                            kAudioUnitScope_Global, 0, (volume * 0.01), 0);
    422 }
    423 
    424395// IOProc style callback for SPDIF audio output
    425396static OSStatus RenderCallbackSPDIF(AudioDeviceID        inDevice,
    426397                                    const AudioTimeStamp *inNow,
  • libs/libmyth/audiooutputwin.h

     
    1313    AudioOutputWin(const AudioSettings &settings);
    1414    virtual ~AudioOutputWin();
    1515
    16     // Volume control
    17     virtual int  GetVolumeChannel(int channel) const;
    18     virtual void SetVolumeChannel(int channel, int volume);
    19 
    2016  protected:
    2117    virtual bool OpenDevice(void);
    2218    virtual void CloseDevice(void);
  • libs/libmyth/audiooutputjack.cpp

     
    148148    audio_buffer_unused = JACK_GetBytesFreeSpace(audioid);
    149149    JACK_SetPosition(audioid, BYTES, 0);
    150150
    151     // Setup volume control
    152     if (internal_vol)
    153         VolumeInit();
    154 
    155151    // Device opened successfully
    156152    return true;
    157153}
     
    206202
    207203    return space;
    208204}
    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) const
    220 {
    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

     
    1212    AudioOutputOSS(const AudioSettings &settings);
    1313    virtual ~AudioOutputOSS();
    1414
    15     // Volume control
    16     virtual int GetVolumeChannel(int channel) const;
    17     virtual void SetVolumeChannel(int channel, int volume);
    18 
    1915  protected:
    2016    // You need to implement the following functions
    2117    virtual bool OpenDevice(void);
     
    2622    vector<int> GetSupportedRates(void);
    2723
    2824  private:
    29     void VolumeInit(void);
    30     void VolumeCleanup(void);
    31    
    3225    void SetFragSize(void);
    3326   
    3427    int audiofd;
    3528    mutable int numbadioctls;
    36 
    37     // Volume related
    38     int mixerfd;
    39     int control;
    4029};
    4130
    4231#endif
  • libs/libmyth/audiooutputbase.cpp

     
    3838    pauseaudio(false),          audio_actually_paused(false),
    3939    was_paused(false),
    4040
    41     set_initial_vol(settings.set_initial_vol),
    4241    buffer_output_data_for_use(false),
    4342
    4443    // private
     
    5554    needs_upmix(false),
    5655    surround_mode(FreeSurround::SurroundModePassive),
    5756    old_audio_stretchfactor(1.0),
    58     volume(80),
    5957
    6058    blocking(false),
    6159
     
    110108
    111109    allow_ac3_passthru = (orig_config_channels > 2) ? gContext->GetNumSetting("AC3PassThru", false) : false;
    112110
     111    if (gContext->GetSetting("MixerDevice") == "Software:")
     112        volume_control = VolumeControlManager::GetControl("Software:");
     113   
    113114    // You need to call Reconfigure from your concrete class.
    114115    // Reconfigure(laudio_bits,       laudio_channels,
    115116    //             laudio_samplerate, laudio_passthru);
     
    279280    killaudio = false;
    280281    pauseaudio = false;
    281282    was_paused = true;
    282     internal_vol = gContext->GetNumSetting("MythControlsVolume", 0);
    283283
    284284    numlowbuffer = 0;
    285285   
     
    359359        return;
    360360    }
    361361
    362     // Only used for software volume
    363     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 
    374362    VERBOSE(VB_AUDIO, LOC + QString("Audio fragment size: %1")
    375363            .arg(fragment_size));
    376364
     
    669657     return audbuf_timecode - GetAudiotime();
    670658}
    671659
    672 void AudioOutputBase::SetSWVolume(int new_volume, bool save)
    673 {
    674     volume = new_volume;
    675     if (save)
    676     {
    677         QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
    678         controlLabel += "MixerVolume";
    679         gContext->SaveSetting(controlLabel, volume);
    680     }
    681 }
    682 
    683 int AudioOutputBase::GetSWVolume()
    684 {
    685     return volume;
    686 }
    687 
    688660void AudioOutputBase::AdjustVolume(void *buffer, int len, bool music)
    689661{
    690662    if (audio_bits == 8)
     
    696668template <class AudioDataType>
    697669void AudioOutputBase::_AdjustVolume(AudioDataType *buffer, int len, bool music)
    698670{
     671    int volume = volume_control->mute() ? 0 : volume_control->volume();
     672 
    699673    float g = volume / 100.0;
    700674
    701675    // Should probably be exponential - this'll do
     
    11041078        }
    11051079    }
    11061080
    1107     if (internal_vol && SWVolume())
     1081    if (volume_control)
    11081082    {
    11091083        int bdiff = kAudioRingBufferSize - waud;
    11101084        bool music = (timecode < 1);
     
    13651339    audio_buflock.unlock();
    13661340
    13671341    // Mute individual channels through mono->stereo duplication
    1368     MuteState mute_state = GetMuteState();
     1342//    MuteState mute_state = GetMuteState();
    13691343    if (written_size &&
    1370         audio_channels > 1 &&
    1371         (mute_state == kMuteLeft || mute_state == kMuteRight))
     1344        audio_channels > 1 //&&
     1345//        (mute_state == kMuteLeft || mute_state == kMuteRight)
     1346       )
    13721347    {
    13731348        int offset_src = 0;
    13741349        int offset_dst = 0;
    13751350 
    1376         if (mute_state == kMuteLeft)
    1377             offset_src = audio_bits / 8;    // copy channel 1 to channel 0
    1378         else if (mute_state == kMuteRight)
    1379             offset_dst = audio_bits / 8;    // copy channel 0 to channel 1
     1351//        if (mute_state == kMuteLeft)
     1352//            offset_src = audio_bits / 8;    // copy channel 1 to channel 0
     1353//        else if (mute_state == kMuteRight)
     1354//            offset_dst = audio_bits / 8;    // copy channel 0 to channel 1
    13801355     
    13811356        for (int i = 0; i < written_size; i += audio_bytes_per_sample)
    13821357        {
  • libs/libmyth/audiooutput.cpp

     
    3434    int audio_bits, int audio_channels,
    3535    int audio_codec, int audio_samplerate,
    3636    AudioOutputSource source,
    37     bool set_initial_vol, bool audio_passthru,
     37    bool audio_passthru,
    3838    int upmixer_startup)
    3939{
    4040    AudioSettings settings(
    4141        main_device, passthru_device, audio_bits,
    4242        audio_channels, audio_codec, audio_samplerate, source,
    43         set_initial_vol, audio_passthru, upmixer_startup);
     43        audio_passthru, upmixer_startup);
    4444
    4545    settings.FixPassThrough();
    4646
  • libs/libmyth/libmyth.pro

     
    2323HEADERS += output.h
    2424HEADERS += settings.h
    2525HEADERS += uilistbtntype.h uitypes.h util.h mythuifilebrowser.h
    26 HEADERS += volumebase.h visual.h xmlparse.h
     26HEADERS += volumecontrol.h volumecontrolmanager.h volumecontrolsoftware.h
     27HEADERS += visual.h xmlparse.h
    2728HEADERS += mythhdd.h mythcdrom.h storagegroup.h dbutil.h
    2829HEADERS += mythcommandlineparser.h mythterminal.h
    2930HEADERS += mythhttppool.h mythhttphandler.h
     
    4546SOURCES += output.cpp
    4647SOURCES += settings.cpp
    4748SOURCES += uilistbtntype.cpp uitypes.cpp util.cpp mythuifilebrowser.cpp
    48 SOURCES += volumebase.cpp xmlparse.cpp
     49SOURCES += volumecontrolmanager.cpp volumecontrolsoftware.cpp
     50SOURCES += xmlparse.cpp
    4951SOURCES += mythhdd.cpp mythcdrom.cpp storagegroup.cpp dbutil.cpp
    5052SOURCES += mythcommandlineparser.cpp mythterminal.cpp
    5153SOURCES += mythhttppool.cpp mythhttphandler.cpp
     
    8385# Install headers so that plugins can compile independently
    8486inc.path = $${PREFIX}/include/mythtv/
    8587inc.files  = dialogbox.h mythcontext.h
    86 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h
     88inc.files += mythwidgets.h remotefile.h oldsettings.h
    8789inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h
    8890inc.files += audiooutput.h audiosettings.h util.h
    8991inc.files += inetcomms.h mythmedia.h mythwizard.h schemawizard.h dbutil.h
    9092inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h
    91 inc.files += visual.h volumebase.h output.h langsettings.h
     93inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h
    9294inc.files += mythexp.h mythpluginapi.h storagegroup.h
    9395inc.files += mythconfigdialogs.h mythconfiggroups.h
    9496inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h
     
    103105
    104106using_oss {
    105107    DEFINES += USING_OSS
    106     SOURCES += audiooutputoss.cpp
    107     HEADERS += audiooutputoss.h
     108    SOURCES += audiooutputoss.cpp volumecontroloss.cpp
     109    HEADERS += audiooutputoss.h volumecontroloss.h
    108110    LIBS += $$OSS_LIBS
    109111}
    110112
     
    132134
    133135mingw {
    134136    DEFINES += USING_MINGW
    135     SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp
    136     HEADERS += mediamonitor-windows.h   audiooutputwin.h   audiooutputdx.h
    137     LIBS += -lpthread -lwinmm -lws2_32
     137    SOURCES += mediamonitor-windows.cpp
     138    HEADERS += mediamonitor-windows.h
     139    SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp
     140    HEADERS += audiooutputwin.h   audiooutputdx.h   volumecontrolendpoint.h
     141    LIBS += -lpthread -lwinmm -lws2_32 -lole32
    138142}
    139143
    140144macx {
    141     HEADERS += audiooutputca.h
    142     SOURCES += audiooutputca.cpp
     145    DEFINES += USE_COREAUDIO
     146    HEADERS += audiooutputca.h volumecontrolcoreaudio.h
     147    SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp
    143148    HEADERS += mythcdrom-darwin.h
    144149    SOURCES += mythcdrom-darwin.cpp
    145150
     
    179184
    180185using_alsa {
    181186    DEFINES += USE_ALSA
    182     HEADERS += audiooutputalsa.h
    183     SOURCES += audiooutputalsa.cpp
     187    HEADERS += audiooutputalsa.h volumecontrolalsa.h
     188    SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp
    184189    LIBS += $$ALSA_LIBS
    185190}
    186191
  • libs/libmyth/audiosettings.h

     
    3232        int               audio_codec,
    3333        int               audio_samplerate,
    3434        AudioOutputSource audio_source,
    35         bool              audio_set_initial_vol,
    3635        bool              audio_use_passthru,
    3736        int               upmixer_startup = 0);
    3837
     
    5857    int     channels;
    5958    int     codec;
    6059    int     samplerate;
    61     bool    set_initial_vol;
    6260    bool    use_passthru;
    6361    AudioOutputSource source;
    6462    int     upmixer;
  • libs/libmyth/audiooutputca.h

     
    2525    bool RenderAudio(unsigned char *aubuf, int size,
    2626                     unsigned long long timestamp);
    2727
    28     // Volume control
    29     virtual int  GetVolumeChannel(int channel) const;
    30     virtual void SetVolumeChannel(int channel, int volume);
    31 
    3228    void Debug(QString msg)
    3329    {   VERBOSE(VB_AUDIO,     "AudioOutputCA::" + msg);   }
    3430
     
    3733
    3834    void Warn(QString msg)
    3935    {   VERBOSE(VB_IMPORTANT, "AudioOutputCA Warning: " + msg);   }
     36    bool internal_vol;
    4037
    4138protected:
    4239
  • libs/libmyth/audiooutputoss.cpp

     
    3030
    3131AudioOutputOSS::AudioOutputOSS(const AudioSettings &settings) :
    3232    AudioOutputBase(settings),
    33     audiofd(-1), numbadioctls(0),
    34     mixerfd(-1), control(SOUND_MIXER_VOLUME)
     33    audiofd(-1), numbadioctls(0)
    3534{
    3635    // Set everything up
    3736    Reconfigure(settings);
     
    194193                " the error was: %1").arg(strerror(errno)));
    195194    }
    196195
    197     // Setup volume control
    198     if (internal_vol)
    199         VolumeInit();
    200 
    201196    // Device opened successfully
    202197    return true;
    203198}
     
    242237        close(audiofd);
    243238
    244239    audiofd = -1;
    245    
    246     VolumeCleanup();
    247240}
    248241
    249242
     
    310303
    311304    return space;
    312305}
    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     else
    333     {
    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) const
    377 {
    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; // left
    394     } else if (channel == 1) {
    395         volume = (tmpVol >> 8) & 0xff; // right
    396     } 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         else
    423             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/audiooutputdx.cpp

     
    337337    dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
    338338                    | DSBCAPS_GLOBALFOCUS       /* Allows background playing */
    339339                    | DSBCAPS_LOCHARDWARE;      /* Needed for 5.1 on emu101k */
    340     if (!m_UseSPDIF)
    341         dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME;  /* Allow volume control */
    342340    dsbdesc.dwBufferBytes = soundcard_buffer_size;   /* buffer size */
    343341    dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf;
    344342
     
    485483    return buffered;
    486484}
    487485
    488 int AudioOutputDX::GetVolumeChannel(int channel) const
    489 {
    490     HRESULT dsresult;
    491     long dxVolume = 0;
    492     int volume;
    493 
    494     if (m_UseSPDIF)
    495         return 100;
    496 
    497     dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);
    498     volume = (int)(pow(10,(float)dxVolume/20)*100);
    499 
    500     if (dsresult != DS_OK)
    501     {
    502         VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Failed to get volume %1")
    503                                                 .arg(dxVolume));
    504         return volume;
    505     }
    506 
    507     VERBOSE(VB_AUDIO, LOC + QString("Got volume %1").arg(volume));
    508     return volume;
    509 }
    510 
    511 void AudioOutputDX::SetVolumeChannel(int channel, int volume)
    512 {
    513     HRESULT dsresult;
    514     float dbAtten = 20 * log10((float)volume/100);
    515     long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);
    516 
    517     if (m_UseSPDIF)
    518         return;
    519 
    520     // dxVolume is attenuation in 100ths of a decibel
    521     dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);
    522 
    523     if (dsresult != DS_OK)
    524     {
    525         VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Failed to set volume %1")
    526                                                 .arg(dxVolume));
    527         return;
    528     }
    529    
    530     VERBOSE(VB_AUDIO, LOC + QString("Set volume %1").arg(dxVolume));
    531 }
    532 
    533486/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmyth/audiooutputnull.h

     
    2727
    2828    virtual void Reset(void);
    2929
    30 
    31     // Volume control
    32     virtual int GetVolumeChannel(int /* channel */) const { return 100; }
    33     virtual void SetVolumeChannel(int /* channel */, int /* volume */){return;}
    34 
    3530    virtual int readOutputData(unsigned char *read_buffer, int max_length);
    3631
    3732  protected:
  • libs/libmyth/audiooutput.h

     
    55
    66#include "audiosettings.h"
    77#include "mythcontext.h"
    8 #include "volumebase.h"
    98#include "output.h"
    109
    11 class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
     10class MPUBLIC AudioOutput : public OutputListeners
    1211{
    1312 public:
    1413    // opens one of the concrete subclasses
     
    1817        int audio_bits, int audio_channels,
    1918        int audio_codec, int audio_samplerate,
    2019        AudioOutputSource source,
    21         bool set_initial_vol, bool audio_passthru,
     20        bool audio_passthru,
    2221        int upmixer_startup = 0);
    2322
    2423    AudioOutput() :
    25         VolumeBase(),             OutputListeners(),
     24        OutputListeners(),
    2625        lastError(QString::null), lastWarn(QString::null) {}
    2726
    2827    virtual ~AudioOutput() { };
  • 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
     12class MPUBLIC VolumeControlManager
     13{
     14public:
     15    static QHash<QString, QString> Enumerate();
     16    static QSharedPointer<VolumeControl> GetControl(QString device);
     17};
     18
     19#endif // VOLUMECONTROLMANAGER
  • 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
     13class VolumeControlEndpoint : public VolumeControl,
     14                              protected IAudioEndpointVolumeCallback
     15{
     16public:
     17    static QHash<QString, QString> Enumerate();
     18
     19public:
     20    VolumeControlEndpoint(QString device);
     21    virtual ~VolumeControlEndpoint();
     22
     23public:
     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
     32protected:
     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
     38private:
     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
  • libs/libmyth/audiooutputdx.h

     
    1313    AudioOutputDX(const AudioSettings &settings);
    1414    virtual ~AudioOutputDX();
    1515
    16     virtual int GetVolumeChannel(int channel) const;
    17     virtual void SetVolumeChannel(int channel, int volume);
    18 
    1916  protected:
    2017    virtual bool OpenDevice(void);
    2118    virtual void CloseDevice(void);
  • libs/libmyth/audiooutputalsa.h

     
    99
    1010using namespace std;
    1111
    12 class ALSAVolumeInfo
    13 {
    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 
    5012class AudioOutputALSA : public AudioOutputBase
    5113{
    5214  public:
    5315    AudioOutputALSA(const AudioSettings &settings);
    5416    virtual ~AudioOutputALSA();
    5517
    56     // Volume control
    57     virtual int GetVolumeChannel(int channel) const; // Returns 0-100
    58     virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol
    59 
    60    
    6118  protected:
    6219    // You need to implement the following functions
    6320    virtual bool OpenDevice(void);
     
    7734    void ReorderSmpteToAlsa6ch(void *buf, int frames);
    7835    template <class AudioDataType>
    7936        void _ReorderSmpteToAlsa6ch(AudioDataType *buf, int frames);
    80     // Volume related
    81     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;
    8637
    8738  private:
    8839    snd_pcm_t   *pcm_handle;
    8940    int          numbadioctls;
    9041    QMutex       killAudioLock;
    91     snd_mixer_t *mixer_handle;
    92     QString      mixer_control; // e.g. "PCM"
    9342    snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*,
    9443                                        snd_pcm_uframes_t);
    9544};
  • 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
     19static const unsigned long poll = 250;   //< OSS control poll interval (ms)
     20
     21QHash<QString, QString> VolumeControlOSS::Enumerate()
     22{
     23    QHash<QString, QString> result;
     24#if 1
     25    int mixerfd = open("/dev/mixer", O_RDWR, 0);
     26
     27    if (mixerfd == -1)
     28    {
     29        VERBOSE(VB_IMPORTANT,
     30                QString("VolumeControlOSS::Enumerate() - ERROR: "
     31                        "opening \"/dev/mixer\""));
     32        return result;
     33    }
     34
     35    oss_sysinfo sysinfo;
     36    if (ioctl(mixerfd, SNDCTL_SYSINFO, &sysinfo) == -1)
     37    {
     38        VERBOSE(VB_IMPORTANT,
     39                QString("VolumeControlOSS::Enumerate() - ERROR: "
     40                        "obtaining system information"));
     41        return result;
     42    }
     43
     44    for (int mixer = 0; mixer < sysinfo.nummixers; ++mixer)
     45    {
     46        oss_mixerinfo info = {
     47            dev: mixer
     48        };
     49
     50        if (ioctl(mixerfd, SNDCTL_MIXERINFO, &info) != -1)
     51            result.insert(QString("OSS:%1").arg(info.devnode), info.name);
     52    }
     53
     54    close(mixerfd);
     55
     56#else
     57    QDir devs("/dev", "mixer*", QDir::Name, QDir::System);
     58
     59    QFileInfoList files = devs.entryInfoList();
     60    QFileInfoList::Iterator file;
     61    for (file = files.begin(); file != files.end(); ++file)
     62    {
     63        result.insert("OSS:" + file->absoluteFilePath(),
     64                      file->absoluteFilePath());
     65    }
     66
     67    devs.setPath("/dev/sound");
     68    files = devs.entryInfoList();
     69    for (file = files.begin(); file != files.end(); ++file)
     70    {
     71        result.insert("OSS:" + file->absoluteFilePath(),
     72                      file->absoluteFilePath());
     73    }
     74#endif
     75    return result;
     76}
     77
     78VolumeControlOSS::VolumeControlOSS(QString device) :
     79   m_VolumeCtrl(-1), m_MuteCtrl(-1), m_Exit(false)
     80{
     81    m_Mixer = open(device.toAscii().constData(), O_RDWR, 0);
     82
     83    if (m_Mixer == -1)
     84    {
     85        VERBOSE(VB_IMPORTANT,
     86                QString("VolumeControlOSS::VolumeControlOSS() - ERROR: "
     87                        "opening \"%1\"").arg(device));
     88        return;
     89    }
     90
     91    oss_sysinfo sysinfo;
     92    if (ioctl(m_Mixer, SNDCTL_SYSINFO, &sysinfo) == -1)
     93    {
     94        VERBOSE(VB_IMPORTANT,
     95                QString("VolumeControlOSS::VolumeControlOSS() - ERROR: "
     96                        "obtaining system information"));
     97        return;
     98    }
     99
     100    for (m_MixerDev = 0; m_MixerDev < sysinfo.nummixers; ++m_MixerDev)
     101    {
     102        oss_mixerinfo info = {
     103            dev: m_MixerDev
     104        };
     105
     106        if (ioctl(m_Mixer, SNDCTL_MIXERINFO, &info) != -1)
     107            if (QString(info.devnode) == device)
     108                break;
     109    }
     110
     111    int extensions = m_MixerDev;
     112    if (ioctl(m_Mixer, SNDCTL_MIX_NREXT, &extensions) == -1)
     113    {
     114        VERBOSE(VB_IMPORTANT,
     115                QString("VolumeControlOSS::VolumeControlOSS() - ERROR: "
     116                        "obtaining number of extensions"));
     117        return;
     118    }
     119
     120    for (int control = 0; control < extensions; ++control)
     121    {
     122        oss_mixext info = {
     123            dev:  m_MixerDev,
     124            ctrl: control
     125        };
     126
     127        if (ioctl(m_Mixer, SNDCTL_MIX_EXTINFO, &info) == -1)
     128            continue;
     129
     130        switch (info.type)
     131        {
     132        case MIXT_MONODB:
     133        case MIXT_MONOSLIDER:
     134        case MIXT_MONOSLIDER16:
     135        case MIXT_SLIDER:
     136        case MIXT_STEREOSLIDER:
     137        case MIXT_STEREOSLIDER16:
     138            if (m_VolumeCtrl == -1)
     139            {
     140                m_VolumeCtrl = info.ctrl;
     141                m_VolumeMax = info.maxvalue;
     142                m_VolumeType = info.type;
     143                m_VolumeTimestamp = info.timestamp;
     144            }
     145            break;
     146
     147        case MIXT_ONOFF:
     148        case MIXT_MUTE:
     149            if (m_MuteCtrl == -1)
     150            {
     151                m_MuteCtrl = info.ctrl;
     152                m_MuteTimestamp = info.timestamp;
     153            }
     154            break;
     155        }
     156
     157        if (m_VolumeCtrl != -1 && m_MuteCtrl != -1)
     158            break;
     159    }
     160
     161    m_Range = std::min(std::max(1, m_VolumeMax), 100);
     162
     163    if (m_VolumeCtrl != -1)
     164        start();
     165}
     166
     167VolumeControlOSS::~VolumeControlOSS()
     168{
     169    m_Exit = true;
     170
     171    if (isRunning())
     172        wait();
     173
     174    if (m_Mixer != -1)
     175        close(m_Mixer);
     176}
     177
     178int VolumeControlOSS::volume() const
     179{
     180    int volume = 0;
     181
     182    if (m_VolumeCtrl != -1)
     183    {
     184        if (m_MuteCtrl != -1 || !mute())
     185        {
     186            oss_mixer_value value;
     187            memset(&value, 0, sizeof(value));
     188
     189            value.dev = m_MixerDev;
     190            value.ctrl = m_VolumeCtrl;
     191            value.timestamp = m_VolumeTimestamp;
     192
     193            if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1)
     194            {
     195                switch (m_VolumeType)
     196                {
     197                case MIXT_MONODB:
     198                case MIXT_MONOSLIDER:
     199                    volume = value.value & 0xFF;
     200                    break;
     201
     202                case MIXT_MONOSLIDER16:
     203                    volume = value.value & 0xFFFF;
     204                    break;
     205
     206                case MIXT_SLIDER:
     207                    volume = value.value & 0x7FFFFFFF;
     208                    break;
     209
     210                case MIXT_STEREOSLIDER:
     211                    volume = std::max(value.value & 0xFF,
     212                                      (value.value >> 8) & 0xFF);
     213                    break;
     214
     215                case MIXT_STEREOSLIDER16:
     216                    volume = std::max(value.value & 0xFFFF,
     217                                      (value.value >> 16) & 0xFFFF);
     218                    break;
     219                }
     220
     221                volume = ((200 * volume) + m_VolumeMax) / (2 * m_VolumeMax);
     222            }
     223        }
     224        else
     225            volume = m_Volume;
     226    }
     227
     228    VERBOSE(VB_AUDIO,
     229            QString("VolumeControlOSS::volume() = %1")
     230            .arg(volume));
     231
     232    return volume;
     233}
     234
     235void VolumeControlOSS::setVolume(int volume)
     236{
     237    VERBOSE(VB_AUDIO,
     238            QString("VolumeControlOSS::setVolume(%1)")
     239            .arg(volume));
     240
     241    volume = std::min(std::max(0, volume), 100);
     242
     243    if (mute() && volume > VolumeControlOSS::volume())
     244        setMute(false);
     245
     246    if (m_VolumeCtrl != -1 && (m_MuteCtrl != -1 || !mute()))
     247    {
     248        oss_mixer_value value;
     249        memset(&value, 0, sizeof(value));
     250
     251        value.dev = m_MixerDev;
     252        value.ctrl = m_VolumeCtrl;
     253        value.timestamp = m_VolumeTimestamp;
     254        value.value = (m_VolumeMax * volume) / 100;
     255
     256        switch (m_VolumeType)
     257        {
     258        case MIXT_STEREOSLIDER:
     259            value.value = value.value | (value.value << 8);
     260            break;
     261
     262        case MIXT_STEREOSLIDER16:
     263            value.value = value.value | (value.value << 16);
     264            break;
     265        }
     266
     267        ioctl(m_Mixer, SNDCTL_MIX_WRITE, &value);
     268    }
     269
     270    if (m_Volume.fetchAndStoreRelaxed(volume) != volume)
     271        emit changedVolume(volume);
     272}
     273
     274void VolumeControlOSS::increaseVolume()
     275{
     276    setVolume((volume() * m_Range + 100) / m_Range);
     277}
     278
     279void VolumeControlOSS::decreaseVolume()
     280{
     281    setVolume((volume() * m_Range - 100) / m_Range);
     282}
     283
     284bool VolumeControlOSS::mute() const
     285{
     286    bool mute = false;
     287
     288    if (m_VolumeCtrl != -1)
     289    {
     290        oss_mixer_value value;
     291        memset(&value, 0, sizeof(value));
     292
     293        value.dev = m_MixerDev;
     294
     295        if (m_MuteCtrl != -1)
     296        {
     297            value.ctrl = m_MuteCtrl;
     298            value.timestamp = m_MuteTimestamp;
     299
     300            if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1)
     301                mute = value.value;
     302        }
     303        else
     304        {
     305            value.ctrl = m_VolumeCtrl;
     306            value.timestamp = m_VolumeTimestamp;
     307
     308            if (ioctl(m_Mixer, SNDCTL_MIX_READ, &value) != -1)
     309                mute = !value.value;
     310        }
     311    }
     312
     313    VERBOSE(VB_AUDIO,
     314            QString("VolumeControlOSS::mute() = %1")
     315            .arg(mute ? "mute" : "unmute"));
     316
     317    return mute;
     318}
     319
     320void VolumeControlOSS::setMute(bool mute)
     321{
     322    VERBOSE(VB_AUDIO,
     323            QString("VolumeControlOSS::setMute(%1)")
     324            .arg(mute ? "mute" : "unmute"));
     325
     326    if (m_VolumeCtrl != -1)
     327    {
     328        oss_mixer_value value;
     329        memset(&value, 0, sizeof(value));
     330
     331        value.dev = m_MixerDev;
     332
     333        if (m_MuteCtrl != -1)
     334        {
     335            value.ctrl = m_MuteCtrl;
     336            value.timestamp = m_MuteTimestamp;
     337            value.value = mute;
     338        }
     339        else
     340        {
     341            value.ctrl = m_VolumeCtrl;
     342            value.timestamp = m_VolumeTimestamp;
     343            value.value = mute ? 0 : (m_VolumeMax * m_Volume) / 100;
     344
     345            switch (m_VolumeType)
     346            {
     347            case MIXT_STEREOSLIDER:
     348                value.value = value.value | (value.value << 8);
     349                break;
     350
     351            case MIXT_STEREOSLIDER16:
     352                value.value = value.value | (value.value << 16);
     353                break;
     354            }
     355        }
     356
     357        ioctl(m_Mixer, SNDCTL_MIX_WRITE, &value);
     358    }
     359
     360    if (m_Mute.fetchAndStoreRelaxed(mute) != mute)
     361        emit changedMute(mute);
     362}
     363
     364void VolumeControlOSS::run()
     365{
     366    VERBOSE(VB_AUDIO,
     367            QString("VolumeControlOSS::run() - begin"));
     368
     369    m_Volume = volume();
     370    m_Mute = mute();
     371
     372    while(!m_Exit)
     373    {
     374        msleep(poll);
     375
     376        int pollvolume = volume();
     377        if (m_Volume.fetchAndStoreRelaxed(pollvolume) != pollvolume)
     378            emit changedVolume(pollvolume);
     379
     380        bool pollmute = mute();
     381        if (m_Mute.fetchAndStoreRelaxed(pollmute) != pollmute)
     382            emit changedMute(pollmute);
     383    }
     384
     385    VERBOSE(VB_AUDIO,
     386            QString("VolumeControlOSS::run() - end"));
     387}
     388
  • programs/mythfrontend/globalsettings.cpp

     
    2828#include "libmythtv/mpeg/iso639.h"
    2929#include "playbackbox.h"
    3030#include "globalsettings.h"
     31#include "libmyth/volumecontrolmanager.h"
    3132#include "libmythtv/recordingprofile.h"
    3233#include "mythxdisplay.h"
    3334#include "DisplayRes.h"
     
    179180    return gc;
    180181}
    181182
    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 
    194183static HostComboBox *MixerDevice()
    195184{
    196185    HostComboBox *gc = new HostComboBox("MixerDevice", true);
    197186    gc->setLabel(QObject::tr("Mixer Device"));
     187    gc->addSelection(QObject::tr("Disabled"), QString());
    198188
    199 #ifdef USING_OSS
    200     QDir dev("/dev", "mixer*", QDir::Name, QDir::System);
    201     gc->fillSelectionsFromDir(dev);
     189    QHash<QString, QString> controls = VolumeControlManager::Enumerate();
    202190
    203     dev.setPath("/dev/sound");
    204     if (dev.exists())
     191    for (QHash<QString, QString>::const_iterator control = controls.begin();
     192         control != controls.end(); ++control)
    205193    {
    206         gc->fillSelectionsFromDir(dev);
     194        gc->addSelection(control.value(), control.key());
    207195    }
    208 #endif
    209 #ifdef USING_ALSA
    210     gc->addSelection("ALSA:default", "ALSA:default");
    211 #endif
    212 #ifdef USING_MINGW
    213     gc->addSelection("DirectX:", "DirectX:");
    214     gc->addSelection("Windows:", "Windows:");
    215 #endif
    216 #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 #endif
    221196
    222197    return gc;
    223198}
    224199
    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 
    264200static HostCheckBox *IndividualMuteControl()
    265201{
    266202    HostCheckBox *gc = new HostCheckBox("IndividualMuteControl");
     
    35523488    group2->addChild(AggressiveBuffer());
    35533489
    35543490    return vcg;
    3555 
    35563491}
    35573492
    3558 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup
     3493static ConfigurationGroup *AudioMixerSettingsGroup()
    35593494{
    3560   public:
    3561     AudioMixerSettingsGroup() :
    3562         TriggeredConfigurationGroup(false, true, false, false)
    3563     {
    3564         setLabel(QObject::tr("Audio Mixer"));
    3565         setUseLabel(false);
     3495    ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false);
     3496   
     3497    vcg->setLabel(QObject::tr("Audio Mixer"));
     3498    vcg->setUseLabel(false);
    35663499
    3567         Setting *volumeControl = MythControlsVolume();
    3568         addChild(volumeControl);
     3500    vcg->addChild(MixerDevice());
    35693501
    3570         // Mixer settings
    3571         ConfigurationGroup *settings =
    3572             new VerticalConfigurationGroup(false, true, false, false);
    3573         settings->addChild(MixerDevice());
    3574         settings->addChild(MixerControl());
    3575         settings->addChild(MixerVolume());
    3576         settings->addChild(PCMVolume());
    3577         settings->addChild(IndividualMuteControl());
     3502    return vcg;
     3503}
    35783504
    3579         ConfigurationGroup *dummy =
    3580             new VerticalConfigurationGroup(false, true, false, false);
    3581 
    3582         // Show Mixer config only if internal volume controls enabled
    3583         setTrigger(volumeControl);
    3584         addTarget("0", dummy);
    3585         addTarget("1", settings);
    3586     }
    3587 };
    3588 
    35893505static HostComboBox *MythLanguage()
    35903506{
    35913507    HostComboBox *gc = new HostComboBox("Language");
     
    44854401
    44864402    addChild(AudioSystemSettingsGroup());
    44874403
    4488     addChild(new AudioMixerSettingsGroup());
     4404    addChild(AudioMixerSettingsGroup());
    44894405
    44904406    VerticalConfigurationGroup *general =
    44914407        new VerticalConfigurationGroup(false, true, false, false);
  • programs/mythtranscode/transcode.cpp

     
    166166        return last_audiotime;
    167167    }
    168168
    169     virtual int GetVolumeChannel(int) const
    170     {
    171         // Do nothing
    172         return 100;
    173     }
    174     virtual void SetVolumeChannel(int, int)
    175     {
    176         // Do nothing
    177     }
    178     virtual void SetVolumeAll(int)
    179     {
    180         // Do nothing
    181     }
    182     virtual uint GetCurrentVolume(void) const
    183     {
    184         // Do nothing
    185         return 100;
    186     }
    187     virtual void SetCurrentVolume(int)
    188     {
    189         // Do nothing
    190     }
    191     virtual void AdjustCurrentVolume(int)
    192     {
    193         // Do nothing
    194     }
    195     virtual void SetMute(bool)
    196     {
    197         // Do nothing
    198     }
    199     virtual void ToggleMute(void)
    200     {
    201         // Do nothing
    202     }
    203     virtual MuteState GetMuteState(void) const
    204     {
    205         // Do nothing
    206         return kMuteOff;
    207     }
    208     virtual MuteState IterateMutedChannels(void)
    209     {
    210         // Do nothing
    211         return kMuteOff;
    212     }
    213169    virtual bool ToggleUpmix(void)
    214170    {
    215171        // Do nothing
    216172        return false;
    217173    }
    218174
    219     virtual void SetSWVolume(int new_volume, bool save)
    220     {
    221         // Do nothing
    222         return;
    223     }
    224     virtual int GetSWVolume(void)
    225     {
    226         // Do nothing
    227         return 100;
    228     }
    229 
    230175    //  These are pure virtual in AudioOutput, but we don't need them here
    231176    virtual void bufferOutputData(bool){ return; }
    232177    virtual int readOutputData(unsigned char*, int ){ return 0; }