mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
libarmbox: hdmi_cec add option to regulate audio systems volume via CEC, better log readability
Signed-off-by: Thilo Graf <dbt@novatux.de>
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include "../libspark/video_lib.h"
|
#include "../libspark/video_lib.h"
|
||||||
#elif HAVE_ARM_HARDWARE
|
#elif HAVE_ARM_HARDWARE
|
||||||
#include "../libarmbox/video_lib.h"
|
#include "../libarmbox/video_lib.h"
|
||||||
|
#include "../libarmbox/hdmi_cec.h"
|
||||||
#elif HAVE_AZBOX_HARDWARE
|
#elif HAVE_AZBOX_HARDWARE
|
||||||
#include "../azbox/video_lib.h"
|
#include "../azbox/video_lib.h"
|
||||||
#elif HAVE_GENERIC_HARDWARE
|
#elif HAVE_GENERIC_HARDWARE
|
||||||
|
@@ -69,8 +69,9 @@ hdmi_cec * CEC = hdmi_cec::getInstance();
|
|||||||
|
|
||||||
hdmi_cec::hdmi_cec()
|
hdmi_cec::hdmi_cec()
|
||||||
{
|
{
|
||||||
standby_cec_activ = autoview_cec_activ = standby = false;
|
standby_cec_activ = autoview_cec_activ = standby = muted = false;
|
||||||
hdmiFd = -1;
|
hdmiFd = -1;
|
||||||
|
volume = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdmi_cec::~hdmi_cec()
|
hdmi_cec::~hdmi_cec()
|
||||||
@@ -267,7 +268,7 @@ void hdmi_cec::SendCECMessage(struct cec_message &txmessage)
|
|||||||
{
|
{
|
||||||
sprintf(str+(i*6),"[0x%02X]", txmessage.data[i]);
|
sprintf(str+(i*6),"[0x%02X]", txmessage.data[i]);
|
||||||
}
|
}
|
||||||
lt_info("[CEC] send message 0x%02X >> 0x%02X '%s' (%s)\n", txmessage.initiator, txmessage.destination, ToString((cec_opcode)txmessage.data[0]), str);
|
lt_info("[CEC] send message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n",ToString((cec_logical_address)txmessage.initiator), txmessage.destination == 0xf ? "all" : ToString((cec_logical_address)txmessage.destination), txmessage.initiator, txmessage.destination, ToString((cec_opcode)txmessage.data[0]), str);
|
||||||
struct cec_msg msg;
|
struct cec_msg msg;
|
||||||
cec_msg_init(&msg, txmessage.initiator, txmessage.destination);
|
cec_msg_init(&msg, txmessage.initiator, txmessage.destination);
|
||||||
memcpy(&msg.msg[1], txmessage.data, txmessage.length);
|
memcpy(&msg.msg[1], txmessage.data, txmessage.length);
|
||||||
@@ -324,6 +325,9 @@ void hdmi_cec::SetCECState(bool state)
|
|||||||
message.data[2] = physicalAddress[1];
|
message.data[2] = physicalAddress[1];
|
||||||
message.length = 3;
|
message.length = 3;
|
||||||
SendCECMessage(message);
|
SendCECMessage(message);
|
||||||
|
usleep(10000);
|
||||||
|
|
||||||
|
request_audio_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -517,10 +521,20 @@ void hdmi_cec::Receive()
|
|||||||
{
|
{
|
||||||
sprintf(str+(i*6),"[0x%02X]", rxmessage.data[i]);
|
sprintf(str+(i*6),"[0x%02X]", rxmessage.data[i]);
|
||||||
}
|
}
|
||||||
lt_info("[CEC] received message 0x%02X << 0x%02X '%s' (%s)\n", rxmessage.destination, rxmessage.initiator, ToString((cec_opcode)rxmessage.opcode), str);
|
lt_info("[CEC] received message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n",ToString((cec_logical_address)rxmessage.initiator), rxmessage.destination == 0xf ? "all" : ToString((cec_logical_address)rxmessage.destination), rxmessage.initiator, rxmessage.destination, ToString((cec_opcode)rxmessage.opcode), str);
|
||||||
|
|
||||||
switch (rxmessage.opcode)
|
switch (rxmessage.opcode)
|
||||||
{
|
{
|
||||||
|
case CEC_OPCODE_REPORT_AUDIO_STATUS:
|
||||||
|
{
|
||||||
|
muted = ((rxmessage.data[1] & 0x80) == 0x80);
|
||||||
|
volume = rxmessage.data[1] & 0x7F;
|
||||||
|
if (muted)
|
||||||
|
lt_debug("[CEC] %s volume muted\n", ToString((cec_logical_address)rxmessage.initiator));
|
||||||
|
else
|
||||||
|
lt_debug("[CEC] %s volume %d \n", ToString((cec_logical_address)rxmessage.initiator), volume);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CEC_OPCODE_DEVICE_VENDOR_ID:
|
case CEC_OPCODE_DEVICE_VENDOR_ID:
|
||||||
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
|
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
|
||||||
{
|
{
|
||||||
@@ -564,7 +578,7 @@ void hdmi_cec::handleCode(long code, bool keypressed)
|
|||||||
}
|
}
|
||||||
if (keypressed)
|
if (keypressed)
|
||||||
{
|
{
|
||||||
if (rc_send(evd, code, KEY_PRESSED) < 0)
|
if (rc_send(evd, code, CEC_KEY_PRESSED) < 0)
|
||||||
{
|
{
|
||||||
lt_debug("[CEC] writing 'KEY_PRESSED' event failed");
|
lt_debug("[CEC] writing 'KEY_PRESSED' event failed");
|
||||||
close(evd);
|
close(evd);
|
||||||
@@ -574,7 +588,7 @@ void hdmi_cec::handleCode(long code, bool keypressed)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (rc_send(evd, code, KEY_RELEASED) < 0)
|
if (rc_send(evd, code, CEC_KEY_RELEASED) < 0)
|
||||||
{
|
{
|
||||||
lt_debug("[CEC] writing 'KEY_RELEASED' event failed");
|
lt_debug("[CEC] writing 'KEY_RELEASED' event failed");
|
||||||
close(evd);
|
close(evd);
|
||||||
@@ -605,3 +619,51 @@ void hdmi_cec::rc_sync(int fd)
|
|||||||
ev.value = 0;
|
ev.value = 0;
|
||||||
write(fd, &ev, sizeof(ev));
|
write(fd, &ev, sizeof(ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::send_key(unsigned char key, unsigned char destination)
|
||||||
|
{
|
||||||
|
struct cec_message txmessage;
|
||||||
|
txmessage.destination = destination;
|
||||||
|
txmessage.initiator = logicalAddress;
|
||||||
|
txmessage.data[0] = CEC_OPCODE_USER_CONTROL_PRESSED;
|
||||||
|
txmessage.data[1] = key;
|
||||||
|
txmessage.length = 2;
|
||||||
|
SendCECMessage(txmessage);
|
||||||
|
usleep(10000);
|
||||||
|
|
||||||
|
txmessage.destination = destination;
|
||||||
|
txmessage.initiator = logicalAddress;
|
||||||
|
txmessage.data[0] = CEC_OPCODE_USER_CONTROL_RELEASE;
|
||||||
|
txmessage.data[1] = key;
|
||||||
|
txmessage.length = 2;
|
||||||
|
SendCECMessage(txmessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::request_audio_status()
|
||||||
|
{
|
||||||
|
struct cec_message txmessage;
|
||||||
|
txmessage.destination = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
|
||||||
|
txmessage.initiator = logicalAddress;
|
||||||
|
txmessage.data[0] = CEC_OPCODE_GIVE_AUDIO_STATUS;
|
||||||
|
txmessage.length = 1;
|
||||||
|
SendCECMessage(txmessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdmi_cec::vol_up()
|
||||||
|
{
|
||||||
|
send_key(CEC_USER_CONTROL_CODE_VOLUME_UP, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
|
||||||
|
usleep(50000);
|
||||||
|
request_audio_status();
|
||||||
|
}
|
||||||
|
void hdmi_cec::vol_down()
|
||||||
|
{
|
||||||
|
send_key(CEC_USER_CONTROL_CODE_VOLUME_DOWN, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
|
||||||
|
usleep(50000);
|
||||||
|
request_audio_status();
|
||||||
|
}
|
||||||
|
void hdmi_cec::toggle_mute()
|
||||||
|
{
|
||||||
|
send_key(CEC_USER_CONTROL_CODE_MUTE, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
|
||||||
|
usleep(50000);
|
||||||
|
request_audio_status();
|
||||||
|
}
|
||||||
|
@@ -38,10 +38,11 @@ struct addressinfo
|
|||||||
unsigned char type;
|
unsigned char type;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum
|
||||||
KEY_RELEASED = 0,
|
{
|
||||||
KEY_PRESSED,
|
CEC_KEY_RELEASED = 0,
|
||||||
KEY_AUTOREPEAT
|
CEC_KEY_PRESSED,
|
||||||
|
CEC_KEY_AUTOREPEAT
|
||||||
};
|
};
|
||||||
|
|
||||||
class hdmi_cec : public OpenThreads::Thread
|
class hdmi_cec : public OpenThreads::Thread
|
||||||
@@ -62,6 +63,10 @@ private:
|
|||||||
int rc_send(int fd, unsigned int code, unsigned int value);
|
int rc_send(int fd, unsigned int code, unsigned int value);
|
||||||
void rc_sync(int fd);
|
void rc_sync(int fd);
|
||||||
bool standby;
|
bool standby;
|
||||||
|
void send_key(unsigned char key, unsigned char destination);
|
||||||
|
void request_audio_status();
|
||||||
|
bool muted;
|
||||||
|
int volume;
|
||||||
protected:
|
protected:
|
||||||
bool running;
|
bool running;
|
||||||
public:
|
public:
|
||||||
@@ -75,4 +80,15 @@ public:
|
|||||||
void SetCECState(bool state);
|
void SetCECState(bool state);
|
||||||
void ReportPhysicalAddress();
|
void ReportPhysicalAddress();
|
||||||
bool standby_cec_activ;
|
bool standby_cec_activ;
|
||||||
|
void vol_up();
|
||||||
|
void vol_down();
|
||||||
|
void toggle_mute();
|
||||||
|
int GetVolume()
|
||||||
|
{
|
||||||
|
return volume;
|
||||||
|
};
|
||||||
|
bool isMuted()
|
||||||
|
{
|
||||||
|
return muted;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@@ -630,6 +630,46 @@ static const char *ToString(const cec_user_control_code key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *ToString(cec_logical_address la)
|
||||||
|
{
|
||||||
|
switch (la & 0xf)
|
||||||
|
{
|
||||||
|
case CECDEVICE_TV:
|
||||||
|
return "TV";
|
||||||
|
case CECDEVICE_RECORDINGDEVICE1:
|
||||||
|
return "Recording Device 1";
|
||||||
|
case CECDEVICE_RECORDINGDEVICE2:
|
||||||
|
return "Recording Device 2";
|
||||||
|
case CECDEVICE_TUNER1:
|
||||||
|
return "Tuner 1";
|
||||||
|
case CECDEVICE_PLAYBACKDEVICE1:
|
||||||
|
return "Playback Device 1";
|
||||||
|
case CECDEVICE_AUDIOSYSTEM:
|
||||||
|
return "Audio System";
|
||||||
|
case CECDEVICE_TUNER2:
|
||||||
|
return "Tuner 2";
|
||||||
|
case CECDEVICE_TUNER3:
|
||||||
|
return "Tuner 3";
|
||||||
|
case CECDEVICE_PLAYBACKDEVICE2:
|
||||||
|
return "Playback Device 2";
|
||||||
|
case CECDEVICE_RECORDINGDEVICE3:
|
||||||
|
return "Recording Device 3";
|
||||||
|
case CECDEVICE_TUNER4:
|
||||||
|
return "Tuner 4";
|
||||||
|
case CECDEVICE_PLAYBACKDEVICE3:
|
||||||
|
return "Playback Device 3";
|
||||||
|
case CECDEVICE_RESERVED1:
|
||||||
|
return "Reserved 1";
|
||||||
|
case CECDEVICE_RESERVED2:
|
||||||
|
return "Reserved 2";
|
||||||
|
case CECDEVICE_FREEUSE:
|
||||||
|
return "Free use";
|
||||||
|
case CECDEVICE_UNREGISTERED:
|
||||||
|
default:
|
||||||
|
return "Unregistered";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static cec_opcode GetResponseOpcode(cec_opcode opcode)
|
static cec_opcode GetResponseOpcode(cec_opcode opcode)
|
||||||
{
|
{
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
|
Reference in New Issue
Block a user