Ticket #7517: volume_control_trunk_r25178.patch

File volume_control_trunk_r25178.patch, 130.5 KB (added by mythtv@…, 15 years ago)
  • mythplugins/mythmusic/mythmusic/playbackbox.cpp

     
    9898
    9999    // Possibly (user-defined) control the volume
    100100
    101     volume_control = false;
    102     volume_display_timer = new QTimer(this);
    103     if (gCoreContext->GetNumSetting("MythControlsVolume", 0))
     101    volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice"));
     102    if (volume_control)
    104103    {
    105         volume_control = true;
     104        connect(volume_control.data(), SIGNAL(changedVolume(int)),
     105                this, SLOT(VolumeChanged(int)));
     106        connect(volume_control.data(), SIGNAL(changedMute(bool)),
     107                this, SLOT(MuteChanged(bool)));
    106108    }
     109
     110    volume_display_timer = new QTimer(this);
    107111    volume_display_timer->setSingleShot(true);
    108112    volume_display_timer->start(2000);
    109113    connect(volume_display_timer, SIGNAL(timeout()),
     
    11781182    if (volume_control && gPlayer->getOutput())
    11791183    {
    11801184        if (up_or_down)
    1181             gPlayer->getOutput()->AdjustCurrentVolume(2);
     1185            gPlayer->incVolume();
    11821186        else
    1183             gPlayer->getOutput()->AdjustCurrentVolume(-2);
     1187            gPlayer->decVolume();
    11841188        showVolume(true);
    11851189    }
    11861190}
     
    12011205{
    12021206    if (volume_control && gPlayer->getOutput())
    12031207    {
    1204         gPlayer->getOutput()->ToggleMute();
     1208        gPlayer->toggleMute();
    12051209        showVolume(true);
    12061210    }
    12071211}
     
    12431247        {
    12441248            if (on_or_off)
    12451249            {
    1246                 volume_status->SetUsed(gPlayer->getOutput()->GetCurrentVolume());
     1250                volume_status->SetUsed(gPlayer->getVolume());
    12471251                volume_status->SetOrder(0);
    12481252                volume_status->refresh();
    12491253                volume_display_timer->setSingleShot(true);
     
    24542458
    24552459    return time_string;
    24562460}
     2461
     2462void PlaybackBoxMusic::VolumeChanged(int)
     2463{
     2464     showVolume(true);
     2465}
     2466
     2467void PlaybackBoxMusic::MuteChanged(bool)
     2468{
     2469     showVolume(true);
     2470}
  • mythplugins/mythmusic/mythmusic/musicplayer.h

     
    33
    44#include <mythdialogs.h>
    55#include <audiooutput.h>
     6#include <libmyth/volumecontrolmanager.h>
    67#include <mythobservable.h>
    78
    89#include "metadata.h"
     
    5556
    5657    void setCDDevice(const QString &dev) { m_CDdevice = dev; }
    5758
    58     void      toggleMute(void);
    59     MuteState getMuteState(void) const;
    60     bool      isMuted(void) const { return getMuteState() == kMuteAll; }
     59    void toggleMute(void);
     60    bool isMuted(void) const;
    6161
    6262    void setVolume(int volume);
    6363    void incVolume(void);
     
    176176    AudioOutput *m_output;
    177177    Decoder     *m_decoder;
    178178
     179    QSharedPointer<VolumeControl> volume_control; ///< Volume control interface
     180
    179181    QSet<QObject*>  m_visualisers;
    180182
    181183    QString      m_CDdevice;
  • mythplugins/mythmusic/mythmusic/musicplayer.cpp

     
    8888
    8989    m_autoShowPlayer = (gCoreContext->GetNumSetting("MusicAutoShowPlayer", 1) > 0);
    9090
     91    volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice"));
     92
    9193    gCoreContext->addListener(this);
    9294}
    9395
     
    379381    // TODO: Error checking that device is opened correctly!
    380382    m_output = AudioOutput::OpenAudio(
    381383                   adevice, pdevice, FORMAT_S16, 2, 0, 44100,
    382                    AUDIOOUTPUT_MUSIC, true, false,
     384                   AUDIOOUTPUT_MUSIC, false,
    383385                   gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1);
    384386
    385387    m_output->setBufferSize(256 * 1024);
     
    939941
    940942void MusicPlayer::incVolume()
    941943{
    942     if (getOutput())
     944    if (volume_control)
    943945    {
    944         getOutput()->AdjustCurrentVolume(2);
     946        volume_control->increaseVolume();
    945947        sendVolumeChangedEvent();
    946948    }
    947949}
    948950
    949951void MusicPlayer::decVolume()
    950952{
    951     if (getOutput())
     953    if (volume_control)
    952954    {
    953         getOutput()->AdjustCurrentVolume(-2);
     955        volume_control->decreaseVolume();
    954956        sendVolumeChangedEvent();
    955957    }
    956958}
    957959
    958960void MusicPlayer::setVolume(int volume)
    959961{
    960     if (getOutput())
     962    if (volume_control)
    961963    {
    962         getOutput()->SetCurrentVolume(volume);
     964        volume_control->setVolume(volume);
    963965        sendVolumeChangedEvent();
    964966    }
    965967}
    966968
    967969uint MusicPlayer::getVolume(void) const
    968970{
    969     if (m_output)
    970         return m_output->GetCurrentVolume();
     971    if (volume_control)
     972        return volume_control->volume();
    971973    return 0;
    972974}
    973975
    974976void MusicPlayer::toggleMute(void)
    975977{
    976     if (m_output)
     978    if (volume_control)
    977979    {
    978         m_output->ToggleMute();
     980        volume_control->setMute(!volume_control->mute());
    979981        sendVolumeChangedEvent();
    980982    }
    981983}
    982984
    983 MuteState MusicPlayer::getMuteState(void) const
     985bool MusicPlayer::isMuted(void) const
    984986{
    985     if (m_output)
    986         return m_output->GetMuteState();
    987     return kMuteAll;
     987    if (volume_control)
     988        return volume_control->mute();
     989    return true;
    988990}
    989991
    990992void MusicPlayer::toMap(QHash<QString, QString> &map)
  • mythplugins/mythmusic/mythmusic/playbackbox.h

     
    88// mythtv
    99#include <mythwidgets.h>
    1010#include <dialogbox.h>
    11 #include <audiooutput.h>
     11#include <libmyth/volumecontrolmanager.h>
    1212
    1313// mythmusic
    1414#include "mainvisual.h"
     
    101101    bool getInsertPLOptions(InsertPLOption &insertOption,
    102102                            PlayPLOption &playOption, bool &bRemoveDups);
    103103
     104  protected slots:
     105    void VolumeChanged(int volume);
     106    void MuteChanged(bool mute);
     107
    104108  signals:
    105109
    106110    void dummy();   // debugging
     
    172176    bool show_album_art;
    173177    bool show_whole_tree;
    174178    bool keyboard_accelerators;
    175     bool volume_control;
     179    QSharedPointer<VolumeControl> volume_control; ///< Volume control interface
    176180
    177181    QString exit_action;
    178182
  • mythtv/configure

     
    637637    eval "$var=\"\$$var $*\""
    638638}
    639639
     640prepend(){
     641    var=$1
     642    shift
     643    flags_saved && eval "SAVE_$var=\"$* \$SAVE_$var\""
     644    eval "$var=\"$* \$$var\""
     645}
     646
    640647append_uniq(){
    641648    log append_uniq "$@"
    642649    var=$1
     
    36423649    { { ! enabled audio_alsa || die "ERROR: Alsa >= 1.0.16 required"; } &&
    36433650    disable audio_alsa; }
    36443651
     3652# OSS probe
     3653if ! disabled audio_oss ; then
     3654    if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h &&
     3655       check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then
     3656        disable soundcard_h
     3657        enable sys_soundcard_h
     3658        prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include"
     3659    elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h &&
     3660       check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then
     3661        disable soundcard_h
     3662        enable sys_soundcard_h
     3663        prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include"
     3664    else
     3665        if enabled soundcard_h ; then
     3666            check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" &&
     3667            enable  audio_oss ||
     3668            disable audio_oss
     3669        elif enabled sys_soundcard_h ; then
     3670            check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" &&
     3671            enable  audio_oss ||
     3672            disable audio_oss
     3673        fi
     3674    fi
     3675fi
    36453676
    36463677# JACK probe
    36473678! disabled audio_jack &&
  • mythtv/libs/libmythtv/NuppelVideoPlayer.cpp

     
    154154    return 0;
    155155}
    156156
    157 NuppelVideoPlayer::NuppelVideoPlayer(bool muted)
     157NuppelVideoPlayer::NuppelVideoPlayer()
    158158    : decoder(NULL),                decoder_change_lock(QMutex::Recursive),
    159159      videoOutput(NULL),            player_ctx(NULL),
    160160      decoderThread(NULL),          playerThread(NULL),
     
    214214      // OSD stuff
    215215      osd(NULL),
    216216      // Audio
    217       audio(this, muted),
     217      audio(this),
    218218      // Picture-in-Picture stuff
    219219      pip_active(false),            pip_visible(true),
    220220      // Filters
  • mythtv/libs/libmythtv/avformatdecoder.cpp

     
    496496      selectedVideoIndex(-1),
    497497      // Audio
    498498      audioSamples(NULL),
    499       internal_vol(false),
    500499      disable_passthru(false),
    501500      dummy_frame(NULL),
    502501      // DVD
     
    517516    av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR);
    518517    av_log_set_callback(myth_av_log);
    519518
    520     internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);
    521519
    522520    audioIn.sample_size = -32; // force SetupAudioStream to run once
    523521    itv = GetNVP()->GetInteractiveTV();
     
    46414639    bool passthru = false;
    46424640
    46434641    if (ctx->codec_id == CODEC_ID_AC3)
    4644         passthru = m_audio->CanAC3() &&
    4645             ctx->channels >= (int)m_audio->GetMaxChannels() &&
    4646                    !internal_vol;
     4642        passthru = m_audio->CanAC3();
    46474643    else if (ctx->codec_id == CODEC_ID_DTS)
    4648         passthru = m_audio->CanDTS() && !internal_vol;
     4644        passthru = m_audio->CanDTS();
    46494645
    46504646    passthru &= m_audio->CanPassthrough();
    46514647    passthru &= !transcoding && !disable_passthru;
  • mythtv/libs/libmythtv/mythbdplayer.h

     
    66class MythBDPlayer : public NuppelVideoPlayer
    77{
    88  public:
    9     MythBDPlayer(bool muted = false);
     9    MythBDPlayer();
    1010};
    1111
    1212#endif // MYTHBDPLAYER_H
  • mythtv/libs/libmythtv/tv_play.h

     
    3333#include "programinfo.h"
    3434#include "channelutil.h"
    3535#include "videoouttypes.h"
    36 #include "volumebase.h"
     36#include "volumecontrolmanager.h"
    3737#include "inputinfo.h"
    3838#include "channelgroup.h"
    3939
     
    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 OSDDialogEvent(int result, QString text, QString action);
    297300
     
    484487
    485488    vector<long long> TeardownAllNVPs(PlayerContext*);
    486489    void RestartAllNVPs(PlayerContext *lctx,
    487                         const vector<long long> &pos,
    488                         MuteState mctx_mute);
     490                        const vector<long long> &pos);
    489491    void RestartMainNVP(PlayerContext *mctx);
    490492
    491493    void PxPToggleView(  PlayerContext *actx, bool wantPBP);
     
    708710    /// Picture attribute to modify (on arrow left or right)
    709711    PictureAttribute  adjustingPictureAttribute;
    710712
     713    QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface
     714
    711715    // Ask Allow state
    712716    QMap<QString,AskProgramInfo> askAllowPrograms;
    713717    QMutex                       askAllowLock;
  • mythtv/libs/libmythtv/mythdvdplayer.h

     
    66class MythDVDPlayer : public NuppelVideoPlayer
    77{
    88  public:
    9     MythDVDPlayer(bool muted = false);
     9    MythDVDPlayer();
    1010    virtual int  OpenFile(uint retries = 4, bool allow_libmpeg2 = true);
    1111    virtual void ReleaseNextVideoFrame(VideoFrame *buffer, long long timecode,
    1212                                       bool wrap = true);
  • mythtv/libs/libmythtv/mythbdplayer.cpp

     
    33#define LOC     QString("BDPlayer: ")
    44#define LOC_ERR QString("BDPlayer error: ")
    55
    6 MythBDPlayer::MythBDPlayer(bool muted) : NuppelVideoPlayer(muted)
     6MythBDPlayer::MythBDPlayer() : NuppelVideoPlayer()
    77{
    88}
  • mythtv/libs/libmythtv/audioplayer.cpp

     
    44
    55#define LOC QString("AudioPlayer: ")
    66
    7 AudioPlayer::AudioPlayer(NuppelVideoPlayer *parent, bool muted)
     7AudioPlayer::AudioPlayer(NuppelVideoPlayer *parent)
    88  : m_parent(parent),    m_audioOutput(NULL),
    99    m_channels(2),       m_codec(0),            m_format(FORMAT_NONE),
    1010    m_samplerate(44100), m_stretchfactor(1.0f), m_lock(QMutex::Recursive),
    11     m_muted_on_creation(muted), m_main_device(QString::null),
     11    m_main_device(QString::null),
    1212    m_passthru_device(QString::null),
    1313    no_audio_in(false), no_audio_out(false)
    1414{
     
    8888            VERBOSE(VB_IMPORTANT, LOC + "Enabling Audio");
    8989            no_audio_out = false;
    9090        }
    91         if (m_muted_on_creation)
    92         {
    93             SetMuteState(kMuteAll);
    94             m_muted_on_creation = false;
    95         }
    9691    }
    9792
    9893    if (m_audioOutput)
     
    147142    m_lock.unlock();
    148143}
    149144
    150 uint AudioPlayer::GetVolume(void)
    151 {
    152     uint res = 0;
    153     m_lock.lock();
    154     if (m_audioOutput)
    155         res = m_audioOutput->GetCurrentVolume();
    156     m_lock.unlock();
    157     return res;
    158 }
    159 
    160145void AudioPlayer::SetAudioInfo(const QString &main_device,
    161146                               const QString &passthru_device,
    162147                               uint           samplerate)
     
    193178    m_lock.unlock();
    194179}
    195180
    196 bool AudioPlayer::SetMuted(bool mute)
    197 {
    198     QMutexLocker lock(&m_lock);
    199     bool is_muted = IsMuted();
    200 
    201     if (m_audioOutput && !is_muted && mute &&
    202         (kMuteAll == SetMuteState(kMuteAll)))
    203     {
    204         VERBOSE(VB_AUDIO, "muting sound " <<IsMuted());
    205         return true;
    206     }
    207     else if (m_audioOutput && is_muted && !mute &&
    208              (kMuteOff == SetMuteState(kMuteOff)))
    209     {
    210         VERBOSE(VB_AUDIO, "unmuting sound "<<IsMuted());
    211         return true;
    212     }
    213 
    214     VERBOSE(VB_AUDIO, "not changing sound mute state "<<IsMuted());
    215 
    216     return false;
    217 }
    218 
    219 MuteState AudioPlayer::SetMuteState(MuteState mstate)
    220 {
    221     QMutexLocker lock(&m_lock);
    222     if (m_audioOutput)
    223         return m_audioOutput->SetMuteState(mstate);
    224     return kMuteAll;
    225 }
    226 
    227 MuteState AudioPlayer::IncrMuteState(void)
    228 {
    229     QMutexLocker lock(&m_lock);
    230     MuteState mstate = kMuteAll;
    231     if (m_audioOutput)
    232         mstate = SetMuteState(VolumeBase::NextMuteState(GetMuteState()));
    233     return mstate;
    234 }
    235 
    236 MuteState AudioPlayer::GetMuteState(void)
    237 {
    238     QMutexLocker lock(&m_lock);
    239     if (m_audioOutput)
    240         return m_audioOutput->GetMuteState();
    241     return kMuteAll;
    242 }
    243 
    244 uint AudioPlayer::AdjustVolume(int change)
    245 {
    246     QMutexLocker lock(&m_lock);
    247     if (m_audioOutput)
    248         m_audioOutput->AdjustCurrentVolume(change);
    249     return GetVolume();
    250 }
    251 
    252181long long AudioPlayer::GetAudioTime(void)
    253182{
    254183    long long time = 0;
  • mythtv/libs/libmythtv/mythdvdplayer.cpp

     
    88#define LOC_WARN QString("DVDPlayer, Warning: ")
    99#define LOC_ERR  QString("DVDPlayer, Error: ")
    1010
    11 MythDVDPlayer::MythDVDPlayer(bool muted)
    12   : NuppelVideoPlayer(muted), hidedvdbutton(true),
     11MythDVDPlayer::MythDVDPlayer()
     12  : NuppelVideoPlayer(), hidedvdbutton(true),
    1313    dvd_stillframe_showing(false), need_change_dvd_track(0)
    1414{
    1515}
  • mythtv/libs/libmythtv/playercontext.cpp

     
    401401
    402402bool PlayerContext::CreateNVP(TV *tv, QWidget *widget,
    403403                              TVState desiredState,
    404                               WId embedwinid, const QRect *embedbounds,
    405                               bool muted)
     404                              WId embedwinid, const QRect *embedbounds)
    406405{
    407406    int exact_seeking = gCoreContext->GetNumSetting("ExactSeeking", 0);
    408407
     
    415414
    416415    NuppelVideoPlayer *_nvp = NULL;
    417416    if (kState_WatchingBD  == desiredState)
    418         _nvp = new MythBDPlayer(muted);
     417        _nvp = new MythBDPlayer();
    419418    if (kState_WatchingDVD == desiredState)
    420         _nvp = new MythDVDPlayer(muted);
     419        _nvp = new MythDVDPlayer();
    421420    else
    422         _nvp = new NuppelVideoPlayer(muted);
     421        _nvp = new NuppelVideoPlayer();
    423422
    424423    if (nohardwaredecoders)
    425424        _nvp->DisableHardwareDecoders();
     
    471470                VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg);
    472471        }
    473472    }
    474     else if (pipState == kPBPRight)
    475         nvp->SetMuted(true);
    476473
    477474    return StartPlaying(-1);
    478475}
  • mythtv/libs/libmythtv/NuppelVideoPlayer.h

     
    77#include <QTimer>
    88
    99#include "playercontext.h"
    10 #include "volumebase.h"
    1110#include "audiooutputsettings.h"
    1211#include "RingBuffer.h"
    1312#include "osd.h"
     
    121120    friend class DecoderThread;
    122121
    123122  public:
    124     NuppelVideoPlayer(bool muted = false);
     123    NuppelVideoPlayer();
    125124   ~NuppelVideoPlayer();
    126125
    127126    // Initialization
     
    136135    bool IsEmbedding(void);
    137136    void WindowResized(const QSize &new_size);
    138137
    139     // Audio Sets
    140     uint AdjustVolume(int change)           { return audio.AdjustVolume(change); }
    141     bool SetMuted(bool mute)                { return audio.SetMuted(mute);       }
    142     MuteState SetMuteState(MuteState state) { return audio.SetMuteState(state);  }
    143     MuteState IncrMuteState(void)           { return audio.IncrMuteState();      }
    144 
    145138    // Sets
    146139    void SetPlayerInfo(TV             *tv,
    147140                       QWidget        *widget,
     
    190183    float   GetFrameRate(void) const          { return video_frame_rate; }
    191184
    192185    bool    IsAudioNeeded(void) { return !using_null_videoout && player_ctx->IsAudioNeeded(); }
    193     uint    GetVolume(void) { return audio.GetVolume(); }
    194186    int     GetSecondsBehind(void) const;
    195187    AspectOverrideMode GetAspectOverride(void) const;
    196188    AdjustFillMode     GetAdjustFill(void) const;
    197     MuteState          GetMuteState(void) { return audio.GetMuteState(); }
    198189
    199190    int     GetFFRewSkip(void) const          { return ffrew_skip; }
    200191    AudioPlayer* GetAudio(void)               { return &audio; }
     
    225216    bool    HasAudioOut(void) const           { return audio.HasAudioOut(); }
    226217    bool    IsPIPActive(void) const           { return pip_active; }
    227218    bool    IsPIPVisible(void) const          { return pip_visible; }
    228     bool    IsMuted(void)                     { return audio.IsMuted(); }
    229219    bool    UsingNullVideo(void) const { return using_null_videoout; }
    230220    bool    HasTVChainNext(void) const;
    231221
  • mythtv/libs/libmythtv/tv_play.cpp

     
    10371037    player.push_back(new PlayerContext(kPlayerInUseID));
    10381038    playerActive = 0;
    10391039    playerLock.unlock();
     1040
     1041    volumeControl = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice"));
     1042    if (volumeControl)
     1043    {
     1044        connect(volumeControl.data(), SIGNAL(changedVolume(int)),
     1045                this, SLOT(VolumeChanged(int)), Qt::QueuedConnection);
     1046        connect(volumeControl.data(), SIGNAL(changedMute(bool)),
     1047                this, SLOT(MuteChanged(bool)), Qt::QueuedConnection);
     1048    }
     1049
    10401050    VERBOSE(VB_PLAYBACK, LOC + "ctor -- end");
    10411051}
    10421052
     
    51165126        }
    51175127    }
    51185128
    5119     MuteState mctx_mute = kMuteOff;
    5120     mctx->LockDeleteNVP(__FILE__, __LINE__);
    5121     if (mctx->nvp)
    5122         mctx_mute = mctx->nvp->GetMuteState();
    5123     mctx->UnlockDeleteNVP(__FILE__, __LINE__);
    5124 
    51255129    vector<long long> pos = TeardownAllNVPs(mctx);
    51265130
    51275131    if (wantPBP)
     
    51395143        }
    51405144    }
    51415145
    5142     RestartAllNVPs(mctx, pos, mctx_mute);
     5146    RestartAllNVPs(mctx, pos);
    51435147
    51445148    VERBOSE(VB_PLAYBACK, LOC +
    51455149            QString("PxPToggleType() converting from %1 to %2 -- end")
     
    52835287* \brief Recreate Main and PIP windows. Could be either PIP or PBP views.
    52845288*/
    52855289void TV::RestartAllNVPs(PlayerContext *lctx,
    5286                         const vector<long long> &pos,
    5287                         MuteState mctx_mute)
     5290                        const vector<long long> &pos)
    52885291{
    52895292    QString loc = LOC + QString("RestartAllNVPs(): ");
    52905293
     
    53315334            pipctx->LockDeleteNVP(__FILE__, __LINE__);
    53325335            if (pipctx->nvp)
    53335336            {
    5334                 pipctx->nvp->SetMuted(true);
    53355337                pipctx->nvp->JumpToFrame(pos[i]);
    53365338            }
    53375339            pipctx->UnlockDeleteNVP(__FILE__, __LINE__);
     
    53435345            ForceNextStateNone(pipctx);
    53445346        }
    53455347    }
    5346 
    5347     // If old main player had a kMuteAll | kMuteOff setting,
    5348     // apply old main player's mute setting to new main player.
    5349     mctx->LockDeleteNVP(__FILE__, __LINE__);
    5350     if (mctx->nvp && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))
    5351         mctx->nvp->SetMuteState(mctx_mute);
    5352     mctx->UnlockDeleteNVP(__FILE__, __LINE__);
    53535348}
    53545349
    53555350void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx)
     
    53775372        return;
    53785373    }
    53795374
    5380     MuteState mctx_mute = mctx->nvp->GetMuteState();
    53815375    mctx->deleteNVPLock.unlock();
    53825376    pipctx->deleteNVPLock.unlock();
    53835377
     
    53915385    playerActive = (ctx_index == playerActive) ?
    53925386        0 : ((ctx_index == 0) ? ctx_index : playerActive);
    53935387
    5394     RestartAllNVPs(mctx, pos, mctx_mute);
     5388    RestartAllNVPs(mctx, pos);
    53955389
    53965390    SetActive(mctx, playerActive, false);
    53975391
     
    54125406        mctx->deleteNVPLock.unlock();
    54135407        return;
    54145408    }
    5415 
    5416     MuteState mctx_mute = mctx->nvp->GetMuteState();
    5417 
    5418     // HACK - FIXME
    5419     // workaround muted audio when NVP is re-created
    5420     mctx_mute = kMuteOff;
    5421     // FIXME - end
    54225409    mctx->deleteNVPLock.unlock();
    54235410
    54245411    vector<long long> pos = TeardownAllNVPs(mctx);
    5425     RestartAllNVPs(mctx, pos, mctx_mute);
     5412    RestartAllNVPs(mctx, pos);
    54265413    SetActive(mctx, playerActive, false);
    54275414
    54285415    VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end");
     
    61266113        if (mctx != ctx)
    61276114            PIPRemovePlayer(mctx, ctx);
    61286115
    6129         bool muted = false;
    6130         ctx->LockDeleteNVP(__FILE__, __LINE__);
    6131         if (ctx->nvp && ctx->nvp->IsMuted())
    6132             muted = true;
    6133         ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    6134 
    61356116        // pause the decoder first, so we're not reading too close to the end.
    61366117        ctx->buffer->IgnoreLiveEOF(true);
    61376118        ctx->buffer->StopReads();
     
    61836164
    61846165            if (ctx->CreateNVP(
    61856166                    this, GetMythMainWindow(), ctx->GetState(),
    6186                     mctx->embedWinID, &mctx->embedBounds, muted))
     6167                    mctx->embedWinID, &mctx->embedBounds))
    61876168            {
    61886169                ScheduleStateChange(ctx);
    61896170                ok = true;
     
    77757756
    77767757void TV::ChangeVolume(PlayerContext *ctx, bool up)
    77777758{
    7778     ctx->LockDeleteNVP(__FILE__, __LINE__);
    7779     if (!ctx->nvp)
     7759    if (volumeControl)
    77807760    {
    7781         ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    7782         return;
     7761        if (up)
     7762            volumeControl->increaseVolume();
     7763        else
     7764            volumeControl->decreaseVolume();
    77837765    }
    7784     uint curvol = ctx->nvp->AdjustVolume((up) ? +2 : -2);
    7785     ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    7786 
    7787     if (!browsemode)
    7788     {
    7789         UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"),
    7790                         QString::number(curvol),
    7791                         kOSDFunctionalType_PictureAdjust, "%", curvol * 10);
    7792         SetUpdateOSDPosition(false);
    7793     }
    77947766}
    77957767
    77967768void TV::ToggleTimeStretch(PlayerContext *ctx)
     
    79327904
    79337905void TV::ToggleMute(PlayerContext *ctx, const bool muteIndividualChannels)
    79347906{
    7935     ctx->LockDeleteNVP(__FILE__, __LINE__);
    7936     if (!ctx->nvp || !ctx->nvp->HasAudioOut())
    7937     {
    7938         ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    7939         return;
    7940     }
    7941 
    7942     MuteState mute_status;
    7943 
    7944     if (!muteIndividualChannels)
    7945     {
    7946         ctx->nvp->SetMuted(!ctx->nvp->IsMuted());
    7947         mute_status = (ctx->nvp->IsMuted()) ? kMuteAll : kMuteOff;
    7948     }
    7949     else
    7950     {
    7951         mute_status = ctx->nvp->IncrMuteState();
    7952     }
    7953     ctx->UnlockDeleteNVP(__FILE__, __LINE__);
    7954 
    7955     QString text;
    7956 
    7957     switch (mute_status)
    7958     {
    7959         case kMuteOff:   text = tr("Mute Off"); break;
    7960         case kMuteAll:   text = tr("Mute On"); break;
    7961         case kMuteLeft:  text = tr("Left Channel Muted"); break;
    7962         case kMuteRight: text = tr("Right Channel Muted"); break;
    7963     }
    7964 
    7965     SetOSDMessage(ctx, text);
     7907    if (volumeControl)
     7908        volumeControl->setMute(!volumeControl->mute());
    79667909}
    79677910
    79687911void TV::ToggleSleepTimer(const PlayerContext *ctx)
     
    89178860        {
    89188861            value = ctx->nvp->getVideoOutput()->GetPictureAttribute(attr);
    89198862        }
    8920         else if (ctx->nvp->HasAudioOut())
     8863        else if (ctx->nvp->HasAudioOut() && volumeControl)
    89218864        {
    8922             value = ctx->nvp->GetVolume();
     8865            value = volumeControl->volume();
    89238866            title = tr("Adjust Volume");
    89248867        }
    89258868    }
     
    1177811721    ReturnPlayerLock(mctx);
    1177911722}
    1178011723
     11724void TV::VolumeChanged(int volume)
     11725{
     11726    if (!browsemode)
     11727    {
     11728        PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__);
     11729        UpdateOSDStatus(actx, tr("Adjust Volume"), tr("Volume"),
     11730                        QString::number(volume),
     11731                        kOSDFunctionalType_PictureAdjust, "%", 10 * volume);
     11732        SetUpdateOSDPosition(false);
     11733        ReturnPlayerLock(actx);
     11734    }
     11735}
     11736
     11737void TV::MuteChanged(bool mute)
     11738{
     11739    PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__);
     11740    SetOSDMessage(actx, mute ? tr("Mute On") : tr("Mute Off"));
     11741    ReturnPlayerLock(actx);
     11742}
     11743
     11744
    1178111745OSD *TV::GetOSDL(const char *file, int location)
    1178211746{
    1178311747    PlayerContext *actx = GetPlayerReadLock(-1, file, location);
  • mythtv/libs/libmythtv/playercontext.h

     
    6868    // Actions
    6969    bool CreateNVP(TV *tv, QWidget *widget,
    7070                   TVState desiredState,
    71                    WId embedwinid, const QRect *embedBounds,
    72                    bool muted = false);
     71                   WId embedwinid, const QRect *embedBounds);
    7372    void TeardownPlayer(void);
    7473    bool StartPlaying(int maxWait = -1);
    7574    void StopPlaying(void);
  • mythtv/libs/libmythtv/avformatdecoder.h

     
    298298
    299299    // Audio
    300300    short int        *audioSamples;
    301     bool              internal_vol;
    302301    bool              disable_passthru;
    303302
    304303    VideoFrame       *dummy_frame;
  • mythtv/libs/libmythtv/mythcommflagplayer.h

     
    66class MPUBLIC MythCommFlagPlayer : public NuppelVideoPlayer
    77{
    88  public:
    9     MythCommFlagPlayer(bool muted = false) : NuppelVideoPlayer(muted) { }
    109    bool RebuildSeekTable(bool showPercentage = true, StatusCallback cb = NULL,
    1110                          void* cbData = NULL);
    1211};
  • mythtv/libs/libmythtv/audioplayer.h

     
    77class MPUBLIC AudioPlayer
    88{
    99  public:
    10     AudioPlayer(NuppelVideoPlayer *parent, bool muted);
     10    AudioPlayer(NuppelVideoPlayer *parent);
    1111   ~AudioPlayer();
    1212
    1313    void  Reset(void);
     
    2828    bool  Pause(bool pause);
    2929    bool  IsPaused(void);
    3030    void  PauseAudioUntilBuffered(void);
    31     uint  GetVolume(void);
    32     uint  AdjustVolume(int change);
    3331    float GetStretchFactor(void) { return m_stretchfactor;   }
    3432    void  SetStretchFactor(float factor);
    3533    bool  ToggleUpmix(void);
     
    3937    uint  GetMaxChannels(void);
    4038    long long GetAudioTime(void);
    4139
    42     bool      IsMuted(void) { return GetMuteState() == kMuteAll; }
    43     bool      SetMuted(bool mute);
    44     MuteState GetMuteState(void);
    45     MuteState SetMuteState(MuteState);
    46     MuteState IncrMuteState(void);
    47 
    4840    void AddAudioData(char *buffer, int len, long long timecode);
    4941    bool GetBufferStatus(uint &fill, uint &total);
    5042
     
    5850    float        m_stretchfactor;
    5951    bool         m_passthru;
    6052    QMutex       m_lock;
    61     bool         m_muted_on_creation;
    6253    QString      m_main_device;
    6354    QString      m_passthru_device;
    6455    bool         no_audio_in;
  • mythtv/libs/libmyth/audiooutputwin.cpp

     
    280280    return m_nPkts * fragment_size;
    281281}
    282282
    283 int AudioOutputWin::GetVolumeChannel(int channel) const
    284 {
    285     DWORD dwVolume = 0xffffffff;
    286     int Volume = 100;
    287     if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))
    288     {
    289         Volume = (channel == 0) ?
    290             (LOWORD(dwVolume) / (0xffff / 100)) :
    291             (HIWORD(dwVolume) / (0xffff / 100));
    292     }
    293 
    294     VERBOSE(VB_AUDIO, "GetVolume(" << channel << ") "
    295                       << Volume << "(" << dwVolume << ")");
    296 
    297     return Volume;
    298 }
    299 
    300 void AudioOutputWin::SetVolumeChannel(int channel, int volume)
    301 {
    302     if (channel > 1)
    303         VBERROR("Windows volume only supports stereo!");
    304 
    305     DWORD dwVolume = 0xffffffff;
    306     if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))
    307     {
    308         if (channel == 0)
    309             dwVolume = dwVolume & 0xffff0000 | volume * (0xffff / 100);
    310         else
    311             dwVolume = dwVolume & 0xffff | ((volume * (0xffff / 100)) << 16);
    312     }
    313     else
    314     {
    315         dwVolume = volume * (0xffff / 100);
    316         dwVolume |= (dwVolume << 16);
    317     }
    318 
    319     VBAUDIO(QString("SetVolume(%1) %2(%3)")
    320             .arg(channel).arg(volume).arg(dwVolume));
    321 
    322     waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, dwVolume);
    323 }
  • mythtv/libs/libmyth/volumecontrolmanager.cpp

     
     1#include "volumecontrolmanager.h"
     2
     3#include "mythverbose.h"
     4#ifdef USE_ALSA
     5#include "volumecontrolalsa.h"
     6#endif
     7#ifdef USE_COREAUDIO
     8#include "volumecontrolcoreaudio.h"
     9#endif
     10#ifdef USING_OSS
     11#include "volumecontroloss.h"
     12#endif
     13#ifdef USING_MINGW
     14#include "volumecontrolendpoint.h"
     15#endif
     16#include "volumecontrolsoftware.h"
     17
     18
     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}
  • mythtv/libs/libmyth/volumecontrolalsa.cpp

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

     
    1818#include "audiooutput.h"
    1919#include "samplerate.h"
    2020#include "mythverbose.h"
     21#include "volumecontrolmanager.h"
    2122
    2223#define VBAUDIO(str)   VERBOSE(VB_AUDIO, LOC + str)
    2324#define VBAUDIOTS(str) VERBOSE(VB_AUDIO+VB_TIMESTAMP, LOC + str)
     
    5556
    5657    virtual void Reset(void);
    5758
    58     void SetSWVolume(int new_volume, bool save);
    59     int GetSWVolume(void);
    60 
    6159    // timecode is in milliseconds.
    6260    virtual bool AddFrames(void *buffer, int frames, long long timecode);
    6361
     
    147145    bool killaudio;
    148146
    149147    bool pauseaudio, actually_paused, was_paused, unpause_when_ready;
    150     bool set_initial_vol;
    151148    bool buffer_output_data_for_use; //  used by AudioOutputNULL
    152149
    153150    int configured_channels;
     
    174171    int surround_mode;
    175172    bool allow_ac3_passthru;
    176173    float old_stretchfactor;
    177     int volume;
     174    QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface
    178175    QString volumeControl;
    179176
    180177    bool processing;
  • mythtv/libs/libmyth/audiooutputalsa.cpp

     
     1#include "audiooutputalsa.h"
     2
    13#include <cstdio>
    24#include <cstdlib>
    35#include <sys/time.h>
     
    810
    911#include <QFile>
    1012#include "mythcorecontext.h"
    11 #include "audiooutputalsa.h"
    1213
    1314#define LOC QString("ALSA: ")
    1415#define LOC_WARN QString("ALSA, Warning: ")
     
    4041    m_device(-1),
    4142    m_subdevice(-1)
    4243{
    43     m_mixer.handle = NULL;
    44     m_mixer.elem = NULL;
    45 
    4644    // Set everything up
    4745    InitSettings(settings);
    4846    if (settings.init)
     
    406404        return OpenDevice();
    407405    }
    408406
    409     if (internal_vol && !OpenMixer())
    410         VBERROR("Unable to open audio mixer. Volume control disabled");
    411 
    412407    // Device opened successfully
    413408    return true;
    414409}
    415410
    416411void AudioOutputALSA::CloseDevice()
    417412{
    418     if (m_mixer.handle)
    419         snd_mixer_close(m_mixer.handle);
    420     m_mixer.handle = NULL;
    421413    if (pcm_handle)
    422414    {
    423415        snd_pcm_close(pcm_handle);
     
    685677    return 0;
    686678}
    687679
    688 int AudioOutputALSA::GetVolumeChannel(int channel) const
    689 {
    690     int retvol = 0;
    691 
    692     if (!m_mixer.elem)
    693         return retvol;
    694 
    695     snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
    696     if (!snd_mixer_selem_has_playback_channel(m_mixer.elem, chan))
    697         return retvol;
    698 
    699     long mixervol;
    700     int chk;
    701     if ((chk = snd_mixer_selem_get_playback_volume(m_mixer.elem,
    702                                                    chan,
    703                                                    &mixervol)) < 0)
    704     {
    705         VBERROR(QString("failed to get channel %1 volume, mixer %2/%3: %4")
    706                 .arg(channel).arg(m_mixer.device)
    707                 .arg(m_mixer.control)
    708                 .arg(snd_strerror(chk)));
    709     }
    710     else
    711     {
    712         retvol = (m_mixer.volrange != 0L) ? (mixervol - m_mixer.volmin) *
    713                                             100.0f / m_mixer.volrange + 0.5f
    714                                             : 0;
    715         retvol = max(retvol, 0);
    716         retvol = min(retvol, 100);
    717         VBAUDIO(QString("get volume channel %1: %2")
    718                 .arg(channel).arg(retvol));
    719     }
    720     return retvol;
    721 }
    722 
    723 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)
    724 {
    725     if (!(internal_vol && m_mixer.elem))
    726         return;
    727 
    728     long mixervol = volume * m_mixer.volrange / 100.0f - m_mixer.volmin + 0.5f;
    729     mixervol = max(mixervol, m_mixer.volmin);
    730     mixervol = min(mixervol, m_mixer.volmax);
    731 
    732     snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
    733     if (snd_mixer_selem_set_playback_volume(m_mixer.elem, chan, mixervol) < 0)
    734         VBERROR(QString("failed to set channel %1 volume").arg(channel));
    735     else
    736         VBAUDIO(QString("channel %1 volume set %2 => %3")
    737                 .arg(channel).arg(volume).arg(mixervol));
    738 }
    739 
    740 bool AudioOutputALSA::OpenMixer(void)
    741 {
    742     if (!pcm_handle)
    743     {
    744         VBERROR("mixer setup without a pcm");
    745         return false;
    746     }
    747     m_mixer.device = gCoreContext->GetSetting("MixerDevice", "default");
    748     m_mixer.device = m_mixer.device.remove(QString("ALSA:"));
    749     if (m_mixer.device.toLower() == "software")
    750         return true;
    751 
    752     m_mixer.control = gCoreContext->GetSetting("MixerControl", "PCM");
    753 
    754     QString mixer_device_tag = QString("mixer device %1").arg(m_mixer.device);
    755 
    756     int chk;
    757     if ((chk = snd_mixer_open(&m_mixer.handle, 0)) < 0)
    758     {
    759         VBERROR(QString("failed to open mixer device %1: %2")
    760                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    761         return false;
    762     }
    763 
    764     QByteArray dev_ba = m_mixer.device.toAscii();
    765     struct snd_mixer_selem_regopt regopts =
    766         {1, SND_MIXER_SABSTRACT_NONE, dev_ba.constData(), NULL, NULL};
    767 
    768     if ((chk = snd_mixer_selem_register(m_mixer.handle, &regopts, NULL)) < 0)
    769     {
    770         snd_mixer_close(m_mixer.handle);
    771         m_mixer.handle = NULL;
    772         VBERROR(QString("failed to register %1: %2")
    773                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    774         return false;
    775     }
    776 
    777     if ((chk = snd_mixer_load(m_mixer.handle)) < 0)
    778     {
    779         snd_mixer_close(m_mixer.handle);
    780         m_mixer.handle = NULL;
    781         VBERROR(QString("failed to load %1: %2")
    782                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    783         return false;
    784     }
    785 
    786     m_mixer.elem = NULL;
    787     uint elcount = snd_mixer_get_count(m_mixer.handle);
    788     snd_mixer_elem_t* elx = snd_mixer_first_elem(m_mixer.handle);
    789 
    790     for (uint ctr = 0; elx != NULL && ctr < elcount; ctr++)
    791     {
    792         QString tmp = QString(snd_mixer_selem_get_name(elx));
    793         if (m_mixer.control == tmp &&
    794             !snd_mixer_selem_is_enumerated(elx) &&
    795             snd_mixer_selem_has_playback_volume(elx) &&
    796             snd_mixer_selem_is_active(elx))
    797         {
    798             m_mixer.elem = elx;
    799             VBAUDIO(QString("found playback control %1 on %2")
    800                     .arg(m_mixer.control)
    801                     .arg(mixer_device_tag));
    802             break;
    803         }
    804         elx = snd_mixer_elem_next(elx);
    805     }
    806     if (!m_mixer.elem)
    807     {
    808         snd_mixer_close(m_mixer.handle);
    809         m_mixer.handle = NULL;
    810         VBERROR(QString("no playback control %1 found on %2")
    811                 .arg(m_mixer.control).arg(mixer_device_tag));
    812         return false;
    813     }
    814     if ((snd_mixer_selem_get_playback_volume_range(m_mixer.elem,
    815                                                    &m_mixer.volmin,
    816                                                    &m_mixer.volmax) < 0))
    817     {
    818         snd_mixer_close(m_mixer.handle);
    819         m_mixer.handle = NULL;
    820         VBERROR(QString("failed to get volume range on %1/%2")
    821                 .arg(mixer_device_tag).arg(m_mixer.control));
    822         return false;
    823     }
    824 
    825     m_mixer.volrange = m_mixer.volmax - m_mixer.volmin;
    826     VBAUDIO(QString("mixer volume range on %1/%2 - min %3, max %4, range %5")
    827             .arg(mixer_device_tag).arg(m_mixer.control)
    828             .arg(m_mixer.volmin).arg(m_mixer.volmax).arg(m_mixer.volrange));
    829     VBAUDIO(QString("%1/%2 set up successfully")
    830             .arg(mixer_device_tag)
    831             .arg(m_mixer.control));
    832 
    833     if (set_initial_vol)
    834     {
    835         int initial_vol;
    836         if (m_mixer.control == "PCM")
    837             initial_vol = gCoreContext->GetNumSetting("PCMMixerVolume", 80);
    838         else
    839             initial_vol = gCoreContext->GetNumSetting("MasterMixerVolume", 80);
    840         for (int ch = 0; ch < channels; ++ch)
    841             SetVolumeChannel(ch, initial_vol);
    842     }
    843 
    844     return true;
    845 }
    846 
    847680QMap<QString, QString> *AudioOutputALSA::GetALSADevices(const char *type)
    848681{
    849682    QMap<QString, QString> *alsadevs = new QMap<QString, QString>();
  • mythtv/libs/libmyth/volumebase.cpp

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

     
     1#ifndef VOLUMECONTROLCOREAUDIO
     2#define VOLUMECONTROLCOREAUDIO
     3
     4#include "volumecontrol.h"
     5
     6#include <QHash>
     7#include <QAtomicInt>
     8#include <CoreAudio/CoreAudio.h>
     9
     10
     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
  • mythtv/libs/libmyth/volumecontrolsoftware.h

     
     1#ifndef VOLUMECONTROLSOFTWARE
     2#define VOLUMECONTROLSOFTWARE
     3
     4#include "volumecontrol.h"
     5
     6#include <QHash>
     7#include <QAtomicInt>
     8
     9
     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
  • mythtv/libs/libmyth/volumecontrolcoreaudio.cpp

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

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

     
     1#ifndef VOLUMECONTROL
     2#define VOLUMECONTROL
     3
     4#include <QObject>
     5#include <QString>
     6
     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
  • mythtv/libs/libmyth/volumecontrolsoftware.cpp

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

     
    3030    AudioOutputPulseAudio(const AudioSettings &settings);
    3131   ~AudioOutputPulseAudio();
    3232
    33     int GetVolumeChannel(int channel) const;
    34     void SetVolumeChannel(int channel, int volume);
    3533    void Drain(void);
    3634
    3735  protected:
  • mythtv/libs/libmyth/volumecontroloss.h

     
     1#ifndef VOLUMECONTROLOSS
     2#define VOLUMECONTROLOSS
     3
     4#include "volumecontrol.h"
     5
     6#include <QHash>
     7#include <QThread>
     8#include <QAtomicInt>
     9
     10
     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
  • mythtv/libs/libmyth/volumecontrolalsa.h

     
     1#ifndef VOLUMECONTROLALSA
     2#define VOLUMECONTROLALSA
     3
     4#include "volumecontrol.h"
     5
     6#include <QHash>
     7#include <QThread>
     8#include <QAtomicInt>
     9#include <alsa/asoundlib.h>
     10
     11
     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
  • mythtv/libs/libmyth/audiooutputpulse.cpp

     
    312312    return (int)latency * samplerate * output_bytes_per_frame / 1000000;
    313313}
    314314
    315 int AudioOutputPulseAudio::GetVolumeChannel(int channel) const
    316 {
    317     return (float)volume_control.values[channel] /
    318            (float)PA_VOLUME_NORM * 100.0f;
    319 }
    320 
    321 void AudioOutputPulseAudio::SetVolumeChannel(int channel, int volume)
    322 {
    323     QString fn_log_tag = "SetVolumeChannel, ";
    324 
    325     if (channel < 0 || channel > PULSE_MAX_CHANNELS || volume < 0)
    326     {
    327         VBERROR(fn_log_tag + QString("bad volume params, channel %1, volume %2")
    328                              .arg(channel).arg(volume));
    329         return;
    330     }
    331 
    332     volume_control.values[channel] =
    333         (float)volume / 100.0f * (float)PA_VOLUME_NORM;
    334 
    335     volume = min(100, volume);
    336     volume = max(0, volume);
    337 
    338     uint32_t sink_index = pa_stream_get_device_index(pstream);
    339     pa_threaded_mainloop_lock(mainloop);
    340     pa_operation *op =
    341         pa_context_set_sink_volume_by_index(pcontext, sink_index,
    342                                             &volume_control,
    343                                             OpCompletionCallback, this);
    344     pa_threaded_mainloop_unlock(mainloop);
    345     if (op)
    346         pa_operation_unref(op);
    347     else
    348         VBERROR(fn_log_tag +
    349                 QString("set sink volume operation failed, sink %1, error %2 ")
    350                 .arg(sink_index).arg(pa_strerror(pa_context_errno(pcontext))));
    351 }
    352 
    353315void AudioOutputPulseAudio::Drain(void)
    354316{
    355317    AudioOutputBase::Drain();
     
    493455    pa_stream_set_overflow_callback(pstream, BufferFlowCallback, (char*)"over");
    494456    pa_stream_set_underflow_callback(pstream, BufferFlowCallback,
    495457                                     (char*)"under");
    496     if (set_initial_vol)
    497     {
    498         int volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);
    499         pa_cvolume_set(&volume_control, channels,
    500                        (float)volume * (float)PA_VOLUME_NORM / 100.0f);
    501     }
    502     else
    503         pa_cvolume_reset(&volume_control, channels);
     458    pa_cvolume_reset(&volume_control, channels);
    504459
    505460    fragment_size = (samplerate * 25 * output_bytes_per_frame) / 1000;
    506461
  • mythtv/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}
  • mythtv/libs/libmyth/audiooutputjack.h

     
    1818    AudioOutputJACK(const AudioSettings &settings);
    1919    virtual ~AudioOutputJACK();
    2020
    21     // Volume control
    22     virtual int GetVolumeChannel(int channel) const; // Returns 0-100
    23     virtual void SetVolumeChannel(int channel, int volume); // range 0-100
    24 
    2521  protected:
    2622
    2723    // You need to implement the following functions
     
    3733
    3834  private:
    3935
    40     void VolumeInit(void);
    41 
    4236    // Our various callback functions
    4337    inline int JackCallback(jack_nframes_t nframes);
    4438    static int _JackCallback(jack_nframes_t nframes, void *arg);
  • mythtv/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),
     
    3029    channels(other.channels),
    3130    codec(other.codec),
    3231    samplerate(other.samplerate),
    33     set_initial_vol(other.set_initial_vol),
    3432    use_passthru(other.use_passthru),
    3533    source(other.source),
    3634    upmixer(other.upmixer),
     
    4644    int               codec,
    4745    int               samplerate,
    4846    AudioOutputSource source,
    49     bool              set_initial_vol,
    5047    bool              use_passthru,
    5148    int               upmixer_startup) :
    5249    main_device(main_device),
     
    5552    channels(channels),
    5653    codec(codec),
    5754    samplerate(samplerate),
    58     set_initial_vol(set_initial_vol),
    5955    use_passthru(use_passthru),
    6056    source(source),
    6157    upmixer(upmixer_startup),
     
    7672    channels(channels),
    7773    codec(codec),
    7874    samplerate(samplerate),
    79     set_initial_vol(false),
    8075    use_passthru(use_passthru),
    8176    source(AUDIOOUTPUT_UNKNOWN),
    8277    upmixer(upmixer_startup),
     
    9388    channels(-1),
    9489    codec(0),
    9590    samplerate(-1),
    96     set_initial_vol(false),
    9791    use_passthru(false),
    9892    source(AUDIOOUTPUT_UNKNOWN),
    9993    upmixer(0),
  • mythtv/libs/libmyth/audiooutputca.cpp

     
    310310        return false;
    311311    }
    312312
    313     if (internal_vol && set_initial_vol)
    314     {
    315         QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");
    316         controlLabel += "MixerVolume";
    317         SetCurrentVolume(gCoreContext->GetNumSetting(controlLabel, 80));
    318     }
    319 
    320313    return true;
    321314}
    322315
     
    422415    return noErr;
    423416}
    424417
    425 int AudioOutputCA::GetVolumeChannel(int channel) const
    426 {
    427     // FIXME: this only returns global volume
    428     (void)channel;
    429     Float32 volume;
    430 
    431     if (!AudioUnitGetParameter(d->mOutputUnit,
    432                                kHALOutputParam_Volume,
    433                                kAudioUnitScope_Global, 0, &volume))
    434         return (int)lroundf(volume * 100.0f);
    435 
    436     return 0;    // error case
    437 }
    438 
    439 void AudioOutputCA::SetVolumeChannel(int channel, int volume)
    440 {
    441     // FIXME: this only sets global volume
    442     (void)channel;
    443      AudioUnitSetParameter(d->mOutputUnit, kHALOutputParam_Volume,
    444                            kAudioUnitScope_Global, 0, (volume * 0.01f), 0);
    445 }
    446 
    447418// IOProc style callback for SPDIF audio output
    448419static OSStatus RenderCallbackSPDIF(AudioDeviceID        inDevice,
    449420                                    const AudioTimeStamp *inNow,
  • mythtv/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);
  • mythtv/libs/libmyth/audiooutputjack.cpp

     
    410410
    411411    return 0;
    412412}
     413<<<<<<< .mine
     414=======
    413415
    414416
    415417/* Our Jack XRun callback.
     
    489491        chan_volumes[i] = volume;
    490492}
    491493
    492 int AudioOutputJACK::GetVolumeChannel(int channel) const
    493 {
    494     unsigned int vol = 0;
    495 
    496     if (!internal_vol)
    497         return 100;
    498 
    499     if (channel < JACK_CHANNELS_MAX)
    500         vol = chan_volumes[channel];
    501 
    502     return vol;
    503 }
    504 
    505 void AudioOutputJACK::SetVolumeChannel(int channel, int volume)
    506 {
    507     if (internal_vol && (channel < JACK_CHANNELS_MAX))
    508     {
    509         chan_volumes[channel] = volume;
    510         if (channel == 0)
    511         {
    512             // Left
    513             chan_volumes[2] = volume; // left rear
    514         }
    515         else if (channel == 1)
    516         {
    517             // Right
    518             chan_volumes[3] = volume; // right rear
    519         }
    520 
    521         // LFE and Center
    522         chan_volumes[4] = chan_volumes[5] =
    523                                     (chan_volumes[0] + chan_volumes[1]) / 2;
    524     }
    525 }
    526 
    527 
    528494/* We don't need an audio output thread for Jack
    529495  Everything handled by callbacks here
    530496  Therefore we can loose all the Start/StopOutputThread, WriteAudio, etc
  • mythtv/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);
     
    2521    AudioOutputSettings* GetOutputSettings(void);
    2622
    2723  private:
    28     void VolumeInit(void);
    29     void VolumeCleanup(void);
    30 
    3124    void SetFragSize(void);
    3225
    3326    int audiofd;
    3427    mutable int numbadioctls;
    35 
    36     // Volume related
    37     int mixerfd;
    38     int control;
    3928};
    4029
    4130#endif
  • mythtv/libs/libmyth/audiooutputbase.cpp

     
    6262    pauseaudio(false),          actually_paused(false),
    6363    was_paused(false),          unpause_when_ready(false),
    6464
    65     set_initial_vol(settings.set_initial_vol),
    6665    buffer_output_data_for_use(false),
    6766
    6867    // private
     
    7574    source_bytes_per_frame(0),
    7675    needs_upmix(false),         needs_downmix(false),
    7776    surround_mode(QUALITY_LOW), old_stretchfactor(1.0f),
    78     volume(80),                 volumeControl(NULL),
     77    volumeControl(NULL),
    7978
    8079    processing(false),
    8180
     
    116115
    117116        VBAUDIO(QString("SRC quality = %1").arg(quality_string(src_quality)));
    118117    }
     118
     119    if (gCoreContext->GetSetting("MixerDevice") == "Software:")
     120        volume_control = VolumeControlManager::GetControl("Software:");
    119121}
    120122
    121123/**
     
    426428
    427429    killaudio = pauseaudio = false;
    428430    was_paused = true;
    429     internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);
    430431
    431432    VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels")
    432433            .arg(codec_id_string((CodecID)codec))
     
    505506
    506507    // Turn on float conversion?
    507508    if (need_resampler || needs_upmix || needs_downmix ||
    508         stretchfactor != 1.0f || (internal_vol && SWVolume()) ||
     509        stretchfactor != 1.0f || (volume_control) ||
    509510        (enc && output_format != FORMAT_S16) ||
    510511        !output_settings->IsSupportedFormat(output_format))
    511512    {
     
    544545        return;
    545546    }
    546547
    547     // Only used for software volume
    548     if (set_initial_vol && internal_vol && SWVolume())
    549     {
    550         VBAUDIO("Software volume enabled");
    551         volumeControl  = gCoreContext->GetSetting("MixerControl", "PCM");
    552         volumeControl += "MixerVolume";
    553         volume = gCoreContext->GetNumSetting(volumeControl, 80);
    554     }
    555 
    556     VolumeBase::SetChannels(channels);
    557     VolumeBase::SyncVolume();
    558     VolumeBase::UpdateVolume();
    559 
    560548    VBAUDIO(QString("Audio fragment size: %1").arg(fragment_size));
    561549
    562550    audbuf_timecode = audiotime = frames_buffered = 0;
     
    835823}
    836824
    837825/**
    838  * Set the volume for software volume control
    839  */
    840 void AudioOutputBase::SetSWVolume(int new_volume, bool save)
    841 {
    842     volume = new_volume;
    843     if (save && volumeControl != NULL)
    844         gCoreContext->SaveSetting(volumeControl, volume);
    845 }
    846 
    847 /**
    848  * Get the volume for software volume control
    849  */
    850 int AudioOutputBase::GetSWVolume()
    851 {
    852     return volume;
    853 }
    854 
    855 /**
    856826 * Check that there's enough space in the audiobuffer to write the provided
    857827 * number of frames
    858828 *
     
    11001070        org_waud += nFrames * bpf;
    11011071    }
    11021072
    1103     if (internal_vol && SWVolume())
     1073    if (volume_control)
    11041074    {
    11051075        org_waud    = waud;
    11061076        int num     = len;
     1077        int volume  = volume_control->volume();
    11071078
    11081079        if (bdiff <= num)
    11091080        {
     
    13161287    raud += frag_size;
    13171288
    13181289    // Mute individual channels through mono->stereo duplication
    1319     MuteState mute_state = GetMuteState();
    1320     if (written_size && channels > 1 &&
    1321         (mute_state == kMuteLeft || mute_state == kMuteRight))
     1290    bool mute = volume_control ? volume_control->mute() : false;
     1291    if (written_size && channels > 1 && mute)
    13221292    {
    1323         AudioOutputUtil::MuteChannel(obytes << 3, channels,
    1324                                      mute_state == kMuteLeft ? 0 : 1,
     1293        AudioOutputUtil::MuteChannel(obytes << 3, channels, 1,
    13251294                                     buffer, written_size);
    13261295    }
    13271296
  • mythtv/libs/libmyth/audiooutput.cpp

     
    3939AudioOutput *AudioOutput::OpenAudio(
    4040    const QString &main_device, const QString &passthru_device,
    4141    AudioFormat format, int channels, int codec, int samplerate,
    42     AudioOutputSource source, bool set_initial_vol, bool passthru,
    43     int upmixer_startup)
     42    AudioOutputSource source, bool passthru, int upmixer_startup)
    4443{
    4544    AudioSettings settings(
    4645        main_device, passthru_device, format, channels, codec, samplerate,
    47         source, set_initial_vol, passthru, upmixer_startup);
     46        source, passthru, upmixer_startup);
    4847
    4948    return OpenAudio(settings);
    5049}
  • mythtv/libs/libmyth/libmyth.pro

     
    2424HEADERS += output.h
    2525HEADERS += settings.h
    2626HEADERS += uilistbtntype.h uitypes.h util.h mythuifilebrowser.h
    27 HEADERS += volumebase.h visual.h xmlparse.h
     27HEADERS += volumecontrol.h volumecontrolmanager.h volumecontrolsoftware.h
     28HEADERS += visual.h xmlparse.h
    2829HEADERS += mythhdd.h mythcdrom.h storagegroupeditor.h dbutil.h
    2930HEADERS += mythcommandlineparser.h mythterminal.h
    3031HEADERS += mythhttppool.h mythhttphandler.h
     
    5152SOURCES += output.cpp
    5253SOURCES += settings.cpp
    5354SOURCES += uilistbtntype.cpp uitypes.cpp util.cpp mythuifilebrowser.cpp
    54 SOURCES += volumebase.cpp xmlparse.cpp
     55SOURCES += volumecontrolmanager.cpp volumecontrolsoftware.cpp
     56SOURCES += xmlparse.cpp
    5557SOURCES += mythhdd.cpp mythcdrom.cpp storagegroupeditor.cpp dbutil.cpp
    5658SOURCES += mythcommandlineparser.cpp mythterminal.cpp
    5759SOURCES += mythhttppool.cpp mythhttphandler.cpp
     
    9395# Install headers so that plugins can compile independently
    9496inc.path = $${PREFIX}/include/mythtv/
    9597inc.files  = dialogbox.h mythcontext.h
    96 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h
     98inc.files += mythwidgets.h remotefile.h oldsettings.h
    9799inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h
    98100inc.files += audiooutput.h audiosettings.h audiooutputsettings.h util.h
    99101inc.files += inetcomms.h mythmedia.h mythcdrom.h mythwizard.h schemawizard.h dbutil.h
    100102inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h
    101 inc.files += visual.h volumebase.h output.h langsettings.h
     103inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h
    102104inc.files += mythexp.h mythpluginapi.h storagegroupeditor.h
    103105inc.files += mythconfigdialogs.h mythconfiggroups.h
    104106inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h
     
    117119
    118120using_oss {
    119121    DEFINES += USING_OSS
    120     SOURCES += audiooutputoss.cpp
    121     HEADERS += audiooutputoss.h
     122    SOURCES += audiooutputoss.cpp volumecontroloss.cpp
     123    HEADERS += audiooutputoss.h volumecontroloss.h
    122124    LIBS += $$OSS_LIBS
    123125}
    124126
     
    146148
    147149mingw {
    148150    DEFINES += USING_MINGW
    149     SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp
    150     HEADERS += mediamonitor-windows.h   audiooutputwin.h   audiooutputdx.h
    151     LIBS += -lpthread -lwinmm -lws2_32
     151    SOURCES += mediamonitor-windows.cpp
     152    HEADERS += mediamonitor-windows.h
     153    SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp
     154    HEADERS += audiooutputwin.h   audiooutputdx.h   volumecontrolendpoint.h
     155    LIBS += -lpthread -lwinmm -lws2_32 -lole32
    152156}
    153157
    154158macx {
    155     HEADERS += audiooutputca.h
    156     SOURCES += audiooutputca.cpp
     159    DEFINES += USE_COREAUDIO
     160    HEADERS += audiooutputca.h volumecontrolcoreaudio.h
     161    SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp
    157162    HEADERS += mythcdrom-darwin.h
    158163    SOURCES += mythcdrom-darwin.cpp
    159164
     
    193198
    194199using_alsa {
    195200    DEFINES += USE_ALSA
    196     HEADERS += audiooutputalsa.h
    197     SOURCES += audiooutputalsa.cpp
     201    HEADERS += audiooutputalsa.h volumecontrolalsa.h
     202    SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp
    198203    LIBS += $$ALSA_LIBS
    199204}
    200205
  • mythtv/libs/libmyth/audiosettings.h

     
    3333        int               codec,
    3434        int               samplerate,
    3535        AudioOutputSource source,
    36         bool              set_initial_vol,
    3736        bool              use_passthru,
    3837        int               upmixer_startup = 0);
    3938
     
    6059    int               channels;
    6160    int               codec;
    6261    int               samplerate;
    63     bool              set_initial_vol;
    6462    bool              use_passthru;
    6563    AudioOutputSource source;
    6664    int               upmixer;
  • mythtv/libs/libmyth/audiooutputca.h

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

     
    3232
    3333AudioOutputOSS::AudioOutputOSS(const AudioSettings &settings) :
    3434    AudioOutputBase(settings),
    35     audiofd(-1), numbadioctls(0),
    36     mixerfd(-1), control(SOUND_MIXER_VOLUME)
     35    audiofd(-1), numbadioctls(0)
    3736{
    3837    // Set everything up
    3938    InitSettings(settings);
     
    221220    else
    222221        OERROR("Unable to get audio card capabilities");
    223222
    224     // Setup volume control
    225     if (internal_vol)
    226         VolumeInit();
    227 
    228223    // Device opened successfully
    229224    return true;
    230225}
     
    235230        close(audiofd);
    236231
    237232    audiofd = -1;
    238 
    239     VolumeCleanup();
    240233}
    241234
    242235
     
    276269    return soundcard_buffer;
    277270}
    278271
    279 void AudioOutputOSS::VolumeInit()
    280 {
    281     mixerfd = -1;
    282     int volume = 0;
    283 
    284     QString device = gCoreContext->GetSetting("MixerDevice", "/dev/mixer");
    285     if (device.toLower() == "software")
    286         return;
    287 
    288     QByteArray dev = device.toAscii();
    289     mixerfd = open(dev.constData(), O_RDONLY);
    290 
    291     QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");
    292 
    293     if (controlLabel == "Master")
    294         control = SOUND_MIXER_VOLUME;
    295     else
    296         control = SOUND_MIXER_PCM;
    297 
    298     if (mixerfd < 0)
    299     {
    300         VBERROR(QString("Unable to open mixer: '%1'").arg(device));
    301         return;
    302     }
    303 
    304     if (set_initial_vol)
    305     {
    306         int tmpVol;
    307         volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);
    308         tmpVol = (volume << 8) + volume;
    309         int ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);
    310         if (ret < 0)
    311             VBERROR(QString("Error Setting initial Master Volume") + ENO);
    312 
    313         volume = gCoreContext->GetNumSetting("PCMMixerVolume", 80);
    314         tmpVol = (volume << 8) + volume;
    315         ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);
    316         if (ret < 0)
    317             VBERROR(QString("Error setting initial PCM Volume") + ENO);
    318     }
    319 }
    320 
    321 void AudioOutputOSS::VolumeCleanup()
    322 {
    323     if (mixerfd >= 0)
    324     {
    325         close(mixerfd);
    326         mixerfd = -1;
    327     }
    328 }
    329 
    330 int AudioOutputOSS::GetVolumeChannel(int channel) const
    331 {
    332     int volume=0;
    333     int tmpVol=0;
    334 
    335     if (mixerfd <= 0)
    336         return 100;
    337 
    338     int ret = ioctl(mixerfd, MIXER_READ(control), &tmpVol);
    339     if (ret < 0)
    340     {
    341         VBERROR(QString("Error reading volume for channel %1").arg(channel));
    342         return 0;
    343     }
    344 
    345     if (channel == 0)
    346         volume = tmpVol & 0xff; // left
    347     else if (channel == 1)
    348         volume = (tmpVol >> 8) & 0xff; // right
    349     else
    350         VBERROR("Invalid channel. Only stereo volume supported");
    351 
    352     return volume;
    353 }
    354 
    355 void AudioOutputOSS::SetVolumeChannel(int channel, int volume)
    356 {
    357     if (channel > 1)
    358     {
    359         // Don't support more than two channels!
    360         VBERROR(QString("Error setting channel %1. Only 2 ch volume supported")
    361                 .arg(channel));
    362         return;
    363     }
    364 
    365     if (volume > 100)
    366         volume = 100;
    367     if (volume < 0)
    368         volume = 0;
    369 
    370     if (mixerfd >= 0)
    371     {
    372         int tmpVol = 0;
    373         if (channel == 0)
    374             tmpVol = (GetVolumeChannel(1) << 8) + volume;
    375         else
    376             tmpVol = (volume << 8) + GetVolumeChannel(0);
    377 
    378         int ret = ioctl(mixerfd, MIXER_WRITE(control), &tmpVol);
    379         if (ret < 0)
    380             VBERROR(QString("Error setting volume on channel %1").arg(channel));
    381     }
    382 }
    383 
  • mythtv/libs/libmyth/audiooutputdx.cpp

     
    483483                    | DSBCAPS_GLOBALFOCUS          // Allows background playing
    484484                    | DSBCAPS_LOCHARDWARE;         // Needed for 5.1 on emu101k
    485485
    486     if (!m_UseSPDIF)
    487         dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME;     // Allow volume control
    488 
    489486    dsbdesc.dwBufferBytes = soundcard_buffer_size; // buffer size
    490487    dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf;
    491488
     
    556553    return buffered;
    557554}
    558555
    559 int AudioOutputDX::GetVolumeChannel(int channel) const
    560 {
    561     HRESULT dsresult;
    562     long dxVolume = 0;
    563     int volume;
    564 
    565     if (m_UseSPDIF)
    566         return 100;
    567 
    568     dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);
    569     volume = (int)(pow(10,(float)dxVolume/20)*100);
    570 
    571     if (dsresult != DS_OK)
    572     {
    573         VBERROR(QString("Failed to get volume %1").arg(dxVolume));
    574         return volume;
    575     }
    576 
    577     VBAUDIO(QString("Got volume %1").arg(volume));
    578     return volume;
    579 }
    580 
    581 void AudioOutputDX::SetVolumeChannel(int channel, int volume)
    582 {
    583     HRESULT dsresult;
    584     float dbAtten = 20 * log10((float)volume/100);
    585     long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);
    586 
    587     if (m_UseSPDIF)
    588         return;
    589 
    590     // dxVolume is attenuation in 100ths of a decibel
    591     dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);
    592 
    593     if (dsresult != DS_OK)
    594     {
    595         VBERROR(QString("Failed to set volume %1").arg(dxVolume));
    596         return;
    597     }
    598 
    599     VBAUDIO(QString("Set volume %1").arg(dxVolume));
    600 }
    601 
    602556/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • mythtv/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:
  • mythtv/libs/libmyth/audiooutput.h

     
    77#include "audiosettings.h"
    88#include "audiooutputsettings.h"
    99#include "mythcorecontext.h"
    10 #include "volumebase.h"
    1110#include "output.h"
    1211
    13 class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
     12class MPUBLIC AudioOutput : public OutputListeners
    1413{
    1514 public:
    1615    class AudioDeviceConfig
     
    3837    static AudioOutput *OpenAudio(
    3938        const QString &audiodevice, const QString &passthrudevice,
    4039        AudioFormat format, int channels, int codec, int samplerate,
    41         AudioOutputSource source, bool set_initial_vol, bool passthru,
    42         int upmixer_startup = 0);
     40        AudioOutputSource source, bool passthru, int upmixer_startup = 0);
    4341    static AudioOutput *OpenAudio(AudioSettings &settings,
    4442                                  bool willsuspendpa = true);
    4543    static AudioOutput *OpenAudio(
     
    4846        bool willsuspendpa = true);
    4947
    5048    AudioOutput() :
    51         VolumeBase(),             OutputListeners(),
     49        OutputListeners(),
    5250        lastError(QString::null), lastWarn(QString::null) {}
    5351
    5452    virtual ~AudioOutput();
  • mythtv/libs/libmyth/volumecontrolmanager.h

     
     1#ifndef VOLUMECONTROLMANAGER
     2#define VOLUMECONTROLMANAGER
     3
     4#include "volumecontrol.h"
     5
     6#include "mythexp.h"
     7
     8#include <QHash>
     9#include <QSharedPointer>
     10#include <QString>
     11
     12class MPUBLIC VolumeControlManager
     13{
     14public:
     15    static QHash<QString, QString> Enumerate();
     16    static QSharedPointer<VolumeControl> GetControl(QString device);
     17};
     18
     19#endif // VOLUMECONTROLMANAGER
  • mythtv/libs/libmyth/volumecontrolendpoint.h

     
     1#ifndef VOLUMECONTROLENDPOINT
     2#define VOLUMECONTROLENDPOINT
     3
     4#include "volumecontrol.h"
     5
     6#include <QHash>
     7#include <QAtomicInt>
     8
     9#include <rpcsal.h>
     10#include <endpointvolume.h>
     11
     12
     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
  • mythtv/libs/libmyth/audiooutputdx.h

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

     
    1717    AudioOutputALSA(const AudioSettings &settings);
    1818    virtual ~AudioOutputALSA();
    1919
    20     // Volume control
    21     virtual int GetVolumeChannel(int channel) const; // Returns 0-100
    22     virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol
    2320    static QMap<QString, QString> *GetALSADevices(const char *type);
    2421
    2522  protected:
     
    3835    inline int SetParameters(snd_pcm_t *handle, snd_pcm_format_t format,
    3936                             uint channels, uint rate, uint buffer_time,
    4037                             uint period_time);
    41     // Volume related
    42     bool OpenMixer(void);
    4338
    4439  private:
    4540    snd_pcm_t   *pcm_handle;
     
    4944    QMutex       killAudioLock;
    5045    snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*,
    5146                                        snd_pcm_uframes_t);
    52     struct {
    53         QString            device;
    54         QString            control;
    55         snd_mixer_t*       handle;
    56         snd_mixer_elem_t*  elem;
    57         long               volmin;
    58         long               volmax;
    59         long               volrange;
    60     } m_mixer;
    61 
    6247};
    6348#endif
  • mythtv/libs/libmyth/volumecontroloss.cpp

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

     
    2828#include "iso639.h"
    2929#include "playbackbox.h"
    3030#include "globalsettings.h"
     31#include "libmyth/volumecontrolmanager.h"
    3132#include "recordingprofile.h"
    3233#include "mythxdisplay.h"
    3334#include "DisplayRes.h"
     
    464465    return gc;
    465466}
    466467
    467 static HostCheckBox *MythControlsVolume()
    468 {
    469     HostCheckBox *gc = new HostCheckBox("MythControlsVolume");
    470     gc->setLabel(QObject::tr("Use internal volume controls"));
    471     gc->setValue(true);
    472     gc->setHelpText(QObject::tr("MythTV can control the PCM and master "
    473                     "mixer volume. If you prefer to control the volume "
    474                     "externally (for example, using your amplifier) or to "
    475                     "use an external mixer program, disable this option."));
    476     return gc;
    477 }
    478 
    479468static HostComboBox *MixerDevice()
    480469{
    481470    HostComboBox *gc = new HostComboBox("MixerDevice", true);
    482471    gc->setLabel(QObject::tr("Mixer device"));
     472    gc->addSelection(QObject::tr("Disabled"), QString());
    483473
    484 #ifdef USING_OSS
    485     QDir dev("/dev", "mixer*", QDir::Name, QDir::System);
    486     gc->fillSelectionsFromDir(dev);
     474    QHash<QString, QString> controls = VolumeControlManager::Enumerate();
    487475
    488     dev.setPath("/dev/sound");
    489     if (dev.exists())
     476    for (QHash<QString, QString>::const_iterator control = controls.begin();
     477         control != controls.end(); ++control)
    490478    {
    491         gc->fillSelectionsFromDir(dev);
     479        gc->addSelection(control.value(), control.key());
    492480    }
    493 #endif
    494 #ifdef USING_ALSA
    495     gc->addSelection("ALSA:default", "ALSA:default");
    496 #endif
    497 #ifdef USING_MINGW
    498     gc->addSelection("DirectX:", "DirectX:");
    499     gc->addSelection("Windows:", "Windows:");
    500 #endif
    501 #if !defined(USING_MINGW)
    502     gc->addSelection("software", "software");
    503     gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" "
    504                     "lets MythTV control the volume of all audio at the "
    505                     "expense of a slight quality loss."));
    506 #endif
    507481
    508482    return gc;
    509483}
    510484
    511 static const char* MixerControlControls[] = { "PCM",
    512                                               "Master" };
    513 
    514 static HostComboBox *MixerControl()
    515 {
    516     HostComboBox *gc = new HostComboBox("MixerControl", true);
    517     gc->setLabel(QObject::tr("Mixer controls"));
    518     for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);
    519          ++i)
    520     {
    521         gc->addSelection(QObject::tr(MixerControlControls[i]),
    522                          MixerControlControls[i]);
    523     }
    524 
    525     gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));
    526     return gc;
    527 }
    528 
    529 static HostSlider *MixerVolume()
    530 {
    531     HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);
    532     gs->setLabel(QObject::tr("Master mixer volume"));
    533     gs->setValue(70);
    534     gs->setHelpText(QObject::tr("Initial volume for the Master mixer. "
    535                     "This affects all sound created by the audio device. "
    536                     "Note: Do not set this too low."));
    537     return gs;
    538 }
    539 
    540 static HostSlider *PCMVolume()
    541 {
    542     HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);
    543     gs->setLabel(QObject::tr("PCM mixer volume"));
    544     gs->setValue(70);
    545     gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "
    546                     "volume keys in MythTV will adjust this parameter."));
    547     return gs;
    548 }
    549 
    550485static HostCheckBox *DecodeExtraAudio()
    551486{
    552487    HostCheckBox *gc = new HostCheckBox("DecodeExtraAudio");
     
    34113346    return gs;
    34123347}
    34133348
    3414 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup
     3349static ConfigurationGroup *AudioMixerSettingsGroup()
    34153350{
    3416   public:
    3417     AudioMixerSettingsGroup() :
    3418         TriggeredConfigurationGroup(false, true, false, false)
    3419     {
    3420         setLabel(QObject::tr("Audio Mixer"));
    3421         setUseLabel(false);
     3351    ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false);
     3352   
     3353    vcg->setLabel(QObject::tr("Audio Mixer"));
     3354    vcg->setUseLabel(false);
    34223355
    3423         Setting *volumeControl = MythControlsVolume();
    3424         addChild(volumeControl);
     3356    vcg->addChild(MixerDevice());
    34253357
    3426         // Mixer settings
    3427         ConfigurationGroup *settings =
    3428             new VerticalConfigurationGroup(false, true, false, false);
    3429         settings->addChild(MixerDevice());
    3430         settings->addChild(MixerControl());
    3431         settings->addChild(MixerVolume());
    3432         settings->addChild(PCMVolume());
     3358    return vcg;
     3359}
    34333360
    3434         ConfigurationGroup *dummy =
    3435             new VerticalConfigurationGroup(false, true, false, false);
    3436 
    3437         // Show Mixer config only if internal volume controls enabled
    3438         setTrigger(volumeControl);
    3439         addTarget("0", dummy);
    3440         addTarget("1", settings);
    3441     }
    3442 };
    3443 
    34443361static HostComboBox *MythLanguage()
    34453362{
    34463363    HostComboBox *gc = new HostComboBox("Language");
     
    41244041
    41254042    addChild(new AudioConfigSettings());
    41264043
    4127     addChild(new AudioMixerSettingsGroup());
     4044    addChild(AudioMixerSettingsGroup());
    41284045
    41294046    VerticalConfigurationGroup *general =
    41304047        new VerticalConfigurationGroup(false, true, false, false);
  • mythtv/programs/mythtranscode/transcode.cpp

     
    137137        return last_audiotime;
    138138    }
    139139
    140     virtual int GetVolumeChannel(int) const
    141     {
    142         // Do nothing
    143         return 100;
    144     }
    145     virtual void SetVolumeChannel(int, int)
    146     {
    147         // Do nothing
    148     }
    149     virtual void SetVolumeAll(int)
    150     {
    151         // Do nothing
    152     }
    153     virtual uint GetCurrentVolume(void) const
    154     {
    155         // Do nothing
    156         return 100;
    157     }
    158     virtual void SetCurrentVolume(int)
    159     {
    160         // Do nothing
    161     }
    162     virtual void AdjustCurrentVolume(int)
    163     {
    164         // Do nothing
    165     }
    166     virtual void SetMute(bool)
    167     {
    168         // Do nothing
    169     }
    170     virtual void ToggleMute(void)
    171     {
    172         // Do nothing
    173     }
    174     virtual MuteState GetMuteState(void) const
    175     {
    176         // Do nothing
    177         return kMuteOff;
    178     }
    179     virtual MuteState IterateMutedChannels(void)
    180     {
    181         // Do nothing
    182         return kMuteOff;
    183     }
    184140    virtual bool ToggleUpmix(void)
    185141    {
    186142        // Do nothing
    187143        return false;
    188144    }
    189145
    190     virtual void SetSWVolume(int new_volume, bool save)
    191     {
    192         // Do nothing
    193         return;
    194     }
    195     virtual int GetSWVolume(void)
    196     {
    197         // Do nothing
    198         return 100;
    199     }
    200 
    201146    //  These are pure virtual in AudioOutput, but we don't need them here
    202147    virtual void bufferOutputData(bool){ return; }
    203148    virtual int readOutputData(unsigned char*, int ){ return 0; }