From 83b34da2dd1978d4ce71d28b26691006c9f4d37e Mon Sep 17 00:00:00 2001
From: Valentin Corfu <valentinx.corfu@intel.com>
Date: Wed, 8 Jan 2014 15:51:32 +0200
Subject: [PATCH 1/1] PATCH - alsa-plugins: Modify jack client name

  The current jack client name contains the process id of the application providing the audio samples.
  This leads to unpredictable jack client names which makes handling of the connections by a controlling application very hard.
  The modification now allows to specify a client name and the number of channels as parameters in the configuration file
  The given number of channels are then created but not connected.
  The implementation is backward compatible and simply adds a new configuration option to the plugin.

Signed-off-by: Valentin Corfu <valentinx.corfu@intel.com>

diff --git a/jack/pcm_jack.c b/jack/pcm_jack.c
index c51fe84..97328b1 100644
--- a/jack/pcm_jack.c
+++ b/jack/pcm_jack.c
@@ -32,6 +32,11 @@ typedef enum _jack_format {
 	SND_PCM_JACK_FORMAT_RAW
 } snd_pcm_jack_format_t;
 
+typedef enum _naming_scheme {
+  SND_PCM_JACK_STD_NAME,
+  SND_PCM_JACK_USER_DEFINED_NAME
+} snd_pcm_jack_naming_t;
+
 typedef struct {
 	snd_pcm_ioplug_t io;
 
@@ -325,7 +330,8 @@ static int make_nonblock(int fd)
 static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name,
 			     snd_config_t *playback_conf,
 			     snd_config_t *capture_conf,
-			     snd_pcm_stream_t stream, int mode)
+			     snd_pcm_stream_t stream, int mode,
+			     snd_pcm_jack_naming_t naming)
 {
 	snd_pcm_jack_t *jack;
 	int err;
@@ -356,11 +362,19 @@ static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name,
 		return -EINVAL;
 	}
 
-	if (snprintf(jack_client_name, sizeof(jack_client_name), "alsa-jack.%s%s.%d.%d", name,
-		     stream == SND_PCM_STREAM_PLAYBACK ? "P" : "C", getpid(), num++)
-	    >= (int)sizeof(jack_client_name)) {
-		fprintf(stderr, "%s: WARNING: JACK client name '%s' truncated to %d characters, might not be unique\n",
-			__func__, jack_client_name, (int)strlen(jack_client_name));
+	if (naming == SND_PCM_JACK_STD_NAME) {
+	  if (snprintf(jack_client_name, sizeof(jack_client_name), "alsa-jack.%s%s.%d.%d", name,
+	      stream == SND_PCM_STREAM_PLAYBACK ? "P" : "C", getpid(), num++)
+	      >= (int)sizeof(jack_client_name)) {
+	    fprintf(stderr, "%s: WARNING: JACK client name '%s' truncated to %d characters, might not be unique\n",
+	        __func__, jack_client_name, (int)strlen(jack_client_name));
+	  }
+	} else {
+    if (snprintf(jack_client_name, sizeof(jack_client_name), "%s", name)
+        >= (int)sizeof(jack_client_name)) {
+      fprintf(stderr, "%s: WARNING: JACK client name '%s' truncated to %d characters, might not be unique\n",
+          __func__, jack_client_name, (int)strlen(jack_client_name));
+    }
 	}
 
 	jack->client = jack_client_new(jack_client_name);
@@ -415,6 +429,10 @@ SND_PCM_PLUGIN_DEFINE_FUNC(jack)
 	snd_config_t *playback_conf = NULL;
 	snd_config_t *capture_conf = NULL;
 	int err;
+  long numChannels = 0;
+  long chan;
+  const char *localName = name;
+  snd_pcm_jack_naming_t naming = SND_PCM_JACK_STD_NAME;
 	
 	snd_config_for_each(i, next, conf) {
 		snd_config_t *n = snd_config_iterator_entry(i);
@@ -423,6 +441,15 @@ SND_PCM_PLUGIN_DEFINE_FUNC(jack)
 			continue;
 		if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0 || strcmp(id, "hint") == 0)
 			continue;
+		if (strcmp(id, "name") == 0) {
+		  snd_config_get_string(n, &localName);
+		  naming = SND_PCM_JACK_USER_DEFINED_NAME;
+		  continue;
+		}
+		if (strcmp(id, "nchan") == 0) {
+		  snd_config_get_integer(n, &numChannels);
+		  continue;
+		}
 		if (strcmp(id, "playback_ports") == 0) {
 			if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
 				SNDERR("Invalid type for %s", id);
@@ -443,7 +470,77 @@ SND_PCM_PLUGIN_DEFINE_FUNC(jack)
 		return -EINVAL;
 	}
 
-	err = snd_pcm_jack_open(pcmp, name, playback_conf, capture_conf, stream, mode);
+	if (   (naming == SND_PCM_JACK_USER_DEFINED_NAME)
+	    && (numChannels != 0)
+	    && (playback_conf == NULL)
+	    && (capture_conf == NULL)) {
+	  err = snd_config_make_compound(&playback_conf, "playback_ports", 0);
+	  if (err) {
+	    SNDERR("Error during snd_config_make_compound(p): %s\n", strerror(err));
+	    return err;
+	  }
+	  err = snd_config_make_compound(&capture_conf, "capture_ports", 0);
+	  if (err) {
+	    SNDERR("Error during snd_config_make_compound(c): %s\n", strerror(err));
+	    return err;
+	  }
+	  char value[4];
+	  for (chan=0; chan<numChannels; ++chan) {
+	    snprintf(value, sizeof(value), "%d", chan);
+	    snd_config_t *newLeafPlayback;
+	    snd_config_t *newLeafCapture;
+	    err = snd_config_imake_integer(&newLeafPlayback, value, chan);
+	    if (err) {
+	      SNDERR("Error during snd_config_imake_string(p): %s\n", strerror(err));
+	      return err;
+	    }
+	    err = snd_config_add(playback_conf, newLeafPlayback);
+	    if (err) {
+	      SNDERR("Error during snd_config_add(p): %s\n", strerror(err));
+	      return err;
+	    }
+	    err = snd_config_imake_integer(&newLeafCapture, value, chan);
+	    if (err) {
+	      SNDERR("Error during snd_config_imake_string(c): %s\n", strerror(err));
+	      return err;
+	    }
+	    err = snd_config_add(capture_conf, newLeafCapture);
+	    if (err) {
+	      SNDERR("Error during snd_config_add(c): %s\n", strerror(err));
+	      return err;
+	    }
+	  }
+	  err = snd_pcm_jack_open(pcmp, localName, playback_conf, capture_conf, stream, mode, naming);
+	  if (err) {
+	    SNDERR("Error during snd_pcm_jack_open: %s\n", strerror(err));
+	    return err;
+	  }
+
+	  err = snd_config_delete_compound_members(playback_conf);
+	  if (err) {
+	    SNDERR("Error during snd_config_delete_compound_members(p): %s\n", strerror(err));
+	    return err;
+	  }
+	  err = snd_config_delete_compound_members(capture_conf);
+	  if (err) {
+	    SNDERR("Error during snd_config_delete_compound_members(c): %s\n", strerror(err));
+	    return err;
+	  }
+	  err = snd_config_delete(playback_conf);
+	  if (err) {
+	    SNDERR("Error during snd_config_delete(p): %s\n", strerror(err));
+	    return err;
+	  }
+	  err = snd_config_delete(capture_conf);
+	  if (err) {
+	    SNDERR("Error during snd_config_delete(c): %s\n", strerror(err));
+	    return err;
+	  }
+	}
+	else
+	{
+    err = snd_pcm_jack_open(pcmp, localName, playback_conf, capture_conf, stream, mode, naming);
+	}
 
 	return err;
 }
-- 
1.7.9.5

