From 78d859eb35b392098a58cb5fb76c49c845c7a698 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 24 Mar 2013 14:51:17 +0100 Subject: [PATCH] CVolume: add external volume control If CONFIGDIR/volume.sh is present it gets executed with parameter "up" or "down" and if unless it returns nonzero, the internal volume handling is skipped. This allows to e.g. control the volume on the TV with samsremote. --- src/driver/volume.cpp | 46 ++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/driver/volume.cpp b/src/driver/volume.cpp index 18ffc9c59..73c814adc 100644 --- a/src/driver/volume.cpp +++ b/src/driver/volume.cpp @@ -37,6 +37,7 @@ /* compat header from zapit/include */ #include #include +#include #include #include #include @@ -45,6 +46,8 @@ #include #endif +#define VOLUME_SCRIPT CONFIGDIR "/volume.sh" + extern CRemoteControl * g_RemoteControl; extern cAudio * audioDecoder; @@ -230,6 +233,7 @@ void CVolume::setVolume(const neutrino_msg_t key, const bool bDoPaint, bool nowa if (!g_RCInput) /* don't die... */ return; neutrino_msg_t msg = key; + static bool do_vol = true; /* false if volume is handled by external script */ int mode = CNeutrinoApp::getInstance()->getMode(); if (msg <= CRCInput::RC_MaxRC) { @@ -244,7 +248,7 @@ void CVolume::setVolume(const neutrino_msg_t key, const bool bDoPaint, bool nowa int vol = g_settings.current_volume; fb_pixel_t * pixbuf = NULL; - if(bDoPaint) { + if (bDoPaint && do_vol) { pixbuf = new fb_pixel_t[(vbar_w+ShadowOffset) * (vbar_h+ShadowOffset)]; if(pixbuf!= NULL) frameBuffer->SaveScreen(x, y, vbar_w+ShadowOffset, vbar_h+ShadowOffset, pixbuf); @@ -275,18 +279,31 @@ void CVolume::setVolume(const neutrino_msg_t key, const bool bDoPaint, bool nowa if ((msg == CRCInput::RC_plus || msg == CRCInput::RC_minus) || (sub_chan_keybind && (msg == CRCInput::RC_right || msg == CRCInput::RC_left))) { int dir = (msg == CRCInput::RC_plus || msg == CRCInput::RC_right) ? 1 : -1; + if (my_system(2, VOLUME_SCRIPT, dir > 0 ? "up" : "down") == 0) + { + do_vol = false; + /* clear all repeated events */ + neutrino_msg_t tmp = msg; + while (msg == tmp) + g_RCInput->getMsg(&tmp, &data, 0); + if (tmp != CRCInput::RC_timeout) + g_RCInput->postMsg(tmp, data); + } else + do_vol = true; if (CNeutrinoApp::getInstance()->isMuted() && (dir > 0 || g_settings.current_volume > 0)) { - if ((bDoPaint) && (pixbuf!= NULL)) { + if (pixbuf != NULL) { frameBuffer->RestoreScreen(x, y, vbar_w+ShadowOffset, vbar_h+ShadowOffset, pixbuf); delete [] pixbuf; } - AudioMute(false, true); - Init(); - setVolume(msg); - return; + if (do_vol) { + AudioMute(false, true); + Init(); + setVolume(msg); + return; + } } - if (!CNeutrinoApp::getInstance()->isMuted()) { + if (do_vol && !CNeutrinoApp::getInstance()->isMuted()) { /* current_volume is char, we need signed to catch v < 0 */ int v = g_settings.current_volume; v += dir * g_settings.current_volume_step; @@ -296,7 +313,7 @@ void CVolume::setVolume(const neutrino_msg_t key, const bool bDoPaint, bool nowa v = 0; g_settings.current_volume = 0; if (g_settings.show_mute_icon) { - if (bDoPaint && pixbuf != NULL) { + if (pixbuf != NULL) { frameBuffer->RestoreScreen(x, y, vbar_w+ShadowOffset, vbar_h+ShadowOffset, pixbuf); delete []pixbuf; } @@ -316,7 +333,8 @@ void CVolume::setVolume(const neutrino_msg_t key, const bool bDoPaint, bool nowa break; } - setvol(g_settings.current_volume); + if (do_vol) + setvol(g_settings.current_volume); timeoutEnd = CRCInput::calcTimeoutEnd(nowait ? 1 : 3); } else if (msg == NeutrinoMessages::EVT_VOLCHANGED) { @@ -327,28 +345,24 @@ void CVolume::setVolume(const neutrino_msg_t key, const bool bDoPaint, bool nowa break; } - if (bDoPaint) { + if (pixbuf) { if(vol != g_settings.current_volume) { vol = g_settings.current_volume; refreshVolumebar(g_settings.current_volume); + frameBuffer->blit(); } } - if (bDoPaint) - frameBuffer->blit(); - CVFD::getInstance()->showVolume(g_settings.current_volume); if (msg != CRCInput::RC_timeout) { g_RCInput->getMsgAbsoluteTimeout(&msg, &data, &timeoutEnd, true ); } } while (msg != CRCInput::RC_timeout); - if( (bDoPaint) && (pixbuf!= NULL) ) { + if (pixbuf != NULL) { frameBuffer->RestoreScreen(x, y, vbar_w+ShadowOffset, vbar_h+ShadowOffset, pixbuf); delete [] pixbuf; } - if (bDoPaint) - frameBuffer->blit(); } void CVolume::refreshVolumebar(int current_volume)