From 6ed251d811d2f14b8f8f9287eb24f4c60703eba0 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 9 Sep 2019 20:11:36 -0400 Subject: Update Kingfisher support for PipeWire and security changes Changes: - Restore the previous Gstreamer pipeline code that used the Si4689 ALSA input device as a source sink, now with an appropriate PipeWire output sink. This will be required until PipeWire adds some form of loopback service, which could be used instead. - Remove usage of the si_init script, as the sysfs accesses it performs cannot obviously be enabled via SMACK labelling in a safe fashion. Since the Si4689 on the KF will not work without the reset toggling done in si_init, the script is now called at boot by a systemd service added in a corresponding change in meta-agl-bsp. Bug-AGL: SPEC-2716 Signed-off-by: Scott Murray Change-Id: I5c5007d809efd4144dd5fbb25d1c07cfe1ff2b8f (cherry picked from commit f679e988816fec8d6671dda213f9d1a851524b69) --- binding/radio_impl_kingfisher.c | 77 +++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/binding/radio_impl_kingfisher.c b/binding/radio_impl_kingfisher.c index dcd3077..24c547f 100644 --- a/binding/radio_impl_kingfisher.c +++ b/binding/radio_impl_kingfisher.c @@ -23,17 +23,19 @@ #include #include #include +#include #include #include "radio_impl.h" #define SI_NODE "/sys/firmware/devicetree/base/si468x@0/compatible" -#define SI_INIT "/usr/bin/si_init" #define SI_CTL "/usr/bin/si_ctl" #define SI_CTL_CMDLINE_MAXLEN 128 #define SI_CTL_OUTPUT_MAXLEN 128 +#define GST_PIPELINE_LEN 256 + // Structure to describe FM band plans, all values in Hz. typedef struct { char *name; @@ -58,7 +60,7 @@ static int scan_valid_rssi_threshold = 128; static bool scanning = false; // stream state - +static GstElement *pipeline; static bool running; static void (*freq_callback)(uint32_t, void*); @@ -75,6 +77,7 @@ static int kf_init(void) char *value_str; char cmd[SI_CTL_CMDLINE_MAXLEN]; int rc; + char gst_pipeline_str[GST_PIPELINE_LEN]; if(present) return 0; @@ -83,9 +86,7 @@ static int kf_init(void) if(stat(SI_NODE, &statbuf) != 0) return -1; - // Check for Cogent's si_init script and si_ctl utility - if(stat(SI_INIT, &statbuf) != 0) - return -1; + // Check for Cogent's si_ctl utility if(stat(SI_CTL, &statbuf) != 0) return -1; @@ -146,12 +147,6 @@ static int kf_init(void) g_key_file_free(conf_file); } - rc = system(SI_INIT); - if(rc != 0) { - AFB_ERROR("si_init failed, rc = %d", rc); - return -1; - } - AFB_INFO("Using FM Bandplan: %s", known_fm_band_plans[bandplan].name); current_frequency = kf_get_min_frequency(BAND_FM); snprintf(cmd, @@ -168,6 +163,26 @@ static int kf_init(void) return -1; } + // Initialize GStreamer + gst_init(NULL, NULL); + + // Use PipeWire output + rc = snprintf(gst_pipeline_str, + GST_PIPELINE_LEN, + "alsasrc device=hw:radio ! queue ! audioconvert ! audioresample ! pwaudiosink stream-properties=\"p,media.role=Multimedia\""); + if(rc >= GST_PIPELINE_LEN) { + AFB_ERROR("pipeline string too long"); + return -1; + } + pipeline = gst_parse_launch(gst_pipeline_str, NULL); + if(!pipeline) { + AFB_ERROR("pipeline construction failed!"); + return -1; + } + + // Start pipeline in paused state + gst_element_set_state(pipeline, GST_STATE_PAUSED); + present = true; return 0; } @@ -300,25 +315,29 @@ static void kf_start(void) if(!present) return; - if (running) - return; - - /* TODO: start the stream in pipewire */ - - running = true; + if(!running) { + // Start pipeline + gst_element_set_state(pipeline, GST_STATE_PLAYING); + running = true; + } } static void kf_stop(void) { - if (!present) - return; - - if (!running) - return; - - /* TODO: stop the stream in pipewire */ - - running = false; + GstEvent *event; + + if(present && running) { + // Stop pipeline + running = false; + gst_element_set_state(pipeline, GST_STATE_PAUSED); + + // Flush pipeline + // This seems required to avoid stutters on starts after a stop + event = gst_event_new_flush_start(); + gst_element_send_event(GST_ELEMENT(pipeline), event); + event = gst_event_new_flush_stop(TRUE); + gst_element_send_event(GST_ELEMENT(pipeline), event); + } } static void kf_scan_start(radio_scan_direction_t direction, @@ -339,9 +358,9 @@ static void kf_scan_start(radio_scan_direction_t direction, scanning = true; snprintf(cmd, - SI_CTL_CMDLINE_MAXLEN, - "%s /dev/i2c-12 0x65 -l %s", - SI_CTL, direction == SCAN_FORWARD ? "up" : "down"); + SI_CTL_CMDLINE_MAXLEN, + "%s /dev/i2c-12 0x65 -l %s", + SI_CTL, direction == SCAN_FORWARD ? "up" : "down"); fp = popen(cmd, "r"); if(fp == NULL) { AFB_ERROR("Could not run: %s!", cmd); -- cgit 1.2.3-korg