[alsa-devel] aconnect patch

lieven moors lievenmoors at gmail.com
Mon Mar 15 14:04:47 CET 2010


Hi everybody,

I'm a musician working intensively with Linux, and I like
writing programs.
Now I am working on a little command line utility to store
and restore all ALSA (midi) and JACK connections to/from an xml
file, and I've been using aconnect as an example for writing
the ALSA part.

I also needed a function to remove all connections, similar
to the remove_connections function in aconnect.
After using aconnect -x for some time, I noticed that it didn't
work as it should. Very often a number of connections were
left untouched after issuing this command.

After digging a little bit deeper, I think I found the reason for
the bug, and wrote a fix for it.

This is what I think happens in remove_connections:

Every time the for loop is executed, the index of the
snd_seq_query_subscribe_t is updated (+ 1).
If the connection has the right capabilities, it is removed.

When the connection is removed, I think the index gets
reassigned, and the next connection gets the position at index 0.
The result is that when one connection is removed, the
removal of the next connection is skipped (because the for
loop updates the index every time).

In the patch, I only update the index when unsubscribing fails,
or if it is unwanted because the capabilities or wrong.
This seems to solve the problems I had with aconnect -x,
and now it disconnects all connections as it should.

In the original function, connections are removed both ways.
First all ports with SND_SEQ_PORT_CAP_SUBS_READ are
checked, and associated connections removed, and then all
ports with SND_SEQ_PORT_CAP_SUBS_WRITE.

In the patch, I removed the second part, because I think it is
doing the same thing twice.

Please let me know what you think about this patch,
and if you think my reasoning is sane...

Greetings,

Lieven Moors



diff --git a/aconnect.c b/aconnect.c
index 1a50666..6092748 100644
--- a/aconnect.c
+++ b/aconnect.c
@@ -192,52 +192,33 @@ static void remove_connection(snd_seq_t *seq, 
snd_seq_client_info_t *cinfo,
                    snd_seq_port_info_t *pinfo, int count)
  {
      snd_seq_query_subscribe_t *query;
-
      snd_seq_query_subscribe_alloca(&query);
      snd_seq_query_subscribe_set_root(query, 
snd_seq_port_info_get_addr(pinfo));
-
      snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_READ);
      snd_seq_query_subscribe_set_index(query, 0);
-    for (; snd_seq_query_port_subscribers(seq, query) >= 0;
-         snd_seq_query_subscribe_set_index(query, 
snd_seq_query_subscribe_get_index(query) + 1)) {
+
+    while (snd_seq_query_port_subscribers(seq, query) >= 0)
+    {
          snd_seq_port_info_t *port;
          snd_seq_port_subscribe_t *subs;
          const snd_seq_addr_t *sender = 
snd_seq_query_subscribe_get_root(query);
          const snd_seq_addr_t *dest = 
snd_seq_query_subscribe_get_addr(query);
          snd_seq_port_info_alloca(&port);
-        if (snd_seq_get_any_port_info(seq, dest->client, dest->port, 
port) < 0)
-            continue;
-        if (!(snd_seq_port_info_get_capability(port) & 
SND_SEQ_PORT_CAP_SUBS_WRITE))
-            continue;
-        if (snd_seq_port_info_get_capability(port) & 
SND_SEQ_PORT_CAP_NO_EXPORT)
-            continue;
-        snd_seq_port_subscribe_alloca(&subs);
-        snd_seq_port_subscribe_set_queue(subs, 
snd_seq_query_subscribe_get_queue(query));
-        snd_seq_port_subscribe_set_sender(subs, sender);
-        snd_seq_port_subscribe_set_dest(subs, dest);
-        snd_seq_unsubscribe_port(seq, subs);
-    }

-    snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_WRITE);
-    snd_seq_query_subscribe_set_index(query, 0);
-    for (; snd_seq_query_port_subscribers(seq, query) >= 0;
-         snd_seq_query_subscribe_set_index(query, 
snd_seq_query_subscribe_get_index(query) + 1)) {
-        snd_seq_port_info_t *port;
-        snd_seq_port_subscribe_t *subs;
-        const snd_seq_addr_t *dest = 
snd_seq_query_subscribe_get_root(query);
-        const snd_seq_addr_t *sender = 
snd_seq_query_subscribe_get_addr(query);
-        snd_seq_port_info_alloca(&port);
-        if (snd_seq_get_any_port_info(seq, sender->client, 
sender->port, port) < 0)
-            continue;
-        if (!(snd_seq_port_info_get_capability(port) & 
SND_SEQ_PORT_CAP_SUBS_READ))
-            continue;
-        if (snd_seq_port_info_get_capability(port) & 
SND_SEQ_PORT_CAP_NO_EXPORT)
+        if ((snd_seq_get_any_port_info(seq, dest->client, dest->port, 
port) < 0) ||
+            !(snd_seq_port_info_get_capability(port) & 
SND_SEQ_PORT_CAP_SUBS_WRITE) ||
+            (snd_seq_port_info_get_capability(port) & 
SND_SEQ_PORT_CAP_NO_EXPORT))
+        {
+            snd_seq_query_subscribe_set_index(query, 
snd_seq_query_subscribe_get_index(query) + 1);
              continue;
+        }
          snd_seq_port_subscribe_alloca(&subs);
          snd_seq_port_subscribe_set_queue(subs, 
snd_seq_query_subscribe_get_queue(query));
          snd_seq_port_subscribe_set_sender(subs, sender);
          snd_seq_port_subscribe_set_dest(subs, dest);
-        snd_seq_unsubscribe_port(seq, subs);
+        if(snd_seq_unsubscribe_port(seq, subs) < 0){
+            snd_seq_query_subscribe_set_index(query, 
snd_seq_query_subscribe_get_index(query) + 1);
+        }
      }
  }








More information about the Alsa-devel mailing list