summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--command_queue.h2
-rw-r--r--options.c1
-rw-r--r--options.h4
-rw-r--r--switchctl.c167
4 files changed, 147 insertions, 27 deletions
diff --git a/command_queue.h b/command_queue.h
index 7a475fd..d77a6f6 100644
--- a/command_queue.h
+++ b/command_queue.h
@@ -24,7 +24,7 @@
#include <sys/time.h>
-enum cmd_id_enum { SWITCH, TYPE, MODE, STATUS, LOG, LISTEN };
+enum cmd_id_enum { SWITCH, CHANNEL, TYPE, MODE, STATUS, LOG, LISTEN };
typedef enum cmd_id_enum cmd_id_t;
struct cmd_struct {
diff --git a/options.c b/options.c
index 37064c6..8cb11a8 100644
--- a/options.c
+++ b/options.c
@@ -231,6 +231,7 @@ void options_default(options_t* opt)
string_list_init(&opt->log_targets_);
opt->mode_ = MODE_MASTER;
+ opt->channel_ = CHAN_MAIN;
opt->conf_file_ = strdup("/etc/rhctl/switchctl.conf");
opt->command_sock_ = strdup("/var/run/rhctl/switchctl.sock");
opt->switch_dev_ = strdup("/dev/audioswitch");
diff --git a/options.h b/options.h
index e8e3930..4d070da 100644
--- a/options.h
+++ b/options.h
@@ -28,6 +28,9 @@
enum mode_enum { MODE_MASTER, MODE_STANDBY };
typedef enum mode_enum mode_t;
+enum channel_enum { CHAN_MAIN, CHAN_MUSIC };
+typedef enum channel_enum channel_t;
+
struct options_struct {
char* progname_;
int daemonize_;
@@ -38,6 +41,7 @@ struct options_struct {
string_list_t log_targets_;
mode_t mode_;
+ channel_t channel_;
char* conf_file_;
char* command_sock_;
char* switch_dev_;
diff --git a/switchctl.c b/switchctl.c
index dcf417c..5a7c94e 100644
--- a/switchctl.c
+++ b/switchctl.c
@@ -44,7 +44,8 @@ int send_command(int switch_fd, cmd_t* cmd)
char* c = NULL;
switch(cmd->cmd) {
- case SWITCH: c = cmd->param; break;
+ case SWITCH:
+ case CHANNEL: c = cmd->param; break;
case STATUS: c = "*0SL"; break;
}
@@ -81,6 +82,7 @@ int process_cmd_request(const char* cmd, cmd_id_t cmd_id, const char* param, int
client_t* c = client_find(client_lst, fd);
if(!c) {
log_printf(WARNING, "ignoring request from unknown client");
+ send_response(fd, "EEE: switch: client not found in client list?!");
return 0;
}
@@ -89,12 +91,13 @@ int process_cmd_request(const char* cmd, cmd_id_t cmd_id, const char* param, int
if((opt->mode_ == MODE_MASTER && c->type == STANDBY )||
(opt->mode_ == MODE_STANDBY && c->type == MASTER ))
{
- log_printf(INFO, "ignoring request from inactive system (%s)", c->type == MASTER ? "master" : "standby");
+ log_printf(INFO, "silently ignoring request from inactive system (%s)", c->type == MASTER ? "master" : "standby");
return 0;
}
if(!param) {
log_printf(INFO, "ignoring switch command without parameter");
+ send_response(fd, "EEE: switch: missing parameter");
return 0;
}
@@ -114,14 +117,9 @@ int process_cmd_request(const char* cmd, cmd_id_t cmd_id, const char* param, int
ch_name = &(param[5]);
ch_nr = &(cmd_param[4]);
}
- else if(!strncmp(param, "on ", 3)) {
+ else if(!strncmp(param, "select ", 7)) {
cmd_param = strdup("*0ii1");
- ch_name = &(param[3]);
- ch_nr = &(cmd_param[2]);
- }
- else if(!strncmp(param, "off ", 4)) {
- cmd_param = strdup("*0iiM1");
- ch_name = &(param[4]);
+ ch_name = &(param[7]);
ch_nr = &(cmd_param[2]);
}
else if(!strncmp(param, "add ", 4)) {
@@ -134,14 +132,14 @@ int process_cmd_request(const char* cmd, cmd_id_t cmd_id, const char* param, int
ch_name = &(param[3]);
ch_nr = &(cmd_param[2]);
}
- else if(!strncmp(param, "on2 ", 4)) {
- cmd_param = strdup("*0ii2");
- ch_name = &(param[4]);
+ else if(!strncmp(param, "mute ", 5)) {
+ cmd_param = strdup("*0iiM1");
+ ch_name = &(param[5]);
ch_nr = &(cmd_param[2]);
}
- else if(!strncmp(param, "off2 ", 5)) {
- cmd_param = strdup("*0iiM2");
- ch_name = &(param[5]);
+ else if(!strncmp(param, "select2 ", 8)) {
+ cmd_param = strdup("*0ii2");
+ ch_name = &(param[8]);
ch_nr = &(cmd_param[2]);
}
else if(!strncmp(param, "add2 ", 5)) {
@@ -154,13 +152,20 @@ int process_cmd_request(const char* cmd, cmd_id_t cmd_id, const char* param, int
ch_name = &(param[4]);
ch_nr = &(cmd_param[2]);
}
+ else if(!strncmp(param, "mute2 ", 6)) {
+ cmd_param = strdup("*0iiM2");
+ ch_name = &(param[6]);
+ ch_nr = &(cmd_param[2]);
+ }
else {
log_printf(INFO, "ignoring invalid switch command: '%s'", param);
+ send_response(fd, "EEE: switch: invalid command");
return 0;
}
char* ch_tmp = key_value_storage_find(&opt->alias_table_, ch_name);
if(!ch_tmp || ch_tmp[0] == 0 || ch_tmp[1] == 0 || ch_tmp[2] != 0) {
log_printf(ERROR, "invalid channel name or number: %s", ch_name);
+ send_response(fd, "EEE: switch: invalid channel name or number");
free(cmd_param);
return 0;
}
@@ -178,14 +183,17 @@ int process_cmd_request(const char* cmd, cmd_id_t cmd_id, const char* param, int
return ret;
if(cmd_id == STATUS) {
- char buf[30];
- snprintf(buf, 30, "Current Mode: %s", opt->mode_ == MODE_MASTER ? "Master" : "Standby");
- send_response(fd, buf);
+ char buf[2][30];
+ snprintf(buf[0], 30, "Current Mode: %s", opt->mode_ == MODE_MASTER ? "Master" : "Standby");
+ send_response(fd, buf[0]);
+ snprintf(buf[1], 30, "Current Channel: %s", opt->channel_ == CHAN_MAIN ? "Main" : "Music");
+ send_response(fd, buf[1]);
client_t* client;
int listener_cnt = 0;
for(client = client_lst; client; client = client->next)
if(client->status_listener && client->fd != fd) {
- send_response(client->fd, buf);
+ send_response(client->fd, buf[0]);
+ send_response(client->fd, buf[1]);
listener_cnt++;
}
log_printf(DEBUG, "sent status to %d additional listeners", listener_cnt);
@@ -196,6 +204,93 @@ int process_cmd_request(const char* cmd, cmd_id_t cmd_id, const char* param, int
return 0;
}
+int process_cmd_channel(const char* cmd, const char* param, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt)
+{
+ client_t* c = client_find(client_lst, fd);
+ if(!c) {
+ log_printf(WARNING, "ignoring request from unknown client");
+ send_response(fd, "EEE: channel: client not found in client list?!");
+ return 0;
+ }
+
+ if(c->type != MASTER && c->type != STANDBY) {
+ log_printf(WARNING, "ignoring request from client of wrong type");
+ send_response(fd, "EEE: channel: client type doesn't fit");
+ return 0;
+ }
+
+ if((opt->mode_ == MODE_MASTER && c->type == STANDBY )||
+ (opt->mode_ == MODE_STANDBY && c->type == MASTER ))
+ {
+ log_printf(INFO, "silently ignoring request from inactive system (%s)", c->type == MASTER ? "master" : "standby");
+ return 0;
+ }
+
+ if(!param) {
+ log_printf(INFO, "ignoring channel command without parameter");
+ send_response(fd, "EEE: channel: missing parameter");
+ return 0;
+ }
+
+ char* cmd_param = strdup("*0FDii*0FUii");
+ char* ch_from = NULL;
+ char* ch_to = NULL;
+ if(!strcmp(param, "main")) {
+ if(opt->mode_ == MODE_MASTER) {
+ ch_from = "master_music";
+ ch_to = "master_main";
+ }
+ else {
+ ch_from = "standby_music";
+ ch_to = "standby_main";
+ }
+ opt->channel_ = CHAN_MAIN;
+ }
+ else if(!strcmp(param, "music")) {
+ if(opt->mode_ == MODE_MASTER) {
+ ch_from = "master_main";
+ ch_to = "master_music";
+ }
+ else {
+ ch_from = "standby_main";
+ ch_to = "standby_music";
+ }
+ opt->channel_ = CHAN_MUSIC;
+ }
+
+
+ char* ch_nr_from = key_value_storage_find(&opt->alias_table_, ch_from);
+ if(!ch_nr_from || ch_nr_from[0] == 0 || ch_nr_from[1] == 0 || ch_nr_from[2] != 0) {
+ log_printf(ERROR, "invalid channel name or number: %s", ch_from);
+ send_response(fd, "EEE: channel: invalid channel name or number");
+ free(cmd_param);
+ return 0;
+ }
+
+ char* ch_nr_to = key_value_storage_find(&opt->alias_table_, ch_to);
+ if(!ch_nr_to || ch_nr_to[0] == 0 || ch_nr_to[1] == 0 || ch_nr_to[2] != 0) {
+ log_printf(ERROR, "invalid channel name or number: %s", ch_to);
+ send_response(fd, "EEE: channel: invalid channel name or number");
+ free(cmd_param);
+ return 0;
+ }
+
+ cmd_param[4] = ch_nr_from[0];
+ cmd_param[5] = ch_nr_from[1];
+ cmd_param[10] = ch_nr_to[0];
+ cmd_param[11] = ch_nr_to[1];
+
+ log_printf(DEBUG, "enqueing command to switch: '%s'", cmd_param);
+ int ret = cmd_push(cmd_q, fd, CHANNEL, cmd_param);
+ free(cmd_param);
+ if(ret)
+ return ret;
+
+ log_printf(NOTICE, "command: %s", cmd);
+
+ return 0;
+}
+
void process_cmd_type(const char* param, int fd, client_t* client_lst)
{
if(param) {
@@ -209,19 +304,24 @@ void process_cmd_type(const char* param, int fd, client_t* client_lst)
client->type = HEARTBEAT;
else {
log_printf(DEBUG, "unkown client type '%s'", param);
+ send_response(fd, "EEE: type: unknown client type");
return;
}
log_printf(DEBUG, "client %d type set to %s", fd, param);
}
- else
+ else {
log_printf(ERROR, "unable to set client type for %d: client not found", fd);
+ send_response(fd, "EEE: type: client not found in client list?!");
+ }
}
- else
+ else {
log_printf(ERROR, "unable to set client type for %d: empty parameter", fd);
+ send_response(fd, "EEE: type: missing parameter");
+ }
}
-void process_cmd_mode(const char* param, options_t* opt)
+void process_cmd_mode(const char* param, int fd, options_t* opt)
{
if(param) {
if(!strncmp(param, "master", 6))
@@ -230,11 +330,14 @@ void process_cmd_mode(const char* param, options_t* opt)
opt->mode_ = MODE_STANDBY;
else {
log_printf(DEBUG, "unkown mode '%s'", param);
+ send_response(fd, "EEE: mode: unknown mode");
return;
}
}
- else
+ else {
log_printf(ERROR, "unable to set mode: empty parameter");
+ send_response(fd, "EEE: mode: missing parameter");
+ }
log_printf(NOTICE, "new mode: %s", opt->mode_ == MODE_MASTER ? "master" : "standby");
}
@@ -258,13 +361,16 @@ void process_cmd_listen(const char* param, int fd, client_t* client_lst)
}
else {
log_printf(DEBUG, "unkown listener type '%s'", param);
+ send_response(fd, "EEE: listen: unkown type");
return;
}
}
log_printf(DEBUG, "listener %d requests %s messages", fd, param ? param:"all");
}
- else
+ else {
log_printf(ERROR, "unable to add listener %d", fd);
+ send_response(fd, "EEE: listen: client not found in client list?!");
+ }
}
int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt)
@@ -277,6 +383,8 @@ int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, op
cmd_id_t cmd_id;
if(!strncmp(cmd, "switch", 6))
cmd_id = SWITCH;
+ if(!strncmp(cmd, "channel", 7))
+ cmd_id = CHANNEL;
else if(!strncmp(cmd, "type", 4))
cmd_id = TYPE;
else if(!strncmp(cmd, "mode", 4))
@@ -290,13 +398,14 @@ int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, op
}
else {
log_printf(WARNING, "unknown command '%s'", cmd);
+ send_response(fd, "EEE: unknown command");
return 0;
}
char* param = strchr(cmd, ' ');
if(param)
param++;
- if(cmd_id == SWITCH || cmd_id == MODE) {
+ if(cmd_id == SWITCH || cmd_id == CHANNEL || cmd_id == MODE) {
char* resp;
asprintf(&resp, "Request: %s", cmd);
if(resp) {
@@ -323,8 +432,14 @@ int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, op
return ret;
break;
}
+ case CHANNEL: {
+ int ret = process_cmd_channel(cmd, param, fd, cmd_q, client_lst, opt);
+ if(ret)
+ return ret;
+ break;
+ }
case TYPE: process_cmd_type(param, fd, client_lst); break;
- case MODE: process_cmd_mode(param, opt); break;
+ case MODE: process_cmd_mode(param, fd, opt); break;
case LOG: {
if(param && param[0])
log_printf(NOTICE, "ext msg: %s", param);