Ticket #7517: volume_control_trunk_r26401.patch

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

     
    9898
    9999    // Possibly (user-defined) control the volume
    100100
    101     volume_control = false;
    102     volume_display_timer = new QTimer(this);
    103     if (gCoreContext->GetNumSetting("MythControlsVolume", 0))
     101    volume_control = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice"));
     102    if (volume_control)
    104103    {
    105         volume_control = true;
     104        connect(volume_control.data(), SIGNAL(changedVolume(int)),
     105                this, SLOT(VolumeChanged(int)));
     106        connect(volume_control.data(), SIGNAL(changedMute(bool)),
     107                this, SLOT(MuteChanged(bool)));
    106108    }
     109
     110    volume_display_timer = new QTimer(this);
    107111    volume_display_timer->setSingleShot(true);
    108112    volume_display_timer->start(2000);
    109113    connect(volume_display_timer, SIGNAL(timeout()),
     
    11801184    if (volume_control && gPlayer->getOutput())
    11811185    {
    11821186        if (up_or_down)
    1183             gPlayer->getOutput()->AdjustCurrentVolume(2);
     1187            gPlayer->incVolume();
    11841188        else
    1185             gPlayer->getOutput()->AdjustCurrentVolume(-2);
     1189            gPlayer->decVolume();
    11861190        showVolume(true);
    11871191    }
    11881192}
     
    12031207{
    12041208    if (volume_control && gPlayer->getOutput())
    12051209    {
    1206         gPlayer->getOutput()->ToggleMute();
     1210        gPlayer->toggleMute();
    12071211        showVolume(true);
    12081212    }
    12091213}
     
    12451249        {
    12461250            if (on_or_off)
    12471251            {
    1248                 volume_status->SetUsed(gPlayer->getOutput()->GetCurrentVolume());
     1252                volume_status->SetUsed(gPlayer->getVolume());
    12491253                volume_status->SetOrder(0);
    12501254                volume_status->refresh();
    12511255                volume_display_timer->setSingleShot(true);
     
    24632467
    24642468    return time_string;
    24652469}
     2470
     2471void PlaybackBoxMusic::VolumeChanged(int)
     2472{
     2473     showVolume(true);
     2474}
     2475
     2476void PlaybackBoxMusic::MuteChanged(bool)
     2477{
     2478     showVolume(true);
     2479}
  • 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
     
    308310    // TODO: Error checking that device is opened correctly!
    309311    m_output = AudioOutput::OpenAudio(
    310312                   adevice, pdevice, FORMAT_S16, 2, 0, 44100,
    311                    AUDIOOUTPUT_MUSIC, true, false,
     313                   AUDIOOUTPUT_MUSIC, false,
    312314                   gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1);
    313315
    314316    m_output->setBufferSize(256 * 1024);
     
    891893
    892894void MusicPlayer::incVolume()
    893895{
    894     if (getOutput())
     896    if (volume_control)
    895897    {
    896         getOutput()->AdjustCurrentVolume(2);
     898        volume_control->increaseVolume();
    897899        sendVolumeChangedEvent();
    898900    }
    899901}
    900902
    901903void MusicPlayer::decVolume()
    902904{
    903     if (getOutput())
     905    if (volume_control)
    904906    {
    905         getOutput()->AdjustCurrentVolume(-2);
     907        volume_control->decreaseVolume();
    906908        sendVolumeChangedEvent();
    907909    }
    908910}
    909911
    910912void MusicPlayer::setVolume(int volume)
    911913{
    912     if (getOutput())
     914    if (volume_control)
    913915    {
    914         getOutput()->SetCurrentVolume(volume);
     916        volume_control->setVolume(volume);
    915917        sendVolumeChangedEvent();
    916918    }
    917919}
    918920
    919921uint MusicPlayer::getVolume(void) const
    920922{
    921     if (m_output)
    922         return m_output->GetCurrentVolume();
     923    if (volume_control)
     924        return volume_control->volume();
    923925    return 0;
    924926}
    925927
    926928void MusicPlayer::toggleMute(void)
    927929{
    928     if (m_output)
     930    if (volume_control)
    929931    {
    930         m_output->ToggleMute();
     932        volume_control->setMute(!volume_control->mute());
    931933        sendVolumeChangedEvent();
    932934    }
    933935}
    934936
    935 MuteState MusicPlayer::getMuteState(void) const
     937bool MusicPlayer::isMuted(void) const
    936938{
    937     if (m_output)
    938         return m_output->GetMuteState();
    939     return kMuteAll;
     939    if (volume_control)
     940        return volume_control->mute();
     941    return true;
    940942}
    941943
    942944void 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

     
    38153815    { { ! enabled audio_alsa || die "ERROR: Alsa >= 1.0.16 required"; } &&
    38163816    disable audio_alsa; }
    38173817
     3818# OSS probe
     3819if ! disabled audio_oss ; then
     3820    if test -f /usr/"${libdir_name}"/oss/include/sys/soundcard.h &&
     3821       check_cpp_condition /usr/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then
     3822        disable soundcard_h
     3823        enable sys_soundcard_h
     3824        prepend CONFIG_INCLUDEPATH "/usr/${libdir_name}/oss/include"
     3825    elif test -f /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h &&
     3826       check_cpp_condition /usr/local/"${libdir_name}"/oss/include/sys/soundcard.h "SOUND_VERSION >= 0x040000"; then
     3827        disable soundcard_h
     3828        enable sys_soundcard_h
     3829        prepend CONFIG_INCLUDEPATH "/usr/local/${libdir_name}/oss/include"
     3830    else
     3831        if enabled soundcard_h ; then
     3832            check_cpp_condition soundcard.h "SOUND_VERSION >= 0x040000" &&
     3833            enable  audio_oss ||
     3834            disable audio_oss
     3835        elif enabled sys_soundcard_h ; then
     3836            check_cpp_condition sys/soundcard.h "SOUND_VERSION >= 0x040000" &&
     3837            enable  audio_oss ||
     3838            disable audio_oss
     3839        fi
     3840    fi
     3841fi
    38183842
    38193843# JACK probe
    38203844! disabled audio_jack &&
  • mythtv/libs/libmythtv/avformatdecoder.cpp

     
    280280      itv(NULL),
    281281      // Audio
    282282      audioSamples(NULL),
    283       internal_vol(false),
    284283      disable_passthru(false),
    285284      dummy_frame(NULL),
    286285      // DVD
     
    301300    av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR);
    302301    av_log_set_callback(myth_av_log);
    303302
    304     internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);
    305303
    306304    audioIn.sample_size = -32; // force SetupAudioStream to run once
    307305    itv = GetPlayer()->GetInteractiveTV();
     
    45864584    passthru &= m_audio->CanPassthrough(ctx->sample_rate);
    45874585        // Will downmix if we can't support the amount of channels
    45884586    passthru &= ctx->channels >= (int)m_audio->GetMaxChannels();
    4589     passthru &= !internal_vol;
    45904587    passthru &= !transcoding && !disable_passthru;
    45914588    // Don't know any cards that support spdif clocked at < 44100
    45924589    // Some US cable transmissions have 2ch 32k AC-3 streams
  • 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

     
    3636#include "programinfo.h"
    3737#include "channelutil.h"
    3838#include "videoouttypes.h"
    39 #include "volumebase.h"
     39#include "volumecontrolmanager.h"
    4040#include "inputinfo.h"
    4141#include "channelgroup.h"
    4242#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
     
    497500
    498501    vector<long long> TeardownAllPlayers(PlayerContext*);
    499502    void RestartAllPlayers(PlayerContext *lctx,
    500                            const vector<long long> &pos,
    501                            MuteState mctx_mute);
     503                           const vector<long long> &pos);
    502504    void RestartMainPlayer(PlayerContext *mctx);
    503505
    504506    void PxPToggleView(  PlayerContext *actx, bool wantPBP);
     
    704706    /// Picture attribute to modify (on arrow left or right)
    705707    PictureAttribute  adjustingPictureAttribute;
    706708
     709    QSharedPointer<VolumeControl> volumeControl; ///< Volume Control interface
     710
    707711    // Ask Allow state
    708712    QMap<QString,AskProgramInfo> askAllowPrograms;
    709713    QMutex                       askAllowLock;
  • mythtv/libs/libmythtv/mythdvdplayer.h

     
    88class MythDVDPlayer : public MythPlayer
    99{
    1010  public:
    11     MythDVDPlayer(bool muted = false);
     11    MythDVDPlayer();
    1212    virtual int  OpenFile(uint retries = 4, bool allow_libmpeg2 = true);
    1313    virtual void ReleaseNextVideoFrame(VideoFrame *buffer, int64_t timecode,
    1414                                       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

     
    99#include <QEvent>
    1010
    1111#include "playercontext.h"
    12 #include "volumebase.h"
    1312#include "audiooutputsettings.h"
    1413#include "RingBuffer.h"
    1514#include "osd.h"
     
    119118    friend class DecoderThread;
    120119
    121120  public:
    122     MythPlayer(bool muted = false);
     121    MythPlayer();
    123122   ~MythPlayer();
    124123
    125124    // Initialization
     
    134133    bool IsEmbedding(void);
    135134    void WindowResized(const QSize &new_size);
    136135
    137     // Audio Sets
    138     uint AdjustVolume(int change)           { return audio.AdjustVolume(change); }
    139     bool SetMuted(bool mute)                { return audio.SetMuted(mute);       }
    140     MuteState SetMuteState(MuteState state) { return audio.SetMuteState(state);  }
    141     MuteState IncrMuteState(void)           { return audio.IncrMuteState();      }
    142 
    143136    // Sets
    144137    void SetPlayerInfo(TV             *tv,
    145138                       QWidget        *widget,
     
    188181    float   GetFrameRate(void) const          { return video_frame_rate; }
    189182
    190183    bool    IsAudioNeeded(void) { return !using_null_videoout && player_ctx->IsAudioNeeded(); }
    191     uint    GetVolume(void) { return audio.GetVolume(); }
    192184    int     GetSecondsBehind(void) const;
    193185    AspectOverrideMode GetAspectOverride(void) const;
    194186    AdjustFillMode     GetAdjustFill(void) const;
    195     MuteState          GetMuteState(void) { return audio.GetMuteState(); }
    196187
    197188    int     GetFFRewSkip(void) const          { return ffrew_skip; }
    198189    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),   m_channels(2),
    99    m_orig_channels(2),  m_codec(0),            m_format(FORMAT_NONE),
    1010    m_samplerate(44100), m_stretchfactor(1.0f), m_passthru(false),
    11     m_lock(QMutex::Recursive), m_muted_on_creation(muted),
     11    m_lock(QMutex::Recursive),
    1212    m_main_device(QString::null), m_passthru_device(QString::null),
    1313    no_audio_in(false), no_audio_out(false)
    1414{
     
    8585            VERBOSE(VB_IMPORTANT, LOC + "Enabling Audio");
    8686            no_audio_out = false;
    8787        }
    88         if (m_muted_on_creation)
    89         {
    90             SetMuteState(kMuteAll);
    91             m_muted_on_creation = false;
    92         }
    9388    }
    9489
    9590    if (m_audioOutput && !no_audio_out)
     
    150145    m_lock.unlock();
    151146}
    152147
    153 uint AudioPlayer::GetVolume(void)
    154 {
    155     uint res = 0;
    156     m_lock.lock();
    157     if (m_audioOutput && !no_audio_out)
    158         res = m_audioOutput->GetCurrentVolume();
    159     m_lock.unlock();
    160     return res;
    161 }
    162 
    163148void AudioPlayer::SetAudioInfo(const QString &main_device,
    164149                               const QString &passthru_device,
    165150                               uint           samplerate)
     
    198183    m_lock.unlock();
    199184}
    200185
    201 bool AudioPlayer::SetMuted(bool mute)
    202 {
    203     QMutexLocker lock(&m_lock);
    204     bool is_muted = IsMuted();
    205 
    206     if (m_audioOutput && !no_audio_out && !is_muted && mute &&
    207         (kMuteAll == SetMuteState(kMuteAll)))
    208     {
    209         VERBOSE(VB_AUDIO, "muting sound " <<IsMuted());
    210         return true;
    211     }
    212     else if (m_audioOutput && !no_audio_out && is_muted && !mute &&
    213              (kMuteOff == SetMuteState(kMuteOff)))
    214     {
    215         VERBOSE(VB_AUDIO, "unmuting sound "<<IsMuted());
    216         return true;
    217     }
    218 
    219     VERBOSE(VB_AUDIO, "not changing sound mute state "<<IsMuted());
    220 
    221     return false;
    222 }
    223 
    224 MuteState AudioPlayer::SetMuteState(MuteState mstate)
    225 {
    226     QMutexLocker lock(&m_lock);
    227     if (m_audioOutput && !no_audio_out)
    228         return m_audioOutput->SetMuteState(mstate);
    229     return kMuteAll;
    230 }
    231 
    232 MuteState AudioPlayer::IncrMuteState(void)
    233 {
    234     QMutexLocker lock(&m_lock);
    235     MuteState mstate = kMuteAll;
    236     if (m_audioOutput && !no_audio_out)
    237         mstate = SetMuteState(VolumeBase::NextMuteState(GetMuteState()));
    238     return mstate;
    239 }
    240 
    241 MuteState AudioPlayer::GetMuteState(void)
    242 {
    243     QMutexLocker lock(&m_lock);
    244     if (m_audioOutput && !no_audio_out)
    245         return m_audioOutput->GetMuteState();
    246     return kMuteAll;
    247 }
    248 
    249 uint AudioPlayer::AdjustVolume(int change)
    250 {
    251     QMutexLocker lock(&m_lock);
    252     if (m_audioOutput && !no_audio_out)
    253         m_audioOutput->AdjustCurrentVolume(change);
    254     return GetVolume();
    255 }
    256 
    257186int64_t AudioPlayer::GetAudioTime(void)
    258187{
    259188    int64_t 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

     
    402402
    403403bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget,
    404404                                 TVState desiredState,
    405                                  WId embedwinid, const QRect *embedbounds,
    406                                  bool muted)
     405                                 WId embedwinid, const QRect *embedbounds)
    407406{
    408407    int exact_seeking = gCoreContext->GetNumSetting("ExactSeeking", 0);
    409408
     
    416415
    417416    MythPlayer *player = NULL;
    418417    if (kState_WatchingBD  == desiredState)
    419         player = new MythBDPlayer(muted);
     418        player = new MythBDPlayer();
    420419    else if (kState_WatchingDVD == desiredState)
    421         player = new MythDVDPlayer(muted);
     420        player = new MythDVDPlayer();
    422421    else
    423         player = new MythPlayer(muted);
     422        player = new MythPlayer();
    424423
    425424    if (nohardwaredecoders)
    426425        player->DisableHardwareDecoders();
     
    472471                VERBOSE(VB_IMPORTANT, LOC_ERR + errMsg);
    473472        }
    474473    }
    475     else if (pipState == kPBPRight)
    476         player->SetMuted(true);
    477474
    478475    return StartPlaying(-1);
    479476}
  • mythtv/libs/libmythtv/tv_play.cpp

     
    10681068
    10691069    gCoreContext->addListener(this);
    10701070
     1071    volumeControl = VolumeControlManager::GetControl(gCoreContext->GetSetting("MixerDevice"));
     1072    if (volumeControl)
     1073    {
     1074        connect(volumeControl.data(), SIGNAL(changedVolume(int)),
     1075                this, SLOT(VolumeChanged(int)), Qt::QueuedConnection);
     1076        connect(volumeControl.data(), SIGNAL(changedMute(bool)),
     1077                this, SLOT(MuteChanged(bool)), Qt::QueuedConnection);
     1078    }
     1079
     1080    VERBOSE(VB_PLAYBACK, LOC + "ctor -- end");
     1081
    10711082    QMutexLocker lock(&initFromDBLock);
    10721083    initFromDBDone = true;
    10731084    initFromDBWait.wakeAll();
     
    47424753            if (!ok)
    47434754                return;
    47444755
    4745             if ( 0 <= vol && vol <= 100)
     4756            if ( 0 <= vol && vol <= 100 && volumeControl)
    47464757            {
    4747                 ctx->LockDeletePlayer(__FILE__, __LINE__);
    4748                 if (!ctx->player)
    4749                 {
    4750                     ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    4751                     return;
    4752                 }
    4753 
    4754                 vol -= ctx->player->GetVolume();
    4755                 vol = ctx->player->AdjustVolume(vol);
    4756                 ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    4757 
    4758                 if (!browsehelper->IsBrowsing() && !editmode)
    4759                 {
    4760                     UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"),
    4761                                     QString::number(vol),
    4762                                     kOSDFunctionalType_PictureAdjust, "%", vol * 10,
    4763                                     kOSDTimeout_Med);
    4764                     SetUpdateOSDPosition(false);
    4765                 }
     4758                volumeControl->setVolume(vol);
    47664759            }
    47674760        }
    47684761    }
     
    48584851        }
    48594852        else if (tokens[2] == "VOLUME")
    48604853        {
    4861             QString infoStr = QString("%1%").arg(ctx->player->GetVolume());
     4854            QString infoStr = QString("%1%")
     4855                .arg(volumeControl ? volumeControl->volume() : 0);
    48624856
    48634857            QString message = QString("NETWORK_CONTROL ANSWER %1")
    48644858                .arg(infoStr);
     
    52895283        }
    52905284    }
    52915285
    5292     MuteState mctx_mute = kMuteOff;
    5293     mctx->LockDeletePlayer(__FILE__, __LINE__);
    5294     if (mctx->player)
    5295         mctx_mute = mctx->player->GetMuteState();
    5296     mctx->UnlockDeletePlayer(__FILE__, __LINE__);
    5297 
    52985286    vector<long long> pos = TeardownAllPlayers(mctx);
    52995287
    53005288    if (wantPBP)
     
    53125300        }
    53135301    }
    53145302
    5315     RestartAllPlayers(mctx, pos, mctx_mute);
     5303    RestartAllPlayers(mctx, pos);
    53165304
    53175305    VERBOSE(VB_PLAYBACK, LOC +
    53185306            QString("PxPToggleType() converting from %1 to %2 -- end")
     
    54565444* \brief Recreate Main and PIP windows. Could be either PIP or PBP views.
    54575445*/
    54585446void TV::RestartAllPlayers(PlayerContext *lctx,
    5459                         const vector<long long> &pos,
    5460                         MuteState mctx_mute)
     5447                        const vector<long long> &pos)
    54615448{
    54625449    QString loc = LOC + QString("RestartAllPlayers(): ");
    54635450
     
    55045491            pipctx->LockDeletePlayer(__FILE__, __LINE__);
    55055492            if (pipctx->player)
    55065493            {
    5507                 pipctx->player->SetMuted(true);
    55085494                pipctx->player->JumpToFrame(pos[i]);
    55095495            }
    55105496            pipctx->UnlockDeletePlayer(__FILE__, __LINE__);
     
    55165502            ForceNextStateNone(pipctx);
    55175503        }
    55185504    }
    5519 
    5520     // If old main player had a kMuteAll | kMuteOff setting,
    5521     // apply old main player's mute setting to new main player.
    5522     mctx->LockDeletePlayer(__FILE__, __LINE__);
    5523     if (mctx->player && ((kMuteAll == mctx_mute) || (kMuteOff == mctx_mute)))
    5524         mctx->player->SetMuteState(mctx_mute);
    5525     mctx->UnlockDeletePlayer(__FILE__, __LINE__);
    55265505}
    55275506
    55285507void TV::PxPSwap(PlayerContext *mctx, PlayerContext *pipctx)
     
    55505529        return;
    55515530    }
    55525531
    5553     MuteState mctx_mute = mctx->player->GetMuteState();
    55545532    mctx->deletePlayerLock.unlock();
    55555533    pipctx->deletePlayerLock.unlock();
    55565534
     
    55645542    playerActive = (ctx_index == playerActive) ?
    55655543        0 : ((ctx_index == 0) ? ctx_index : playerActive);
    55665544
    5567     RestartAllPlayers(mctx, pos, mctx_mute);
     5545    RestartAllPlayers(mctx, pos);
    55685546
    55695547    SetActive(mctx, playerActive, false);
    55705548
     
    55855563        mctx->deletePlayerLock.unlock();
    55865564        return;
    55875565    }
    5588 
    5589     MuteState mctx_mute = mctx->player->GetMuteState();
    5590 
    5591     // HACK - FIXME
    5592     // workaround muted audio when Player is re-created
    5593     mctx_mute = kMuteOff;
    5594     // FIXME - end
    55955566    mctx->deletePlayerLock.unlock();
    55965567
    55975568    vector<long long> pos = TeardownAllPlayers(mctx);
    5598     RestartAllPlayers(mctx, pos, mctx_mute);
     5569    RestartAllPlayers(mctx, pos);
    55995570    SetActive(mctx, playerActive, false);
    56005571
    56015572    VERBOSE(VB_PLAYBACK, LOC + "Restart main player -- end");
     
    64186389        if (mctx != ctx)
    64196390            PIPRemovePlayer(mctx, ctx);
    64206391
    6421         bool muted = false;
    6422         ctx->LockDeletePlayer(__FILE__, __LINE__);
    6423         if (ctx->player && ctx->player->IsMuted())
    6424             muted = true;
    6425         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    6426 
    64276392        // pause the decoder first, so we're not reading too close to the end.
    64286393        ctx->buffer->IgnoreLiveEOF(true);
    64296394        ctx->buffer->StopReads();
     
    64756440
    64766441            if (ctx->CreatePlayer(
    64776442                    this, GetMythMainWindow(), ctx->GetState(),
    6478                     mctx->embedWinID, &mctx->embedBounds, muted))
     6443                    mctx->embedWinID, &mctx->embedBounds))
    64796444            {
    64806445                ScheduleStateChange(ctx);
    64816446                ok = true;
     
    78917856
    78927857void TV::ChangeVolume(PlayerContext *ctx, bool up)
    78937858{
    7894     ctx->LockDeletePlayer(__FILE__, __LINE__);
    7895     if (!ctx->player)
     7859    if (volumeControl)
    78967860    {
    7897         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    7898         return;
     7861        if (up)
     7862            volumeControl->increaseVolume();
     7863        else
     7864            volumeControl->decreaseVolume();
    78997865    }
    7900     uint curvol = ctx->player->AdjustVolume((up) ? +2 : -2);
    7901     ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    7902 
    7903     if (!browsehelper->IsBrowsing())
    7904     {
    7905         UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"),
    7906                         QString::number(curvol),
    7907                         kOSDFunctionalType_PictureAdjust, "%", curvol * 10,
    7908                         kOSDTimeout_Med);
    7909         SetUpdateOSDPosition(false);
    7910     }
    79117866}
    79127867
    79137868void TV::ToggleTimeStretch(PlayerContext *ctx)
     
    80508005
    80518006void TV::ToggleMute(PlayerContext *ctx, const bool muteIndividualChannels)
    80528007{
    8053     ctx->LockDeletePlayer(__FILE__, __LINE__);
    8054     if (!ctx->player || !ctx->player->HasAudioOut())
    8055     {
    8056         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    8057         return;
    8058     }
    8059 
    8060     MuteState mute_status;
    8061 
    8062     if (!muteIndividualChannels)
    8063     {
    8064         ctx->player->SetMuted(!ctx->player->IsMuted());
    8065         mute_status = (ctx->player->IsMuted()) ? kMuteAll : kMuteOff;
    8066     }
    8067     else
    8068     {
    8069         mute_status = ctx->player->IncrMuteState();
    8070     }
    8071     ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    8072 
    8073     QString text;
    8074 
    8075     switch (mute_status)
    8076     {
    8077         case kMuteOff:   text = tr("Mute Off"); break;
    8078         case kMuteAll:   text = tr("Mute On"); break;
    8079         case kMuteLeft:  text = tr("Left Channel Muted"); break;
    8080         case kMuteRight: text = tr("Right Channel Muted"); break;
    8081     }
    8082 
    8083     SetOSDMessage(ctx, text);
     8008    if (volumeControl)
     8009        volumeControl->setMute(!volumeControl->mute());
    80848010}
    80858011
    80868012void TV::ToggleSleepTimer(const PlayerContext *ctx)
     
    88598785        {
    88608786            value = ctx->player->getVideoOutput()->GetPictureAttribute(attr);
    88618787        }
    8862         else if (ctx->player->HasAudioOut())
     8788        else if (ctx->player->HasAudioOut() && volumeControl)
    88638789        {
    8864             value = ctx->player->GetVolume();
     8790            value = volumeControl->volume();
    88658791            title = tr("Adjust Volume");
    88668792        }
    88678793    }
     
    1186711793    ReturnPlayerLock(mctx);
    1186811794}
    1186911795
     11796void TV::VolumeChanged(int volume)
     11797{
     11798    if (!browsehelper->IsBrowsing())
     11799    {
     11800        PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__);
     11801        UpdateOSDStatus(actx, tr("Adjust Volume"), tr("Volume"),
     11802                        QString::number(volume),
     11803                        kOSDFunctionalType_PictureAdjust, "%", 10 * volume);
     11804        SetUpdateOSDPosition(false);
     11805        ReturnPlayerLock(actx);
     11806    }
     11807}
     11808
     11809void TV::MuteChanged(bool mute)
     11810{
     11811    PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__);
     11812    SetOSDMessage(actx, mute ? tr("Mute On") : tr("Mute Off"));
     11813    ReturnPlayerLock(actx);
     11814}
     11815
     11816
    1187011817OSD *TV::GetOSDL(const char *file, int location)
    1187111818{
    1187211819    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

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

     
    319319
    320320    // Audio
    321321    short int        *audioSamples;
    322     bool              internal_vol;
    323322    bool              disable_passthru;
    324323
    325324    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

     
    99class MPUBLIC AudioPlayer
    1010{
    1111  public:
    12     AudioPlayer(MythPlayer *parent, bool muted);
     12    AudioPlayer(MythPlayer *parent);
    1313   ~AudioPlayer();
    1414
    1515    void  Reset(void);
     
    3434    int   GetCodec(void)        { return m_codec;         }
    3535    int   GetNumChannels(void)  { return m_channels;      }
    3636    int   GetOrigChannels(void) { return m_orig_channels; }
    37     uint  GetVolume(void);
    38     uint  AdjustVolume(int change);
    3937    float GetStretchFactor(void) { return m_stretchfactor;   }
    4038    void  SetStretchFactor(float factor);
    4139    bool  ToggleUpmix(void);
     
    4543    uint  GetMaxChannels(void);
    4644    int64_t GetAudioTime(void);
    4745
    48     bool      IsMuted(void) { return GetMuteState() == kMuteAll; }
    49     bool      SetMuted(bool mute);
    50     MuteState GetMuteState(void);
    51     MuteState SetMuteState(MuteState);
    52     MuteState IncrMuteState(void);
    53 
    5446    void AddAudioData(char *buffer, int len, int64_t timecode);
    5547    bool GetBufferStatus(uint &fill, uint &total);
    5648
     
    6557    float        m_stretchfactor;
    6658    bool         m_passthru;
    6759    QMutex       m_lock;
    68     bool         m_muted_on_creation;
    6960    QString      m_main_device;
    7061    QString      m_passthru_device;
    7162    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)
     
    6768
    6869    virtual void Reset(void);
    6970
    70     void SetSWVolume(int new_volume, bool save);
    71     int GetSWVolume(void);
    72 
    7371    // timecode is in milliseconds.
    7472    virtual bool AddFrames(void *buffer, int frames, int64_t timecode);
    7573
     
    160158    bool killaudio;
    161159
    162160    bool pauseaudio, actually_paused, was_paused, unpause_when_ready;
    163     bool set_initial_vol;
    164161    bool buffer_output_data_for_use; //  used by AudioOutputNULL
    165162
    166163    int configured_channels;
     
    186183    bool needs_downmix;
    187184    int surround_mode;
    188185    float old_stretchfactor;
    189     int volume;
    190     QString volumeControl;
     186    QSharedPointer<VolumeControl> volume_control; ///< Volume Control interface
    191187
    192188    bool processing;
    193189
  • 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: ")
     
    3738    m_device(-1),
    3839    m_subdevice(-1)
    3940{
    40     m_mixer.handle = NULL;
    41     m_mixer.elem = NULL;
    42 
    4341    // Set everything up
    4442    if (passthru_device == "auto")
    4543    {
     
    360358        return OpenDevice();
    361359    }
    362360
    363     if (internal_vol && !OpenMixer())
    364         VBERROR("Unable to open audio mixer. Volume control disabled");
    365 
    366361    // Device opened successfully
    367362    return true;
    368363}
    369364
    370365void AudioOutputALSA::CloseDevice()
    371366{
    372     if (m_mixer.handle)
    373         snd_mixer_close(m_mixer.handle);
    374     m_mixer.handle = NULL;
    375367    if (pcm_handle)
    376368    {
    377369        snd_pcm_close(pcm_handle);
     
    639631    return 0;
    640632}
    641633
    642 int AudioOutputALSA::GetVolumeChannel(int channel) const
    643 {
    644     int retvol = 0;
    645 
    646     if (!m_mixer.elem)
    647         return retvol;
    648 
    649     snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
    650     if (!snd_mixer_selem_has_playback_channel(m_mixer.elem, chan))
    651         return retvol;
    652 
    653     long mixervol;
    654     int chk;
    655     if ((chk = snd_mixer_selem_get_playback_volume(m_mixer.elem,
    656                                                    chan,
    657                                                    &mixervol)) < 0)
    658     {
    659         VBERROR(QString("failed to get channel %1 volume, mixer %2/%3: %4")
    660                 .arg(channel).arg(m_mixer.device)
    661                 .arg(m_mixer.control)
    662                 .arg(snd_strerror(chk)));
    663     }
    664     else
    665     {
    666         retvol = (m_mixer.volrange != 0L) ? (mixervol - m_mixer.volmin) *
    667                                             100.0f / m_mixer.volrange + 0.5f
    668                                             : 0;
    669         retvol = max(retvol, 0);
    670         retvol = min(retvol, 100);
    671         VBAUDIO(QString("get volume channel %1: %2")
    672                 .arg(channel).arg(retvol));
    673     }
    674     return retvol;
    675 }
    676 
    677 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)
    678 {
    679     if (!(internal_vol && m_mixer.elem))
    680         return;
    681 
    682     long mixervol = volume * m_mixer.volrange / 100.0f - m_mixer.volmin + 0.5f;
    683     mixervol = max(mixervol, m_mixer.volmin);
    684     mixervol = min(mixervol, m_mixer.volmax);
    685 
    686     snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
    687     if (snd_mixer_selem_set_playback_volume(m_mixer.elem, chan, mixervol) < 0)
    688         VBERROR(QString("failed to set channel %1 volume").arg(channel));
    689     else
    690         VBAUDIO(QString("channel %1 volume set %2 => %3")
    691                 .arg(channel).arg(volume).arg(mixervol));
    692 }
    693 
    694 bool AudioOutputALSA::OpenMixer(void)
    695 {
    696     if (!pcm_handle)
    697     {
    698         VBERROR("mixer setup without a pcm");
    699         return false;
    700     }
    701     m_mixer.device = gCoreContext->GetSetting("MixerDevice", "default");
    702     m_mixer.device = m_mixer.device.remove(QString("ALSA:"));
    703     if (m_mixer.device.toLower() == "software")
    704         return true;
    705 
    706     m_mixer.control = gCoreContext->GetSetting("MixerControl", "PCM");
    707 
    708     QString mixer_device_tag = QString("mixer device %1").arg(m_mixer.device);
    709 
    710     int chk;
    711     if ((chk = snd_mixer_open(&m_mixer.handle, 0)) < 0)
    712     {
    713         VBERROR(QString("failed to open mixer device %1: %2")
    714                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    715         return false;
    716     }
    717 
    718     QByteArray dev_ba = m_mixer.device.toAscii();
    719     struct snd_mixer_selem_regopt regopts =
    720         {1, SND_MIXER_SABSTRACT_NONE, dev_ba.constData(), NULL, NULL};
    721 
    722     if ((chk = snd_mixer_selem_register(m_mixer.handle, &regopts, NULL)) < 0)
    723     {
    724         snd_mixer_close(m_mixer.handle);
    725         m_mixer.handle = NULL;
    726         VBERROR(QString("failed to register %1: %2")
    727                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    728         return false;
    729     }
    730 
    731     if ((chk = snd_mixer_load(m_mixer.handle)) < 0)
    732     {
    733         snd_mixer_close(m_mixer.handle);
    734         m_mixer.handle = NULL;
    735         VBERROR(QString("failed to load %1: %2")
    736                 .arg(mixer_device_tag).arg(snd_strerror(chk)));
    737         return false;
    738     }
    739 
    740     m_mixer.elem = NULL;
    741     uint elcount = snd_mixer_get_count(m_mixer.handle);
    742     snd_mixer_elem_t* elx = snd_mixer_first_elem(m_mixer.handle);
    743 
    744     for (uint ctr = 0; elx != NULL && ctr < elcount; ctr++)
    745     {
    746         QString tmp = QString(snd_mixer_selem_get_name(elx));
    747         if (m_mixer.control == tmp &&
    748             !snd_mixer_selem_is_enumerated(elx) &&
    749             snd_mixer_selem_has_playback_volume(elx) &&
    750             snd_mixer_selem_is_active(elx))
    751         {
    752             m_mixer.elem = elx;
    753             VBAUDIO(QString("found playback control %1 on %2")
    754                     .arg(m_mixer.control)
    755                     .arg(mixer_device_tag));
    756             break;
    757         }
    758         elx = snd_mixer_elem_next(elx);
    759     }
    760     if (!m_mixer.elem)
    761     {
    762         snd_mixer_close(m_mixer.handle);
    763         m_mixer.handle = NULL;
    764         VBERROR(QString("no playback control %1 found on %2")
    765                 .arg(m_mixer.control).arg(mixer_device_tag));
    766         return false;
    767     }
    768     if ((snd_mixer_selem_get_playback_volume_range(m_mixer.elem,
    769                                                    &m_mixer.volmin,
    770                                                    &m_mixer.volmax) < 0))
    771     {
    772         snd_mixer_close(m_mixer.handle);
    773         m_mixer.handle = NULL;
    774         VBERROR(QString("failed to get volume range on %1/%2")
    775                 .arg(mixer_device_tag).arg(m_mixer.control));
    776         return false;
    777     }
    778 
    779     m_mixer.volrange = m_mixer.volmax - m_mixer.volmin;
    780     VBAUDIO(QString("mixer volume range on %1/%2 - min %3, max %4, range %5")
    781             .arg(mixer_device_tag).arg(m_mixer.control)
    782             .arg(m_mixer.volmin).arg(m_mixer.volmax).arg(m_mixer.volrange));
    783     VBAUDIO(QString("%1/%2 set up successfully")
    784             .arg(mixer_device_tag)
    785             .arg(m_mixer.control));
    786 
    787     if (set_initial_vol)
    788     {
    789         int initial_vol;
    790         if (m_mixer.control == "PCM")
    791             initial_vol = gCoreContext->GetNumSetting("PCMMixerVolume", 80);
    792         else
    793             initial_vol = gCoreContext->GetNumSetting("MasterMixerVolume", 80);
    794         for (int ch = 0; ch < channels; ++ch)
    795             SetVolumeChannel(ch, initial_vol);
    796     }
    797 
    798     return true;
    799 }
    800 
    801634QMap<QString, QString> *AudioOutputALSA::GetALSADevices(const char *type)
    802635{
    803636    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();
     
    492454    pa_stream_set_overflow_callback(pstream, BufferFlowCallback, (char*)"over");
    493455    pa_stream_set_underflow_callback(pstream, BufferFlowCallback,
    494456                                     (char*)"under");
    495     if (set_initial_vol)
    496     {
    497         int volume = gCoreContext->GetNumSetting("MasterMixerVolume", 80);
    498         pa_cvolume_set(&volume_control, channels,
    499                        (float)volume * (float)PA_VOLUME_NORM / 100.0f);
    500     }
    501     else
    502         pa_cvolume_reset(&volume_control, channels);
     457    pa_cvolume_reset(&volume_control, channels);
    503458
    504459    fragment_size = (samplerate * 25 * output_bytes_per_frame) / 1000;
    505460
  • 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

     
    489489        chan_volumes[i] = volume;
    490490}
    491491
    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 
    528492/* We don't need an audio output thread for Jack
    529493  Everything handled by callbacks here
    530494  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

     
    6363    pauseaudio(false),          actually_paused(false),
    6464    was_paused(false),          unpause_when_ready(false),
    6565
    66     set_initial_vol(settings.set_initial_vol),
    6766    buffer_output_data_for_use(false),
    6867
    6968    // private
     
    7675    source_bytes_per_frame(0),
    7776    needs_upmix(false),         needs_downmix(false),
    7877    surround_mode(QUALITY_LOW), old_stretchfactor(1.0f),
    79     volume(80),                 volumeControl(QString()),
    8078
    8179    processing(false),
    8280
     
    117115
    118116        VBAUDIO(QString("SRC quality = %1").arg(quality_string(src_quality)));
    119117    }
     118
     119    if (gCoreContext->GetSetting("MixerDevice") == "Software:")
     120        volume_control = VolumeControlManager::GetControl("Software:");
    120121}
    121122
    122123/**
     
    394395
    395396    killaudio = pauseaudio = false;
    396397    was_paused = true;
    397     internal_vol = gCoreContext->GetNumSetting("MythControlsVolume", 0);
    398398
    399399    VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels")
    400400            .arg(ff_codec_id_string((CodecID)codec))
     
    495495
    496496    // Turn on float conversion?
    497497    if (need_resampler || needs_upmix || needs_downmix ||
    498         stretchfactor != 1.0f || (internal_vol && SWVolume()) ||
     498        stretchfactor != 1.0f || (volume_control) ||
    499499        (enc && output_format != FORMAT_S16) ||
    500500        !output_settings->IsSupportedFormat(output_format))
    501501    {
     
    534534        return;
    535535    }
    536536
    537     // Only used for software volume
    538     if (set_initial_vol && internal_vol && SWVolume())
    539     {
    540         VBAUDIO("Software volume enabled");
    541         volumeControl  = gCoreContext->GetSetting("MixerControl", "PCM");
    542         volumeControl += "MixerVolume";
    543         volume = gCoreContext->GetNumSetting(volumeControl, 80);
    544     }
    545 
    546     VolumeBase::SetChannels(channels);
    547     VolumeBase::SyncVolume();
    548     VolumeBase::UpdateVolume();
    549 
    550537    VBAUDIO(QString("Audio fragment size: %1").arg(fragment_size));
    551538
    552539    audbuf_timecode = audiotime = frames_buffered = 0;
     
    870857}
    871858
    872859/**
    873  * Set the volume for software volume control
    874  */
    875 void AudioOutputBase::SetSWVolume(int new_volume, bool save)
    876 {
    877     volume = new_volume;
    878     if (save && volumeControl != NULL)
    879         gCoreContext->SaveSetting(volumeControl, volume);
    880 }
    881 
    882 /**
    883  * Get the volume for software volume control
    884  */
    885 int AudioOutputBase::GetSWVolume()
    886 {
    887     return volume;
    888 }
    889 
    890 /**
    891860 * Check that there's enough space in the audiobuffer to write the provided
    892861 * number of frames
    893862 *
     
    11391108        org_waud += nFrames * bpf;
    11401109    }
    11411110
    1142     if (internal_vol && SWVolume())
     1111    if (volume_control)
    11431112    {
    11441113        org_waud    = waud;
    11451114        int num     = len;
     1115        int volume  = volume_control->volume();
    11461116
    11471117        if (bdiff <= num)
    11481118        {
     
    13881358    *local_raud += frag_size;
    13891359
    13901360    // Mute individual channels through mono->stereo duplication
    1391     MuteState mute_state = GetMuteState();
    1392     if (written_size && channels > 1 &&
    1393         (mute_state == kMuteLeft || mute_state == kMuteRight))
     1361    bool mute = volume_control ? volume_control->mute() : false;
     1362    if (written_size && channels > 1 && mute)
    13941363    {
    1395         AudioOutputUtil::MuteChannel(obytes << 3, channels,
    1396                                      mute_state == kMuteLeft ? 0 : 1,
     1364        AudioOutputUtil::MuteChannel(obytes << 3, channels, 1,
    13971365                                     buffer, written_size);
    13981366    }
    13991367
  • 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
     
    9698# Install headers so that plugins can compile independently
    9799inc.path = $${PREFIX}/include/mythtv/
    98100inc.files  = dialogbox.h mythcontext.h
    99 inc.files += mythwidgets.h remotefile.h oldsettings.h volumecontrol.h
     101inc.files += mythwidgets.h remotefile.h oldsettings.h
    100102inc.files += settings.h uitypes.h xmlparse.h mythplugin.h mythdialogs.h
    101103inc.files += audiooutput.h audiosettings.h audiooutputsettings.h util.h
    102104inc.files += inetcomms.h mythmedia.h mythcdrom.h mythwizard.h schemawizard.h dbutil.h
    103105inc.files += uilistbtntype.h generictree.h managedlist.h mythmediamonitor.h
    104 inc.files += visual.h volumebase.h output.h langsettings.h
     106inc.files += visual.h volumecontrol.h volumecontrolmanager.h output.h langsettings.h
    105107inc.files += mythexp.h mythpluginapi.h storagegroupeditor.h
    106108inc.files += mythconfigdialogs.h mythconfiggroups.h
    107109inc.files += mythterminal.h mythdeque.h mythuifilebrowser.h
     
    120122
    121123using_oss {
    122124    DEFINES += USING_OSS
    123     SOURCES += audiooutputoss.cpp
    124     HEADERS += audiooutputoss.h
     125    SOURCES += audiooutputoss.cpp volumecontroloss.cpp
     126    HEADERS += audiooutputoss.h volumecontroloss.h
    125127}
    126128
    127129using_pulse {
     
    149151
    150152mingw {
    151153    DEFINES += USING_MINGW
    152     SOURCES += mediamonitor-windows.cpp audiooutputwin.cpp audiooutputdx.cpp
    153     HEADERS += mediamonitor-windows.h   audiooutputwin.h   audiooutputdx.h
    154     LIBS += -lpthread -lwinmm -lws2_32
     154    SOURCES += mediamonitor-windows.cpp
     155    HEADERS += mediamonitor-windows.h
     156    SOURCES += audiooutputwin.cpp audiooutputdx.cpp volumecontrolendpoint.cpp
     157    HEADERS += audiooutputwin.h   audiooutputdx.h   volumecontrolendpoint.h
     158    LIBS += -lpthread -lwinmm -lws2_32 -lole32
    155159}
    156160
    157161macx {
    158     HEADERS += audiooutputca.h
    159     SOURCES += audiooutputca.cpp
     162    DEFINES += USE_COREAUDIO
     163    HEADERS += audiooutputca.h volumecontrolcoreaudio.h
     164    SOURCES += audiooutputca.cpp volumecontrolcoreaudio.cpp
    160165    HEADERS += mythcdrom-darwin.h
    161166    SOURCES += mythcdrom-darwin.cpp
    162167
     
    195200
    196201using_alsa {
    197202    DEFINES += USE_ALSA
    198     HEADERS += audiooutputalsa.h
    199     SOURCES += audiooutputalsa.cpp
     203    HEADERS += audiooutputalsa.h volumecontrolalsa.h
     204    SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp
    200205}
    201206
    202207using_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);
     
    222221    else
    223222        OERROR("Unable to get audio card capabilities");
    224223
    225     // Setup volume control
    226     if (internal_vol)
    227         VolumeInit();
    228 
    229224    // Device opened successfully
    230225    return true;
    231226}
     
    236231        close(audiofd);
    237232
    238233    audiofd = -1;
    239 
    240     VolumeCleanup();
    241234}
    242235
    243236
     
    277270    return soundcard_buffer;
    278271}
    279272
    280 void AudioOutputOSS::VolumeInit()
    281 {
    282     mixerfd = -1;
    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         int 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

     
    488488                    | DSBCAPS_GLOBALFOCUS          // Allows background playing
    489489                    | DSBCAPS_LOCHARDWARE;         // Needed for 5.1 on emu101k
    490490
    491     if (!m_UseSPDIF)
    492         dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME;     // Allow volume control
    493 
    494491    dsbdesc.dwBufferBytes = soundcard_buffer_size; // buffer size
    495492    dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf;
    496493
     
    561558    return buffered;
    562559}
    563560
    564 int AudioOutputDX::GetVolumeChannel(int channel) const
    565 {
    566     HRESULT dsresult;
    567     long dxVolume = 0;
    568     int volume;
    569 
    570     if (m_UseSPDIF)
    571         return 100;
    572 
    573     dsresult = IDirectSoundBuffer_GetVolume(m_priv->dsbuffer, &dxVolume);
    574     volume = (int)(pow(10,(float)dxVolume/20)*100);
    575 
    576     if (dsresult != DS_OK)
    577     {
    578         VBERROR(QString("Failed to get volume %1").arg(dxVolume));
    579         return volume;
    580     }
    581 
    582     VBAUDIO(QString("Got volume %1").arg(volume));
    583     return volume;
    584 }
    585 
    586 void AudioOutputDX::SetVolumeChannel(int channel, int volume)
    587 {
    588     HRESULT dsresult;
    589     float dbAtten = 20 * log10((float)volume/100);
    590     long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0f * dbAtten);
    591 
    592     if (m_UseSPDIF)
    593         return;
    594 
    595     // dxVolume is attenuation in 100ths of a decibel
    596     dsresult = IDirectSoundBuffer_SetVolume(m_priv->dsbuffer, dxVolume);
    597 
    598     if (dsresult != DS_OK)
    599     {
    600         VBERROR(QString("Failed to set volume %1").arg(dxVolume));
    601         return;
    602     }
    603 
    604     VBAUDIO(QString("Set volume %1").arg(dxVolume));
    605 }
    606 
    607561QMap<int, QString> *AudioOutputDX::GetDXDevices(void)
    608562{
    609563    AudioOutputDXPrivate *tmp_priv = new AudioOutputDXPrivate(NULL);
  • 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

     
    88#include "audiosettings.h"
    99#include "audiooutputsettings.h"
    1010#include "mythcorecontext.h"
    11 #include "volumebase.h"
    1211#include "output.h"
    1312
    14 class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
     13class MPUBLIC AudioOutput : public OutputListeners
    1514{
    1615 public:
    1716    class AudioDeviceConfig
     
    3938    static AudioOutput *OpenAudio(
    4039        const QString &audiodevice, const QString &passthrudevice,
    4140        AudioFormat format, int channels, int codec, int samplerate,
    42         AudioOutputSource source, bool set_initial_vol, bool passthru,
    43         int upmixer_startup = 0);
     41        AudioOutputSource source, bool passthru, int upmixer_startup = 0);
    4442    static AudioOutput *OpenAudio(AudioSettings &settings,
    4543                                  bool willsuspendpa = true);
    4644    static AudioOutput *OpenAudio(
     
    4947        bool willsuspendpa = true);
    5048
    5149    AudioOutput() :
    52         VolumeBase(),             OutputListeners(),
     50        OutputListeners(),
    5351        lastError(QString::null), lastWarn(QString::null) {}
    5452
    5553    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

     
    1616    AudioOutputDX(const AudioSettings &settings);
    1717    virtual ~AudioOutputDX();
    1818
    19     virtual int  GetVolumeChannel(int channel) const;
    20     virtual void SetVolumeChannel(int channel, int volume);
    2119    static QMap<int, QString> *GetDXDevices(void);
    2220
    2321  protected:
  • 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:
     
    3734    inline int SetParameters(snd_pcm_t *handle, snd_pcm_format_t format,
    3835                             uint channels, uint rate, uint buffer_time,
    3936                             uint period_time);
    40     // Volume related
    41     bool OpenMixer(void);
    4237
    4338  private:
    4439    snd_pcm_t   *pcm_handle;
     
    4843    QMutex       killAudioLock;
    4944    snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*,
    5045                                        snd_pcm_uframes_t);
    51     struct {
    52         QString            device;
    53         QString            control;
    54         snd_mixer_t*       handle;
    55         snd_mixer_elem_t*  elem;
    56         long               volmin;
    57         long               volmax;
    58         long               volrange;
    59     } m_mixer;
    60 
    6146};
    6247#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

     
    2929#include "iso639.h"
    3030#include "playbackbox.h"
    3131#include "globalsettings.h"
     32#include "libmyth/volumecontrolmanager.h"
    3233#include "recordingprofile.h"
    3334#include "mythxdisplay.h"
    3435#include "DisplayRes.h"
     
    511512    return gc;
    512513}
    513514
    514 static HostCheckBox *MythControlsVolume()
    515 {
    516     HostCheckBox *gc = new HostCheckBox("MythControlsVolume");
    517     gc->setLabel(QObject::tr("Use internal volume controls"));
    518     gc->setValue(true);
    519     gc->setHelpText(QObject::tr("If enabled, MythTV will control the PCM and "
    520                     "master mixer volume. Disable this option if you prefer "
    521                     "to control the volume externally (for example, using "
    522                     "your amplifier) or if you use an external mixer program."));
    523     return gc;
    524 }
    525 
    526515static HostComboBox *MixerDevice()
    527516{
    528517    HostComboBox *gc = new HostComboBox("MixerDevice", true);
    529518    gc->setLabel(QObject::tr("Mixer device"));
     519    gc->addSelection(QObject::tr("Disabled"), QString());
    530520
    531 #ifdef USING_OSS
    532     QDir dev("/dev", "mixer*", QDir::Name, QDir::System);
    533     gc->fillSelectionsFromDir(dev);
     521    QHash<QString, QString> controls = VolumeControlManager::Enumerate();
    534522
    535     dev.setPath("/dev/sound");
    536     if (dev.exists())
     523    for (QHash<QString, QString>::const_iterator control = controls.begin();
     524         control != controls.end(); ++control)
    537525    {
    538         gc->fillSelectionsFromDir(dev);
     526        gc->addSelection(control.value(), control.key());
    539527    }
    540 #endif
    541 #ifdef USING_ALSA
    542     gc->addSelection("ALSA:default", "ALSA:default");
    543 #endif
    544 #ifdef USING_MINGW
    545     gc->addSelection("DirectX:", "DirectX:");
    546     gc->addSelection("Windows:", "Windows:");
    547 #endif
    548 #if !defined(USING_MINGW)
    549     gc->addSelection("software", "software");
    550     gc->setHelpText(QObject::tr("Setting the mixer device to \"software\" "
    551                     "lets MythTV control the volume of all audio at the "
    552                     "expense of a slight quality loss."));
    553 #endif
    554528
    555529    return gc;
    556530}
    557531
    558 static const char* MixerControlControls[] = { "PCM",
    559                                               "Master" };
    560 
    561 static HostComboBox *MixerControl()
    562 {
    563     HostComboBox *gc = new HostComboBox("MixerControl", true);
    564     gc->setLabel(QObject::tr("Mixer controls"));
    565     for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);
    566          ++i)
    567     {
    568         gc->addSelection(QObject::tr(MixerControlControls[i]),
    569                          MixerControlControls[i]);
    570     }
    571 
    572     gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));
    573     return gc;
    574 }
    575 
    576 static HostSlider *MixerVolume()
    577 {
    578     HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);
    579     gs->setLabel(QObject::tr("Master mixer volume"));
    580     gs->setValue(70);
    581     gs->setHelpText(QObject::tr("Initial volume for the Master mixer. "
    582                     "This affects all sound created by the audio device. "
    583                     "Note: Do not set this too low."));
    584     return gs;
    585 }
    586 
    587 static HostSlider *PCMVolume()
    588 {
    589     HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);
    590     gs->setLabel(QObject::tr("PCM mixer volume"));
    591     gs->setValue(70);
    592     gs->setHelpText(QObject::tr("Initial volume for PCM output. Using the "
    593                     "volume keys in MythTV will adjust this parameter."));
    594     return gs;
    595 }
    596 
    597532static HostCheckBox *DecodeExtraAudio()
    598533{
    599534    HostCheckBox *gc = new HostCheckBox("DecodeExtraAudio");
     
    33363271    return gs;
    33373272}
    33383273
    3339 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup
     3274static ConfigurationGroup *AudioMixerSettingsGroup()
    33403275{
    3341   public:
    3342     AudioMixerSettingsGroup() :
    3343         TriggeredConfigurationGroup(false, true, false, false)
    3344     {
    3345         setLabel(QObject::tr("Audio Mixer"));
    3346         setUseLabel(false);
     3276    ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false);
     3277   
     3278    vcg->setLabel(QObject::tr("Audio Mixer"));
     3279    vcg->setUseLabel(false);
    33473280
    3348         Setting *volumeControl = MythControlsVolume();
    3349         addChild(volumeControl);
     3281    vcg->addChild(MixerDevice());
    33503282
    3351         // Mixer settings
    3352         ConfigurationGroup *settings =
    3353             new VerticalConfigurationGroup(false, true, false, false);
    3354         settings->addChild(MixerDevice());
    3355         settings->addChild(MixerControl());
    3356         settings->addChild(MixerVolume());
    3357         settings->addChild(PCMVolume());
     3283    return vcg;
     3284}
    33583285
    3359         ConfigurationGroup *dummy =
    3360             new VerticalConfigurationGroup(false, true, false, false);
    3361 
    3362         // Show Mixer config only if internal volume controls enabled
    3363         setTrigger(volumeControl);
    3364         addTarget("0", dummy);
    3365         addTarget("1", settings);
    3366     }
    3367 };
    3368 
    33693286static HostComboBox *MythLanguage()
    33703287{
    33713288    HostComboBox *gc = new HostComboBox("Language");
     
    40653982
    40663983    addChild(new AudioConfigSettings());
    40673984
    4068     addChild(new AudioMixerSettingsGroup());
     3985    addChild(AudioMixerSettingsGroup());
    40693986
    40703987    VerticalConfigurationGroup *general =
    40713988        new VerticalConfigurationGroup(false, true, false, false);
  • mythtv/programs/mythtranscode/transcode.cpp

     
    141141        return last_audiotime;
    142142    }
    143143
    144     virtual int GetVolumeChannel(int) const
    145     {
    146         // Do nothing
    147         return 100;
    148     }
    149     virtual void SetVolumeChannel(int, int)
    150     {
    151         // Do nothing
    152     }
    153     virtual void SetVolumeAll(int)
    154     {
    155         // Do nothing
    156     }
    157     virtual uint GetCurrentVolume(void) const
    158     {
    159         // Do nothing
    160         return 100;
    161     }
    162     virtual void SetCurrentVolume(int)
    163     {
    164         // Do nothing
    165     }
    166     virtual void AdjustCurrentVolume(int)
    167     {
    168         // Do nothing
    169     }
    170     virtual void SetMute(bool)
    171     {
    172         // Do nothing
    173     }
    174     virtual void ToggleMute(void)
    175     {
    176         // Do nothing
    177     }
    178     virtual MuteState GetMuteState(void) const
    179     {
    180         // Do nothing
    181         return kMuteOff;
    182     }
    183     virtual MuteState IterateMutedChannels(void)
    184     {
    185         // Do nothing
    186         return kMuteOff;
    187     }
    188144    virtual bool ToggleUpmix(void)
    189145    {
    190146        // Do nothing
    191147        return false;
    192148    }
    193149
    194     virtual void SetSWVolume(int new_volume, bool save)
    195     {
    196         // Do nothing
    197         return;
    198     }
    199     virtual int GetSWVolume(void)
    200     {
    201         // Do nothing
    202         return 100;
    203     }
    204 
    205150    //  These are pure virtual in AudioOutput, but we don't need them here
    206151    virtual void bufferOutputData(bool){ return; }
    207152    virtual int readOutputData(unsigned char*, int ){ return 0; }