Ticket #7517: volume_control_trunk_r25559.patch

File volume_control_trunk_r25559.patch, 133.6 KB (added by mythtv@…, 14 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()),
     
    11741178    if (volume_control && gPlayer->getOutput())
    11751179    {
    11761180        if (up_or_down)
    1177             gPlayer->getOutput()->AdjustCurrentVolume(2);
     1181            gPlayer->incVolume();
    11781182        else
    1179             gPlayer->getOutput()->AdjustCurrentVolume(-2);
     1183            gPlayer->decVolume();
    11801184        showVolume(true);
    11811185    }
    11821186}
     
    11971201{
    11981202    if (volume_control && gPlayer->getOutput())
    11991203    {
    1200         gPlayer->getOutput()->ToggleMute();
     1204        gPlayer->toggleMute();
    12011205        showVolume(true);
    12021206    }
    12031207}
     
    12391243        {
    12401244            if (on_or_off)
    12411245            {
    1242                 volume_status->SetUsed(gPlayer->getOutput()->GetCurrentVolume());
     1246                volume_status->SetUsed(gPlayer->getVolume());
    12431247                volume_status->SetOrder(0);
    12441248                volume_status->refresh();
    12451249                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

     
    44// mythtv
    55#include <mythdialogs.h>
    66#include <audiooutput.h>
     7#include <libmyth/volumecontrolmanager.h>
    78#include <mythobservable.h>
    89
    910// mythmusic
     
    5657
    5758    void setCDDevice(const QString &dev) { m_CDdevice = dev; }
    5859
    59     void      toggleMute(void);
    60     MuteState getMuteState(void) const;
    61     bool      isMuted(void) const { return getMuteState() == kMuteAll; }
     60    void toggleMute(void);
     61    bool isMuted(void) const;
    6262
    6363    void setVolume(int volume);
    6464    void incVolume(void);
     
    182182
    183183    Metadata     m_displayMetadata;
    184184
     185    QSharedPointer<VolumeControl> volume_control; ///< Volume control interface
     186
    185187    AudioOutput    *m_output;
    186188    DecoderHandler *m_decoderHandler;
    187189
  • mythplugins/mythmusic/mythmusic/musicplayer.cpp

     
    9090
    9191    m_autoShowPlayer = (gCoreContext->GetNumSetting("MusicAutoShowPlayer", 1) > 0);
    9292
     93    volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice"));
     94
    9395    gCoreContext->addListener(this);
    9496}
    9597
     
    306308    // TODO: Error checking that device is opened correctly!
    307309    m_output = AudioOutput::OpenAudio(
    308310                   adevice, pdevice, FORMAT_S16, 2, 0, 44100,
    309                    AUDIOOUTPUT_MUSIC, true, false,
     311                   AUDIOOUTPUT_MUSIC, false,
    310312                   gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1);
    311313
    312314    m_output->setBufferSize(256 * 1024);
     
    881883
    882884void MusicPlayer::incVolume()
    883885{
    884     if (getOutput())
     886    if (volume_control)
    885887    {
    886         getOutput()->AdjustCurrentVolume(2);
     888        volume_control->increaseVolume();
    887889        sendVolumeChangedEvent();
    888890    }
    889891}
    890892
    891893void MusicPlayer::decVolume()
    892894{
    893     if (getOutput())
     895    if (volume_control)
    894896    {
    895         getOutput()->AdjustCurrentVolume(-2);
     897        volume_control->decreaseVolume();
    896898        sendVolumeChangedEvent();
    897899    }
    898900}
    899901
    900902void MusicPlayer::setVolume(int volume)
    901903{
    902     if (getOutput())
     904    if (volume_control)
    903905    {
    904         getOutput()->SetCurrentVolume(volume);
     906        volume_control->setVolume(volume);
    905907        sendVolumeChangedEvent();
    906908    }
    907909}
    908910
    909911uint MusicPlayer::getVolume(void) const
    910912{
    911     if (m_output)
    912         return m_output->GetCurrentVolume();
     913    if (volume_control)
     914        return volume_control->volume();
    913915    return 0;
    914916}
    915917
    916918void MusicPlayer::toggleMute(void)
    917919{
    918     if (m_output)
     920    if (volume_control)
    919921    {
    920         m_output->ToggleMute();
     922        volume_control->setMute(!volume_control->mute());
    921923        sendVolumeChangedEvent();
    922924    }
    923925}
    924926
    925 MuteState MusicPlayer::getMuteState(void) const
     927bool MusicPlayer::isMuted(void) const
    926928{
    927     if (m_output)
    928         return m_output->GetMuteState();
    929     return kMuteAll;
     929    if (volume_control)
     930        return volume_control->mute();
     931    return true;
    930932}
    931933
    932934void 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
     
    174178    bool show_album_art;
    175179    bool show_whole_tree;
    176180    bool keyboard_accelerators;
    177     bool volume_control;
     181    QSharedPointer<VolumeControl> volume_control; ///< Volume control interface
    178182
    179183    QString exit_action;
    180184
  • mythtv/configure

     
    639639    eval "$var=\"\$$var $*\""
    640640}
    641641
     642prepend(){
     643    var=$1
     644    shift
     645    flags_saved && eval "SAVE_$var=\"$* \$SAVE_$var\""
     646    eval "$var=\"$* \$$var\""
     647}
     648
    642649append_uniq(){
    643650    log append_uniq "$@"
    644651    var=$1
     
    36583665    { { ! enabled audio_alsa || die "ERROR: Alsa >= 1.0.16 required"; } &&
    36593666    disable audio_alsa; }
    36603667
     3668# OSS probe
     3669if ! disabled audio_oss ; then
     3670    if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h &&
     3671       check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then
     3672        disable soundcard_h
     3673        enable sys_soundcard_h
     3674        prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include"
     3675    elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h &&
     3676       check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then
     3677        disable soundcard_h
     3678        enable sys_soundcard_h
     3679        prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include"
     3680    else
     3681        if enabled soundcard_h ; then
     3682            check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" &&
     3683            enable  audio_oss ||
     3684            disable audio_oss
     3685        elif enabled sys_soundcard_h ; then
     3686            check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" &&
     3687            enable  audio_oss ||
     3688            disable audio_oss
     3689        fi
     3690    fi
     3691fi
    36613692
    36623693# JACK probe
    36633694! disabled audio_jack &&
  • mythtv/libs/libmythtv/NuppelVideoPlayer.cpp

     
    153153    return 0;
    154154}
    155155
    156 NuppelVideoPlayer::NuppelVideoPlayer(bool muted)
     156NuppelVideoPlayer::NuppelVideoPlayer()
    157157    : decoder(NULL),                decoder_change_lock(QMutex::Recursive),
    158158      videoOutput(NULL),            player_ctx(NULL),
    159159      decoderThread(NULL),          playerThread(NULL),
     
    213213      // OSD stuff
    214214      osd(NULL), reinit_osd(false),
    215215      // Audio
    216       audio(this, muted),
     216      audio(this),
    217217      // Picture-in-Picture stuff
    218218      pip_active(false),            pip_visible(true),
    219219      // Filters
  • mythtv/libs/libmythtv/avformatdecoder.cpp

     
    245245      itv(NULL),
    246246      // Audio
    247247      audioSamples(NULL),
    248       internal_vol(false),
    249248      disable_passthru(false),
    250249      dummy_frame(NULL),
    251250      // DVD
     
    266265    av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR);
    267266    av_log_set_callback(myth_av_log);
    268267
    269     internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);
    270268
    271269    audioIn.sample_size = -32; // force SetupAudioStream to run once
    272270    itv = GetPlayer()->GetInteractiveTV();
     
    43764374    bool passthru = false;
    43774375
    43784376    if (ctx->codec_id == CODEC_ID_AC3)
    4379         passthru = m_audio->CanAC3() &&
    4380             ctx->channels >= (int)m_audio->GetMaxChannels() &&
    4381                    !internal_vol;
     4377        passthru = m_audio->CanAC3();
    43824378    else if (ctx->codec_id == CODEC_ID_DTS)
    4383         passthru = m_audio->CanDTS() && !internal_vol;
     4379        passthru = m_audio->CanDTS();
    43844380
    43854381    passthru &= m_audio->CanPassthrough();
    43864382    passthru &= !transcoding && !disable_passthru;
  • mythtv/libs/libmythtv/mythbdplayer.h

     
    66class MythBDPlayer : public MythPlayer
    77{
    88  public:
    9     MythBDPlayer(bool muted = false);
    109    virtual int     GetNumChapters(void);
    1110    virtual int     GetCurrentChapter(void);
    1211    virtual void    GetChapterTimes(QList<long long> &times);
  • 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#include "osd.h"
     
    294294    void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*);
    295295    void ClearUDPNotifyEvents(void);
    296296
     297    void VolumeChanged(int volume);
     298    void MuteChanged(bool mute);
     299
    297300  protected:
    298301    void OSDDialogEvent(int result, QString text, QString action);
    299302
     
    492495
    493496    vector<long long> TeardownAllPlayers(PlayerContext*);
    494497    void RestartAllPlayers(PlayerContext *lctx,
    495                            const vector<long long> &pos,
    496                            MuteState mctx_mute);
     498                           const vector<long long> &pos);
    497499    void RestartMainPlayer(PlayerContext *mctx);
    498500
    499501    void PxPToggleView(  PlayerContext *actx, bool wantPBP);
     
    722724    /// Picture attribute to modify (on arrow left or right)
    723725    PictureAttribute  adjustingPictureAttribute;
    724726
     727    QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface
     728
    725729    // Ask Allow state
    726730    QMap<QString,AskProgramInfo> askAllowPrograms;
    727731    QMutex                       askAllowLock;
  • mythtv/libs/libmythtv/mythdvdplayer.h

     
    66class MythDVDPlayer : public MythPlayer
    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

     
    44#define LOC     QString("BDPlayer: ")
    55#define LOC_ERR QString("BDPlayer error: ")
    66
    7 MythBDPlayer::MythBDPlayer(bool muted) : MythPlayer(muted)
    8 {
    9 }
    107
    118int MythBDPlayer::GetNumChapters(void)
    129{
  • mythtv/libs/libmythtv/mythplayer.h

     
    77#include <QEvent>
    88
    99#include "playercontext.h"
    10 #include "volumebase.h"
    1110#include "audiooutputsettings.h"
    1211#include "RingBuffer.h"
    1312#include "osd.h"
     
    120119    friend class DecoderThread;
    121120
    122121  public:
    123     MythPlayer(bool muted = false);
     122    MythPlayer();
    124123   ~MythPlayer();
    125124
    126125    // Initialization
     
    135134    bool IsEmbedding(void);
    136135    void WindowResized(const QSize &new_size);
    137136
    138     // Audio Sets
    139     uint AdjustVolume(int change)           { return audio.AdjustVolume(change); }
    140     bool SetMuted(bool mute)                { return audio.SetMuted(mute);       }
    141     MuteState SetMuteState(MuteState state) { return audio.SetMuteState(state);  }
    142     MuteState IncrMuteState(void)           { return audio.IncrMuteState();      }
    143 
    144137    // Sets
    145138    void SetPlayerInfo(TV             *tv,
    146139                       QWidget        *widget,
     
    189182    float   GetFrameRate(void) const          { return video_frame_rate; }
    190183
    191184    bool    IsAudioNeeded(void) { return !using_null_videoout && player_ctx->IsAudioNeeded(); }
    192     uint    GetVolume(void) { return audio.GetVolume(); }
    193185    int     GetSecondsBehind(void) const;
    194186    AspectOverrideMode GetAspectOverride(void) const;
    195187    AdjustFillMode     GetAdjustFill(void) const;
    196     MuteState          GetMuteState(void) { return audio.GetMuteState(); }
    197188
    198189    int     GetFFRewSkip(void) const          { return ffrew_skip; }
    199190    AudioPlayer* GetAudio(void)               { return &audio; }
     
    224215    bool    HasAudioOut(void) const           { return audio.HasAudioOut(); }
    225216    bool    IsPIPActive(void) const           { return pip_active; }
    226217    bool    IsPIPVisible(void) const          { return pip_visible; }
    227     bool    IsMuted(void)                     { return audio.IsMuted(); }
    228218    bool    UsingNullVideo(void) const { return using_null_videoout; }
    229219    bool    HasTVChainNext(void) const;
    230220
  • mythtv/libs/libmythtv/audioplayer.cpp

     
    44
    55#define LOC QString("AudioPlayer: ")
    66
    7 AudioPlayer::AudioPlayer(MythPlayer *parent, bool muted)
     7AudioPlayer::AudioPlayer(MythPlayer *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)
     
    153148    m_lock.unlock();
    154149}
    155150
    156 uint AudioPlayer::GetVolume(void)
    157 {
    158     uint res = 0;
    159     m_lock.lock();
    160     if (m_audioOutput)
    161         res = m_audioOutput->GetCurrentVolume();
    162     m_lock.unlock();
    163     return res;
    164 }
    165 
    166151void AudioPlayer::SetAudioInfo(const QString &main_device,
    167152                               const QString &passthru_device,
    168153                               uint           samplerate)
     
    199184    m_lock.unlock();
    200185}
    201186
    202 bool AudioPlayer::SetMuted(bool mute)
    203 {
    204     QMutexLocker lock(&m_lock);
    205     bool is_muted = IsMuted();
    206 
    207     if (m_audioOutput && !is_muted && mute &&
    208         (kMuteAll == SetMuteState(kMuteAll)))
    209     {
    210         VERBOSE(VB_AUDIO, "muting sound " <<IsMuted());
    211         return true;
    212     }
    213     else if (m_audioOutput && is_muted && !mute &&
    214              (kMuteOff == SetMuteState(kMuteOff)))
    215     {
    216         VERBOSE(VB_AUDIO, "unmuting sound "<<IsMuted());
    217         return true;
    218     }
    219 
    220     VERBOSE(VB_AUDIO, "not changing sound mute state "<<IsMuted());
    221 
    222     return false;
    223 }
    224 
    225 MuteState AudioPlayer::SetMuteState(MuteState mstate)
    226 {
    227     QMutexLocker lock(&m_lock);
    228     if (m_audioOutput)
    229         return m_audioOutput->SetMuteState(mstate);
    230     return kMuteAll;
    231 }
    232 
    233 MuteState AudioPlayer::IncrMuteState(void)
    234 {
    235     QMutexLocker lock(&m_lock);
    236     MuteState mstate = kMuteAll;
    237     if (m_audioOutput)
    238         mstate = SetMuteState(VolumeBase::NextMuteState(GetMuteState()));
    239     return mstate;
    240 }
    241 
    242 MuteState AudioPlayer::GetMuteState(void)
    243 {
    244     QMutexLocker lock(&m_lock);
    245     if (m_audioOutput)
    246         return m_audioOutput->GetMuteState();
    247     return kMuteAll;
    248 }
    249 
    250 uint AudioPlayer::AdjustVolume(int change)
    251 {
    252     QMutexLocker lock(&m_lock);
    253     if (m_audioOutput)
    254         m_audioOutput->AdjustCurrentVolume(change);
    255     return GetVolume();
    256 }
    257 
    258187long long AudioPlayer::GetAudioTime(void)
    259188{
    260189    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   : MythPlayer(muted), hidedvdbutton(true),
     11MythDVDPlayer::MythDVDPlayer()
     12  : hidedvdbutton(true),
    1313    dvd_stillframe_showing(false), need_change_dvd_track(0)
    1414{
    1515}
  • mythtv/libs/libmythtv/playercontext.cpp

     
    401401
    402402bool PlayerContext::CreatePlayer(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    MythPlayer *player = NULL;
    417416    if (kState_WatchingBD  == desiredState)
    418         player = new MythBDPlayer(muted);
     417        player = new MythBDPlayer();
    419418    else if (kState_WatchingDVD == desiredState)
    420         player = new MythDVDPlayer(muted);
     419        player = new MythDVDPlayer();
    421420    else
    422         player = new MythPlayer(muted);
     421        player = new MythPlayer();
    423422
    424423    if (nohardwaredecoders)
    425424        player->DisableHardwareDecoders();
     
    471470                VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg);
    472471        }
    473472    }
    474     else if (pipState == kPBPRight)
    475         player->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

     
    10531053
    10541054    gCoreContext->addListener(this);
    10551055
     1056    volumeControl = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice"));
     1057    if (volumeControl)
     1058    {
     1059        connect(volumeControl.data(), SIGNAL(changedVolume(int)),
     1060                this, SLOT(VolumeChanged(int)), Qt::QueuedConnection);
     1061        connect(volumeControl.data(), SIGNAL(changedMute(bool)),
     1062                this, SLOT(MuteChanged(bool)), Qt::QueuedConnection);
     1063    }
     1064
     1065    VERBOSE(VB_PLAYBACK, LOC + "ctor -- end");
     1066
    10561067    QMutexLocker lock(&initFromDBLock);
    10571068    initFromDBDone = true;
    10581069    initFromDBWait.wakeAll();
     
    51455156        }
    51465157    }
    51475158
    5148     MuteState mctx_mute = kMuteOff;
    5149     mctx->LockDeletePlayer(__FILE__, __LINE__);
    5150     if (mctx->player)
    5151         mctx_mute = mctx->player->GetMuteState();
    5152     mctx->UnlockDeletePlayer(__FILE__, __LINE__);
    5153 
    51545159    vector<long long> pos = TeardownAllPlayers(mctx);
    51555160
    51565161    if (wantPBP)
     
    51685173        }
    51695174    }
    51705175
    5171     RestartAllPlayers(mctx, pos, mctx_mute);
     5176    RestartAllPlayers(mctx, pos);
    51725177
    51735178    VERBOSE(VB_PLAYBACK, LOC +
    51745179            QString("PxPToggleType() converting from %1 to %2 -- end")
     
    53125317* \brief Recreate Main and PIP windows. Could be either PIP or PBP views.
    53135318*/
    53145319void TV::RestartAllPlayers(PlayerContext *lctx,
    5315                         const vector<long long> &pos,
    5316                         MuteState mctx_mute)
     5320                        const vector<long long> &pos)
    53175321{
    53185322    QString loc = LOC + QString("RestartAllPlayers(): ");
    53195323
     
    53605364            pipctx->LockDeletePlayer(__FILE__, __LINE__);
    53615365            if (pipctx->player)
    53625366            {
    5363                 pipctx->player->SetMuted(true);
    53645367                pipctx->player->JumpToFrame(pos[i]);
    53655368            }
    53665369            pipctx->UnlockDeletePlayer(__FILE__, __LINE__);
     
    53725375            ForceNextStateNone(pipctx);
    53735376        }
    53745377    }
    5375 
    5376     // If old main player had a kMuteAll | kMuteOff setting,
    5377     // apply old main player's mute setting to new main player.
    5378     mctx->LockDeletePlayer(__FILE__, __LINE__);
    5379     if (mctx->player && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))
    5380         mctx->player->SetMuteState(mctx_mute);
    5381     mctx->UnlockDeletePlayer(__FILE__, __LINE__);
    53825378}
    53835379
    53845380void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx)
     
    54065402        return;
    54075403    }
    54085404
    5409     MuteState mctx_mute = mctx->player->GetMuteState();
    54105405    mctx->deletePlayerLock.unlock();
    54115406    pipctx->deletePlayerLock.unlock();
    54125407
     
    54205415    playerActive = (ctx_index == playerActive) ?
    54215416        0 : ((ctx_index == 0) ? ctx_index : playerActive);
    54225417
    5423     RestartAllPlayers(mctx, pos, mctx_mute);
     5418    RestartAllPlayers(mctx, pos);
    54245419
    54255420    SetActive(mctx, playerActive, false);
    54265421
     
    54415436        mctx->deletePlayerLock.unlock();
    54425437        return;
    54435438    }
    5444 
    5445     MuteState mctx_mute = mctx->player->GetMuteState();
    5446 
    5447     // HACK - FIXME
    5448     // workaround muted audio when Player is re-created
    5449     mctx_mute = kMuteOff;
    5450     // FIXME - end
    54515439    mctx->deletePlayerLock.unlock();
    54525440
    54535441    vector<long long> pos = TeardownAllPlayers(mctx);
    5454     RestartAllPlayers(mctx, pos, mctx_mute);
     5442    RestartAllPlayers(mctx, pos);
    54555443    SetActive(mctx, playerActive, false);
    54565444
    54575445    VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end");
     
    62176205        if (mctx != ctx)
    62186206            PIPRemovePlayer(mctx, ctx);
    62196207
    6220         bool muted = false;
    6221         ctx->LockDeletePlayer(__FILE__, __LINE__);
    6222         if (ctx->player && ctx->player->IsMuted())
    6223             muted = true;
    6224         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    6225 
    62266208        // pause the decoder first, so we're not reading too close to the end.
    62276209        ctx->buffer->IgnoreLiveEOF(true);
    62286210        ctx->buffer->StopReads();
     
    62746256
    62756257            if (ctx->CreatePlayer(
    62766258                    this, GetMythMainWindow(), ctx->GetState(),
    6277                     mctx->embedWinID, &mctx->embedBounds, muted))
     6259                    mctx->embedWinID, &mctx->embedBounds))
    62786260            {
    62796261                ScheduleStateChange(ctx);
    62806262                ok = true;
     
    78897871
    78907872void TV::ChangeVolume(PlayerContext *ctx, bool up)
    78917873{
    7892     ctx->LockDeletePlayer(__FILE__, __LINE__);
    7893     if (!ctx->player)
     7874    if (volumeControl)
    78947875    {
    7895         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    7896         return;
     7876        if (up)
     7877            volumeControl->increaseVolume();
     7878        else
     7879            volumeControl->decreaseVolume();
    78977880    }
    7898     uint curvol = ctx->player->AdjustVolume((up) ? +2 : -2);
    7899     ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    7900 
    7901     if (!browsemode)
    7902     {
    7903         UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"),
    7904                         QString::number(curvol),
    7905                         kOSDFunctionalType_PictureAdjust, "%", curvol * 10,
    7906                         kOSDTimeout_Med);
    7907         SetUpdateOSDPosition(false);
    7908     }
    79097881}
    79107882
    79117883void TV::ToggleTimeStretch(PlayerContext *ctx)
     
    80488020
    80498021void TV::ToggleMute(PlayerContext *ctx, const bool muteIndividualChannels)
    80508022{
    8051     ctx->LockDeletePlayer(__FILE__, __LINE__);
    8052     if (!ctx->player || !ctx->player->HasAudioOut())
    8053     {
    8054         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    8055         return;
    8056     }
    8057 
    8058     MuteState mute_status;
    8059 
    8060     if (!muteIndividualChannels)
    8061     {
    8062         ctx->player->SetMuted(!ctx->player->IsMuted());
    8063         mute_status = (ctx->player->IsMuted()) ? kMuteAll : kMuteOff;
    8064     }
    8065     else
    8066     {
    8067         mute_status = ctx->player->IncrMuteState();
    8068     }
    8069     ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    8070 
    8071     QString text;
    8072 
    8073     switch (mute_status)
    8074     {
    8075         case kMuteOff:   text = tr("Mute Off"); break;
    8076         case kMuteAll:   text = tr("Mute On"); break;
    8077         case kMuteLeft:  text = tr("Left Channel Muted"); break;
    8078         case kMuteRight: text = tr("Right Channel Muted"); break;
    8079     }
    8080 
    8081     SetOSDMessage(ctx, text);
     8023    if (volumeControl)
     8024        volumeControl->setMute(!volumeControl->mute());
    80828025}
    80838026
    80848027void TV::ToggleSleepTimer(const PlayerContext *ctx)
     
    90388981        {
    90398982            value = ctx->player->getVideoOutput()->GetPictureAttribute(attr);
    90408983        }
    9041         else if (ctx->player->HasAudioOut())
     8984        else if (ctx->player->HasAudioOut() && volumeControl)
    90428985        {
    9043             value = ctx->player->GetVolume();
     8986            value = volumeControl->volume();
    90448987            title = tr("Adjust Volume");
    90458988        }
    90468989    }
     
    1194211885    ReturnPlayerLock(mctx);
    1194311886}
    1194411887
     11888void TV::VolumeChanged(int volume)
     11889{
     11890    if (!browsemode)
     11891    {
     11892        PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__);
     11893        UpdateOSDStatus(actx, tr("Adjust Volume"), tr("Volume"),
     11894                        QString::number(volume),
     11895                        kOSDFunctionalType_PictureAdjust, "%", 10 * volume);
     11896        SetUpdateOSDPosition(false);
     11897        ReturnPlayerLock(actx);
     11898    }
     11899}
     11900
     11901void TV::MuteChanged(bool mute)
     11902{
     11903    PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__);
     11904    SetOSDMessage(actx, mute ? tr("Mute On") : tr("Mute Off"));
     11905    ReturnPlayerLock(actx);
     11906}
     11907
     11908
    1194511909OSD *TV::GetOSDL(const char *file, int location)
    1194611910{
    1194711911    PlayerContext *actx = GetPlayerReadLock(-1, file, location);
  • mythtv/libs/libmythtv/playercontext.h

     
    6868    // Actions
    6969    bool CreatePlayer(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/mythplayer.cpp

     
    157157    return 0;
    158158}
    159159
    160 MythPlayer::MythPlayer(bool muted)
     160MythPlayer::MythPlayer()
    161161    : decoder(NULL),                decoder_change_lock(QMutex::Recursive),
    162162      videoOutput(NULL),            player_ctx(NULL),
    163163      decoderThread(NULL),          playerThread(NULL),
     
    217217      // OSD stuff
    218218      osd(NULL), reinit_osd(false),
    219219      // Audio
    220       audio(this, muted),
     220      audio(this),
    221221      // Picture-in-Picture stuff
    222222      pip_active(false),            pip_visible(true),
    223223      // Filters
  • mythtv/libs/libmythtv/avformatdecoder.h

     
    300300
    301301    // Audio
    302302    short int        *audioSamples;
    303     bool              internal_vol;
    304303    bool              disable_passthru;
    305304
    306305    VideoFrame       *dummy_frame;
  • mythtv/libs/libmythtv/mythcommflagplayer.h

     
    66class MPUBLIC MythCommFlagPlayer : public MythPlayer
    77{
    88  public:
    9     MythCommFlagPlayer(bool muted = false) : MythPlayer(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(MythPlayer *parent, bool muted);
     10    AudioPlayer(MythPlayer *parent);
    1111   ~AudioPlayer();
    1212
    1313    void  Reset(void);
     
    2929    bool  Pause(bool pause);
    3030    bool  IsPaused(void);
    3131    void  PauseAudioUntilBuffered(void);
    32     uint  GetVolume(void);
    33     uint  AdjustVolume(int change);
    3432    float GetStretchFactor(void) { return m_stretchfactor;   }
    3533    void  SetStretchFactor(float factor);
    3634    bool  ToggleUpmix(void);
     
    4038    uint  GetMaxChannels(void);
    4139    long long GetAudioTime(void);
    4240
    43     bool      IsMuted(void) { return GetMuteState() == kMuteAll; }
    44     bool      SetMuted(bool mute);
    45     MuteState GetMuteState(void);
    46     MuteState SetMuteState(MuteState);
    47     MuteState IncrMuteState(void);
    48 
    4941    void AddAudioData(char *buffer, int len, long long timecode);
    5042    bool GetBufferStatus(uint &fill, uint &total);
    5143
     
    5951    float        m_stretchfactor;
    6052    bool         m_passthru;
    6153    QMutex       m_lock;
    62     bool         m_muted_on_creation;
    6354    QString      m_main_device;
    6455    QString      m_passthru_device;
    6556    bool         no_audio_in;
  • mythtv/libs/libmyth/audiooutputwin.cpp

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

     
     1#include "volumecontrolmanager.h"
     2
     3#include "mythverbose.h"
     4#ifdef USE_ALSA
     5#include "volumecontrolalsa.h"
     6#endif
     7#ifdef USE_COREAUDIO
     8#include "volumecontrolcoreaudio.h"
     9#endif
     10#ifdef USING_OSS
     11#include "volumecontroloss.h"
     12#endif
     13#ifdef USING_MINGW
     14#include "volumecontrolendpoint.h"
     15#endif
     16#include "volumecontrolsoftware.h"
     17
     18
     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;
     
    172169    bool needs_downmix;
    173170    int surround_mode;
    174171    float old_stretchfactor;
    175     int volume;
     172    QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface
    176173    QString volumeControl;
    177174
    178175    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)
     
    432430        return OpenDevice();
    433431    }
    434432
    435     if (internal_vol && !OpenMixer())
    436         VBERROR("Unable to open audio mixer. Volume control disabled");
    437 
    438433    // Device opened successfully
    439434    return true;
    440435}
    441436
    442437void AudioOutputALSA::CloseDevice()
    443438{
    444     if (m_mixer.handle)
    445         snd_mixer_close(m_mixer.handle);
    446     m_mixer.handle = NULL;
    447439    if (pcm_handle)
    448440    {
    449441        snd_pcm_close(pcm_handle);
     
    711703    return 0;
    712704}
    713705
    714 int AudioOutputALSA::GetVolumeChannel(int channel) const
    715 {
    716     int retvol = 0;
    717 
    718     if (!m_mixer.elem)
    719         return retvol;
    720 
    721     snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
    722     if (!snd_mixer_selem_has_playback_channel(m_mixer.elem, chan))
    723         return retvol;
    724 
    725     long mixervol;
    726     int chk;
    727     if ((chk = snd_mixer_selem_get_playback_volume(m_mixer.elem,
    728                                                    chan,
    729                                                    &mixervol)) < 0)
    730     {
    731         VBERROR(QString("failed to get channel %1 volume, mixer %2/%3: %4")
    732                 .arg(channel).arg(m_mixer.device)
    733                 .arg(m_mixer.control)
    734                 .arg(snd_strerror(chk)));
    735     }
    736     else
    737     {
    738         retvol = (m_mixer.volrange != 0L) ? (mixervol - m_mixer.volmin) *
    739                                             100.0f / m_mixer.volrange + 0.5f
    740                                             : 0;
    741         retvol = max(retvol, 0);
    742         retvol = min(retvol, 100);
    743         VBAUDIO(QString("get volume channel %1: %2")
    744                 .arg(channel).arg(retvol));
    745     }
    746     return retvol;
    747 }
    748 
    749 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)
    750 {
    751     if (!(internal_vol && m_mixer.elem))
    752         return;
    753 
    754     long mixervol = volume * m_mixer.volrange / 100.0f - m_mixer.volmin + 0.5f;
    755     mixervol = max(mixervol, m_mixer.volmin);
    756     mixervol = min(mixervol, m_mixer.volmax);
    757 
    758     snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
    759     if (snd_mixer_selem_set_playback_volume(m_mixer.elem, chan, mixervol) < 0)
    760         VBERROR(QString("failed to set channel %1 volume").arg(channel));
    761     else
    762         VBAUDIO(QString("channel %1 volume set %2 => %3")
    763                 .arg(channel).arg(volume).arg(mixervol));
    764 }
    765 
    766 bool AudioOutputALSA::OpenMixer(void)
    767 {
    768     if (!pcm_handle)
    769     {
    770         VBERROR("mixer setup without a pcm");
    771         return false;
    772     }
    773     m_mixer.device = gCoreContext->GetSetting("MixerDevice", "default");
    774     m_mixer.device = m_mixer.device.remove(QString("ALSA:"));
    775     if (m_mixer.device.toLower() == "software")
    776         return true;
    777 
    778     m_mixer.control = gCoreContext->GetSetting("MixerControl", "PCM");
    779 
    780     QString mixer_device_tag = QString("mixer device %1").arg(m_mixer.device);
    781 
    782     int chk;
    783     if ((chk = snd_mixer_open(&m_mixer.handle, 0)) < 0)
    784     {
    785         VBERROR(QString("failed to open mixer device %1: %2")
    786                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    787         return false;
    788     }
    789 
    790     QByteArray dev_ba = m_mixer.device.toAscii();
    791     struct snd_mixer_selem_regopt regopts =
    792         {1, SND_MIXER_SABSTRACT_NONE, dev_ba.constData(), NULL, NULL};
    793 
    794     if ((chk = snd_mixer_selem_register(m_mixer.handle, &regopts, NULL)) < 0)
    795     {
    796         snd_mixer_close(m_mixer.handle);
    797         m_mixer.handle = NULL;
    798         VBERROR(QString("failed to register %1: %2")
    799                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    800         return false;
    801     }
    802 
    803     if ((chk = snd_mixer_load(m_mixer.handle)) < 0)
    804     {
    805         snd_mixer_close(m_mixer.handle);
    806         m_mixer.handle = NULL;
    807         VBERROR(QString("failed to load %1: %2")
    808                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    809         return false;
    810     }
    811 
    812     m_mixer.elem = NULL;
    813     uint elcount = snd_mixer_get_count(m_mixer.handle);
    814     snd_mixer_elem_t* elx = snd_mixer_first_elem(m_mixer.handle);
    815 
    816     for (uint ctr = 0; elx != NULL && ctr < elcount; ctr++)
    817     {
    818         QString tmp = QString(snd_mixer_selem_get_name(elx));
    819         if (m_mixer.control == tmp &&
    820             !snd_mixer_selem_is_enumerated(elx) &&
    821             snd_mixer_selem_has_playback_volume(elx) &&
    822             snd_mixer_selem_is_active(elx))
    823         {
    824             m_mixer.elem = elx;
    825             VBAUDIO(QString("found playback control %1 on %2")
    826                     .arg(m_mixer.control)
    827                     .arg(mixer_device_tag));
    828             break;
    829         }
    830         elx = snd_mixer_elem_next(elx);
    831     }
    832     if (!m_mixer.elem)
    833     {
    834         snd_mixer_close(m_mixer.handle);
    835         m_mixer.handle = NULL;
    836         VBERROR(QString("no playback control %1 found on %2")
    837                 .arg(m_mixer.control).arg(mixer_device_tag));
    838         return false;
    839     }
    840     if ((snd_mixer_selem_get_playback_volume_range(m_mixer.elem,
    841                                                    &m_mixer.volmin,
    842                                                    &m_mixer.volmax) < 0))
    843     {
    844         snd_mixer_close(m_mixer.handle);
    845         m_mixer.handle = NULL;
    846         VBERROR(QString("failed to get volume range on %1/%2")
    847                 .arg(mixer_device_tag).arg(m_mixer.control));
    848         return false;
    849     }
    850 
    851     m_mixer.volrange = m_mixer.volmax - m_mixer.volmin;
    852     VBAUDIO(QString("mixer volume range on %1/%2 - min %3, max %4, range %5")
    853             .arg(mixer_device_tag).arg(m_mixer.control)
    854             .arg(m_mixer.volmin).arg(m_mixer.volmax).arg(m_mixer.volrange));
    855     VBAUDIO(QString("%1/%2 set up successfully")
    856             .arg(mixer_device_tag)
    857             .arg(m_mixer.control));
    858 
    859     if (set_initial_vol)
    860     {
    861         int initial_vol;
    862         if (m_mixer.control == "PCM")
    863             initial_vol = gCoreContext->GetNumSetting("PCMMixerVolume", 80);
    864         else
    865             initial_vol = gCoreContext->GetNumSetting("MasterMixerVolume", 80);
    866         for (int ch = 0; ch < channels; ++ch)
    867             SetVolumeChannel(ch, initial_vol);
    868     }
    869 
    870     return true;
    871 }
    872 
    873706QMap<QString, QString> *AudioOutputALSA::GetALSADevices(const char *type)
    874707{
    875708    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

     
    308308        return false;
    309309    }
    310310
    311     if (internal_vol && set_initial_vol)
    312     {
    313         QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");
    314         controlLabel += "MixerVolume";
    315         SetCurrentVolume(gCoreContext->GetNumSetting(controlLabel, 80));
    316     }
    317 
    318311    return true;
    319312}
    320313
     
    420413    return noErr;
    421414}
    422415
    423 int AudioOutputCA::GetVolumeChannel(int channel) const
    424 {
    425     // FIXME: this only returns global volume
    426     (void)channel;
    427     Float32 volume;
    428 
    429     if (!AudioUnitGetParameter(d->mOutputUnit,
    430                                kHALOutputParam_Volume,
    431                                kAudioUnitScope_Global, 0, &volume))
    432         return (int)lroundf(volume * 100.0f);
    433 
    434     return 0;    // error case
    435 }
    436 
    437 void AudioOutputCA::SetVolumeChannel(int channel, int volume)
    438 {
    439     // FIXME: this only sets global volume
    440     (void)channel;
    441      AudioUnitSetParameter(d->mOutputUnit, kHALOutputParam_Volume,
    442                            kAudioUnitScope_Global, 0, (volume * 0.01f), 0);
    443 }
    444 
    445416// IOProc style callback for SPDIF audio output
    446417static OSStatus RenderCallbackSPDIF(AudioDeviceID        inDevice,
    447418                                    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/**
     
    393395
    394396    killaudio = pauseaudio = false;
    395397    was_paused = true;
    396     internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);
    397398
    398399    VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels")
    399400            .arg(codec_id_string((CodecID)codec))
     
    472473
    473474    // Turn on float conversion?
    474475    if (need_resampler || needs_upmix || needs_downmix ||
    475         stretchfactor != 1.0f || (internal_vol && SWVolume()) ||
     476        stretchfactor != 1.0f || (volume_control) ||
    476477        (enc && output_format != FORMAT_S16) ||
    477478        !output_settings->IsSupportedFormat(output_format))
    478479    {
     
    511512        return;
    512513    }
    513514
    514     // Only used for software volume
    515     if (set_initial_vol && internal_vol && SWVolume())
    516     {
    517         VBAUDIO("Software volume enabled");
    518         volumeControl  = gCoreContext->GetSetting("MixerControl", "PCM");
    519         volumeControl += "MixerVolume";
    520         volume = gCoreContext->GetNumSetting(volumeControl, 80);
    521     }
    522 
    523     VolumeBase::SetChannels(channels);
    524     VolumeBase::SyncVolume();
    525     VolumeBase::UpdateVolume();
    526 
    527515    VBAUDIO(QString("Audio fragment size: %1").arg(fragment_size));
    528516
    529517    audbuf_timecode = audiotime = frames_buffered = 0;
     
    802790}
    803791
    804792/**
    805  * Set the volume for software volume control
    806  */
    807 void AudioOutputBase::SetSWVolume(int new_volume, bool save)
    808 {
    809     volume = new_volume;
    810     if (save && volumeControl != NULL)
    811         gCoreContext->SaveSetting(volumeControl, volume);
    812 }
    813 
    814 /**
    815  * Get the volume for software volume control
    816  */
    817 int AudioOutputBase::GetSWVolume()
    818 {
    819     return volume;
    820 }
    821 
    822 /**
    823793 * Check that there's enough space in the audiobuffer to write the provided
    824794 * number of frames
    825795 *
     
    10671037        org_waud += nFrames * bpf;
    10681038    }
    10691039
    1070     if (internal_vol && SWVolume())
     1040    if (volume_control)
    10711041    {
    10721042        org_waud    = waud;
    10731043        int num     = len;
     1044        int volume  = volume_control->volume();
    10741045
    10751046        if (bdiff <= num)
    10761047        {
     
    12831254    raud += frag_size;
    12841255
    12851256    // Mute individual channels through mono->stereo duplication
    1286     MuteState mute_state = GetMuteState();
    1287     if (written_size && channels > 1 &&
    1288         (mute_state == kMuteLeft || mute_state == kMuteRight))
     1257    bool mute = volume_control ? volume_control->mute() : false;
     1258    if (written_size && channels > 1 && mute)
    12891259    {
    1290         AudioOutputUtil::MuteChannel(obytes << 3, channels,
    1291                                      mute_state == kMuteLeft ? 0 : 1,
     1260        AudioOutputUtil::MuteChannel(obytes << 3, channels, 1,
    12921261                                     buffer, written_size);
    12931262    }
    12941263
  • 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
     
    9294# Install headers so that plugins can compile independently
    9395inc.path = $${PREFIX}/include/mythtv/
    9496inc.files  = dialogbox.h mythcontext.h
    95 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h
     97inc.files += mythwidgets.h remotefile.h oldsettings.h
    9698inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h
    9799inc.files += audiooutput.h audiosettings.h audiooutputsettings.h util.h
    98100inc.files += inetcomms.h mythmedia.h mythcdrom.h mythwizard.h schemawizard.h dbutil.h
    99101inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h
    100 inc.files += visual.h volumebase.h output.h langsettings.h
     102inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h
    101103inc.files += mythexp.h mythpluginapi.h storagegroupeditor.h
    102104inc.files += mythconfigdialogs.h mythconfiggroups.h
    103105inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h
     
    116118
    117119using_oss {
    118120    DEFINES += USING_OSS
    119     SOURCES += audiooutputoss.cpp
    120     HEADERS += audiooutputoss.h
     121    SOURCES += audiooutputoss.cpp volumecontroloss.cpp
     122    HEADERS += audiooutputoss.h volumecontroloss.h
    121123}
    122124
    123125using_pulse {
     
    143145
    144146mingw {
    145147    DEFINES += USING_MINGW
    146     SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp
    147     HEADERS += mediamonitor-windows.h   audiooutputwin.h   audiooutputdx.h
    148     LIBS += -lpthread -lwinmm -lws2_32
     148    SOURCES += mediamonitor-windows.cpp
     149    HEADERS += mediamonitor-windows.h
     150    SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp
     151    HEADERS += audiooutputwin.h   audiooutputdx.h   volumecontrolendpoint.h
     152    LIBS += -lpthread -lwinmm -lws2_32 -lole32
    149153}
    150154
    151155macx {
    152     HEADERS += audiooutputca.h
    153     SOURCES += audiooutputca.cpp
     156    DEFINES += USE_COREAUDIO
     157    HEADERS += audiooutputca.h volumecontrolcoreaudio.h
     158    SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp
    154159    HEADERS += mythcdrom-darwin.h
    155160    SOURCES += mythcdrom-darwin.cpp
    156161
     
    189194
    190195using_alsa {
    191196    DEFINES += USE_ALSA
    192     HEADERS += audiooutputalsa.h
    193     SOURCES += audiooutputalsa.cpp
     197    HEADERS += audiooutputalsa.h volumecontrolalsa.h
     198    SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp
    194199}
    195200
    196201using_jack {
  • 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

     
    481481                    | DSBCAPS_GLOBALFOCUS          // Allows background playing
    482482                    | DSBCAPS_LOCHARDWARE;         // Needed for 5.1 on emu101k
    483483
    484     if (!m_UseSPDIF)
    485         dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME;     // Allow volume control
    486 
    487484    dsbdesc.dwBufferBytes = soundcard_buffer_size; // buffer size
    488485    dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf;
    489486
     
    554551    return buffered;
    555552}
    556553
    557 int AudioOutputDX::GetVolumeChannel(int channel) const
    558 {
    559     HRESULT dsresult;
    560     long dxVolume = 0;
    561     int volume;
    562 
    563     if (m_UseSPDIF)
    564         return 100;
    565 
    566     dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);
    567     volume = (int)(pow(10,(float)dxVolume/20)*100);
    568 
    569     if (dsresult != DS_OK)
    570     {
    571         VBERROR(QString("Failed to get volume %1").arg(dxVolume));
    572         return volume;
    573     }
    574 
    575     VBAUDIO(QString("Got volume %1").arg(volume));
    576     return volume;
    577 }
    578 
    579 void AudioOutputDX::SetVolumeChannel(int channel, int volume)
    580 {
    581     HRESULT dsresult;
    582     float dbAtten = 20 * log10((float)volume/100);
    583     long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);
    584 
    585     if (m_UseSPDIF)
    586         return;
    587 
    588     // dxVolume is attenuation in 100ths of a decibel
    589     dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);
    590 
    591     if (dsresult != DS_OK)
    592     {
    593         VBERROR(QString("Failed to set volume %1").arg(dxVolume));
    594         return;
    595     }
    596 
    597     VBAUDIO(QString("Set volume %1").arg(dxVolume));
    598 }
    599 
    600554/* 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"
     
    510511    return gc;
    511512}
    512513
    513 static HostCheckBox *MythControlsVolume()
    514 {
    515     HostCheckBox *gc = new HostCheckBox("MythControlsVolume");
    516     gc->setLabel(QObject::tr("Use internal volume controls"));
    517     gc->setValue(true);
    518     gc->setHelpText(QObject::tr("If enabled, MythTV will control the PCM and "
    519                     "master mixer volume. Disable this option if you prefer "
    520                     "to control the volume externally (for example, using "
    521                     "your amplifier) or if you use an external mixer program."));
    522     return gc;
    523 }
    524 
    525514static HostComboBox *MixerDevice()
    526515{
    527516    HostComboBox *gc = new HostComboBox("MixerDevice", true);
    528517    gc->setLabel(QObject::tr("Mixer device"));
     518    gc->addSelection(QObject::tr("Disabled"), QString());
    529519
    530 #ifdef USING_OSS
    531     QDir dev("/dev", "mixer*", QDir::Name, QDir::System);
    532     gc->fillSelectionsFromDir(dev);
     520    QHash<QString, QString> controls = VolumeControlManager::Enumerate();
    533521
    534     dev.setPath("/dev/sound");
    535     if (dev.exists())
     522    for (QHash<QString, QString>::const_iterator control = controls.begin();
     523         control != controls.end(); ++control)
    536524    {
    537         gc->fillSelectionsFromDir(dev);
     525        gc->addSelection(control.value(), control.key());
    538526    }
    539 #endif
    540 #ifdef USING_ALSA
    541     gc->addSelection("ALSA:default", "ALSA:default");
    542 #endif
    543 #ifdef USING_MINGW
    544     gc->addSelection("DirectX:", "DirectX:");
    545     gc->addSelection("Windows:", "Windows:");
    546 #endif
    547 #if !defined(USING_MINGW)
    548     gc->addSelection("software", "software");
    549     gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" "
    550                     "lets MythTV control the volume of all audio at the "
    551                     "expense of a slight quality loss."));
    552 #endif
    553527
    554528    return gc;
    555529}
    556530
    557 static const char* MixerControlControls[] = { "PCM",
    558                                               "Master" };
    559 
    560 static HostComboBox *MixerControl()
    561 {
    562     HostComboBox *gc = new HostComboBox("MixerControl", true);
    563     gc->setLabel(QObject::tr("Mixer controls"));
    564     for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);
    565          ++i)
    566     {
    567         gc->addSelection(QObject::tr(MixerControlControls[i]),
    568                          MixerControlControls[i]);
    569     }
    570 
    571     gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));
    572     return gc;
    573 }
    574 
    575 static HostSlider *MixerVolume()
    576 {
    577     HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);
    578     gs->setLabel(QObject::tr("Master mixer volume"));
    579     gs->setValue(70);
    580     gs->setHelpText(QObject::tr("Initial volume for the Master mixer. "
    581                     "This affects all sound created by the audio device. "
    582                     "Note: Do not set this too low."));
    583     return gs;
    584 }
    585 
    586 static HostSlider *PCMVolume()
    587 {
    588     HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);
    589     gs->setLabel(QObject::tr("PCM mixer volume"));
    590     gs->setValue(70);
    591     gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "
    592                     "volume keys in MythTV will adjust this parameter."));
    593     return gs;
    594 }
    595 
    596531static HostCheckBox *DecodeExtraAudio()
    597532{
    598533    HostCheckBox *gc = new HostCheckBox("DecodeExtraAudio");
     
    33253260    return gs;
    33263261}
    33273262
    3328 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup
     3263static ConfigurationGroup *AudioMixerSettingsGroup()
    33293264{
    3330   public:
    3331     AudioMixerSettingsGroup() :
    3332         TriggeredConfigurationGroup(false, true, false, false)
    3333     {
    3334         setLabel(QObject::tr("Audio Mixer"));
    3335         setUseLabel(false);
     3265    ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false);
     3266   
     3267    vcg->setLabel(QObject::tr("Audio Mixer"));
     3268    vcg->setUseLabel(false);
    33363269
    3337         Setting *volumeControl = MythControlsVolume();
    3338         addChild(volumeControl);
     3270    vcg->addChild(MixerDevice());
    33393271
    3340         // Mixer settings
    3341         ConfigurationGroup *settings =
    3342             new VerticalConfigurationGroup(false, true, false, false);
    3343         settings->addChild(MixerDevice());
    3344         settings->addChild(MixerControl());
    3345         settings->addChild(MixerVolume());
    3346         settings->addChild(PCMVolume());
     3272    return vcg;
     3273}
    33473274
    3348         ConfigurationGroup *dummy =
    3349             new VerticalConfigurationGroup(false, true, false, false);
    3350 
    3351         // Show Mixer config only if internal volume controls enabled
    3352         setTrigger(volumeControl);
    3353         addTarget("0", dummy);
    3354         addTarget("1", settings);
    3355     }
    3356 };
    3357 
    33583275static HostComboBox *MythLanguage()
    33593276{
    33603277    HostComboBox *gc = new HostComboBox("Language");
     
    40503967
    40513968    addChild(new AudioConfigSettings());
    40523969
    4053     addChild(new AudioMixerSettingsGroup());
     3970    addChild(AudioMixerSettingsGroup());
    40543971
    40553972    VerticalConfigurationGroup *general =
    40563973        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; }