]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Hook up active mode stuff to metadata, add two four-char codes, improve external...
authorMike Brady <mikebrady@eircom.net>
Mon, 21 Jan 2019 21:18:40 +0000 (21:18 +0000)
committerMike Brady <mikebrady@eircom.net>
Mon, 21 Jan 2019 21:18:40 +0000 (21:18 +0000)
activity_monitor.c
common.c
metadata_hub.c
metadata_hub.h
rtsp.c

index aea75cd9a32c940feb8539772836f6d16dc49f9d..53e3d7f1a2b4b725cf78e9aa6dbd0ea250916911 100644 (file)
@@ -39,6 +39,7 @@
 #include "config.h"
 
 #include "common.h"
+#include "rtsp.h"
 #include "activity_monitor.h"
 
 enum am_state {am_inactive, am_active, am_timing_out} state;
@@ -49,15 +50,23 @@ pthread_mutex_t activity_monitor_mutex;
 pthread_cond_t activity_monitor_cv;
 
 void going_active(int block) {
-  debug(1, "activity_monitor: state transitioning to \"active\" with%s blocking", block ? "" : "out");
+  // debug(1, "activity_monitor: state transitioning to \"active\" with%s blocking", block ? "" : "out");
   if (config.cmd_active_start)
     command_execute(config.cmd_active_start, "", block);
+#ifdef CONFIG_METADATA
+    debug(2, "abeg"); // active mode begin
+    send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
+#endif
 }
 
 void going_inactive(int block) {
-   debug(1, "activity_monitor: state transitioning to \"inactive\" with%s blocking", block ? "" : "out");
+   // debug(1, "activity_monitor: state transitioning to \"inactive\" with%s blocking", block ? "" : "out");
   if (config.cmd_active_stop)
     command_execute(config.cmd_active_stop, "", block);
+#ifdef CONFIG_METADATA
+    debug(2, "aend"); // active mode end
+    send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
+#endif
 }
 
 void activity_monitor_signify_activity(int active) {
@@ -127,14 +136,14 @@ void *activity_monitor_thread_code(void *arg) {
   do {
     switch (state) {
       case am_inactive:
-       debug(1,"am_state: am_inactive");
+       // debug(1,"am_state: am_inactive");
        while (player_state != ps_active)
           pthread_cond_wait(&activity_monitor_cv, &activity_monitor_mutex);               
         state = am_active;
         // going_active(); // this is done in activity_monitor_signify_activity         
       break;
       case am_active:
-       debug(1,"am_state: am_active");
+       // debug(1,"am_state: am_active");
         while (player_state != ps_inactive)
           pthread_cond_wait(&activity_monitor_cv, &activity_monitor_mutex);
         if (config.active_mode_timeout == 0.0) {
@@ -163,7 +172,7 @@ void *activity_monitor_thread_code(void *arg) {
         }      
       break;
       case am_timing_out:
-       debug(1,"am_state: am_timing_out");
+       // debug(1,"am_state: am_timing_out");
         rc = 0;
         while ((player_state != ps_active) && (rc != ETIMEDOUT)) {
 #ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
@@ -197,7 +206,7 @@ void *activity_monitor_thread_code(void *arg) {
 }
 
 void activity_monitor_start() {
-  debug(1,"activity_monitor_start");
+  // debug(1,"activity_monitor_start");
   pthread_create(&activity_monitor_thread, NULL, activity_monitor_thread_code, NULL);
 }
 
index a13546215c6ed5da5c54dd3ddb1cdf6d1ffdfa31..2c2ede621541cc814421e8a74df9a333dc1753c7 100644 (file)
--- a/common.c
+++ b/common.c
@@ -725,7 +725,8 @@ void command_start(void) {
                                     and if blocking is true, wait for
                                     process to finish */
         pid_t rc = waitpid(pid, 0, 0);                              /* wait for child to exit */
-        if (rc != pid) {
+        if ((rc != pid) && (errno != ECHILD)) {
+          // In this context, ECHILD means that the child process has already completed, I think!
           warn("Execution of on-start command returned an error.");
           debug(1, "on-start command %s finished with error %d", config.cmd_start, errno);
         }
@@ -779,7 +780,8 @@ void command_execute(const char *command, const char *extra_argument, const int
       if (block) { /* pid!=0 means parent process and if blocking is true, wait for
                                     process to finish */
         pid_t rc = waitpid(pid, 0, 0); /* wait for child to exit */
-        if (rc != pid) {
+        if ((rc != pid) && (errno != ECHILD)) {
+          // In this context, ECHILD means that the child process has already completed, I think!
           warn("Execution of command \"%s\" returned an error.", full_command);
           debug(1, "Command \"%s\" finished with error %d", full_command, errno);
         }
@@ -791,36 +793,8 @@ void command_execute(const char *command, const char *extra_argument, const int
 
 void command_stop(void) {
   // this has a cancellation point if waiting is enabled
-  if (config.cmd_stop) {
-    /*Spawn a child to run the program.*/
-    pid_t pid = fork();
-    if (pid == 0) { /* child process */
-      int argC;
-      char **argV;
-      // debug(1,"on-stop command found.");
-      if (poptParseArgvString(config.cmd_stop, &argC, (const char ***)&argV) !=
-          0) // note that argV should be free()'d after use, but we expect this fork to exit
-             // eventually.
-        debug(1, "Can't decipher on-stop command arguments");
-      else {
-        // debug(1,"Executing on-stop command %s",config.cmd_stop);
-        execv(argV[0], argV);
-        warn("Execution of on-stop command failed to start");
-        debug(1, "Error executing on-stop command %s", config.cmd_stop);
-        exit(127); /* only if execv fails */
-      }
-    } else {
-      if (config.cmd_blocking) { /* pid!=0 means parent process and if blocking is true, wait for
-                                    process to finish */
-        pid_t rc = waitpid(pid, 0, 0); /* wait for child to exit */
-        if (rc != pid) {
-          warn("Execution of on-stop command returned an error.");
-          debug(1, "Stop command %s finished with error %d", config.cmd_stop, errno);
-        }
-      }
-      // debug(1,"Continue after on-stop command");
-    }
-  }
+  if (config.cmd_stop)
+    command_execute(config.cmd_stop,"",config.cmd_blocking);
 }
 
 // this is for reading an unsigned 32 bit number, such as an RTP timestamp
index 84cd8076e3d7c39dfacc8c1d0a275e4de190f510..398ad35bd83a4677039c39d47a03a14311c1abcd 100644 (file)
@@ -535,6 +535,18 @@ void metadata_hub_process_metadata(uint32_t type, uint32_t code, char *data, uin
       break;
     // these could tell us about play / pause etc. but will only occur if metadata is enabled, so
     // we'll just ignore them
+    case 'abeg': {
+      metadata_hub_modify_prolog();
+      int changed = (metadata_store.active_state != AM_ACTIVE);
+      metadata_store.active_state = AM_ACTIVE;
+      metadata_hub_modify_epilog(changed);
+    } break;
+    case 'aend': {
+      metadata_hub_modify_prolog();
+      int changed = (metadata_store.active_state != AM_INACTIVE);
+      metadata_store.active_state = AM_INACTIVE;
+      metadata_hub_modify_epilog(changed);
+    } break;
     case 'pbeg': {
       metadata_hub_modify_prolog();
       int changed = (metadata_store.player_state != PS_PLAYING);
index 65e93a23831fabdeb63c0df3b92c72f7a450ecc1..7acc67228f36be1cee7162da8c5b927416cbafa6 100644 (file)
@@ -12,6 +12,11 @@ enum play_status_type {
   PS_PLAYING,
 } play_status_type;
 
+enum active_mode_type {
+  AM_INACTIVE = 0,
+  AM_ACTIVE,
+} active_mode_type;
+
 enum shuffle_status_type {
   SS_NOT_AVAILABLE = 0,
   SS_OFF,
@@ -77,6 +82,8 @@ typedef struct metadata_bundle {
 
   enum play_status_type
       player_state; // this is the state of the actual player itself, which can be a bit noisy.
+  enum active_mode_type
+      active_state;
 
   int speaker_volume; // this is the actual speaker volume, allowing for the main volume and the
                       // speaker volume control
diff --git a/rtsp.c b/rtsp.c
index 5a1cbd0595667709208dbbddacb3b4b92f0b1248..2fcd31038aacdf5c4c70d47539c3b2ef84114086 100644 (file)
--- a/rtsp.c
+++ b/rtsp.c
@@ -974,7 +974,7 @@ void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
             msg_add_header(resp, "Session", "1");
 
             resp->respcode = 200; // it all worked out okay
-            debug(1, "Connection %d: SETUP with UDP ports Control: %d, Timing: %d and Audio: %d.",
+            debug(2, "Connection %d: SETUP with UDP ports Control: %d, Timing: %d and Audio: %d.",
                   conn->connection_number, conn->local_control_port, conn->local_timing_port,
                   conn->local_audio_port);
 
@@ -1087,6 +1087,8 @@ void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *req,
 //    'PICT' -- the payload is a picture, either a JPEG or a PNG. Check the
 //    first few bytes to see
 //    which.
+//    'abeg' -- active mode entered. No arguments
+//    'aend' -- active mode exited. No arguments
 //    'pbeg' -- play stream begin. No arguments
 //    'pend' -- play stream end. No arguments
 //    'pfls' -- play stream flush. No arguments