diff --git a/src/jackpatch.c b/src/jackpatch.c index 372d37c..d734535 100644 --- a/src/jackpatch.c +++ b/src/jackpatch.c @@ -72,7 +72,7 @@ struct patch_record { char *client; char *port; } src , dst; - int active; /* true if patch has already been activate (by us) */ + int active; /* true if patch has already been activated (by us) */ struct patch_record *next; }; @@ -385,7 +385,7 @@ do_for_matching_patches ( const char *portname, void (*func)( struct patch_recor { struct patch_record *pr; - char client[REAL_JACK_PORT_NAME_SIZE]; //the length is too much. The value is client+port+1. But is guaranteed to be enouigh. + char client[REAL_JACK_PORT_NAME_SIZE]; //the length is technically too much. The value is client+port+1. But is guaranteed to be enough. char port[REAL_JACK_PORT_NAME_SIZE]; sscanf( portname, "%[^:]:%[^\n]", client, port ); @@ -485,7 +485,20 @@ static int stringsort ( const void *a, const void *b ) /** * Save all current connections to a file. + * + * Strategy: + * If there are no jack ports at all don't do anything. Else: + * + * Remember all currently known connections where one, or both, ports are missing from the jack graph. + * We consider these temporarily gone by accident. + * + * Clear the current save file. + * + * For each currently existing jack output port save all of it's connections. + * Save all these port-pairs in an empty file. Ports without connections are not saved. + ** */ + void snapshot ( const char *file ) { @@ -503,15 +516,85 @@ snapshot ( const char *file ) return; } - clear_all_patches(); + //Prepare a temporary table where all connection strings are held until the file is written at the bottom of this function. + //We first add all connections that are temporarily out of order (see below) and then all currently existing connections. const int table_increment = 16; int table_index = 0; size_t table_size = table_increment; char **table = (char**)malloc( sizeof( char * ) * table_increment ); + + //Before we forget the current state find all connections that we have in memory but where + //one or both ports are currently missing in the jack graph. + //We don't want to lose connections that are just temporarily not present. + struct patch_record *pr; + while ( patch_list ) + { + //A patch is one connection between a source and a destination. + //If an actual jack port source is connected to more than one destinations it will appear as it's own "patch" in this list. + //We only need to consider 1:1 point connections in this loop. + + //Traverse the linked list + pr = patch_list; + patch_list = pr->next; + + int remember_this_connection = 0; + + char * src_client_port; + char * dst_client_port; + asprintf( &src_client_port, "%s:%s", pr->src.client, pr->src.port ); + asprintf( &dst_client_port, "%s:%s", pr->dst.client, pr->dst.port ); + + jack_port_t *jp_t_src; + jp_t_src = jack_port_by_name( client, src_client_port ); //client is our own jackpatch-jack-client. + + if ( ! jp_t_src ) { + //The port does not exist anymore. We need to remember it! + //It doesn't matter if the destination port still exists, the file-writing below will only consider ports that are currently present and connected. + //printf("[jackpatch] We remember source %s but it does not exist anymore. Making sure it fill not be forgotten.\n", src_client_port); + remember_this_connection = 1; + } + else { + //The source port does still exist, but is it's connection still alive? + //Do not use jack_port_get_all_connections, we want to know if a specific destination is still there. + jack_port_t *jp_t_dst; + jp_t_dst = jack_port_by_name( client, dst_client_port ); //client is our own jackpatch-jack-client. + if ( ! jp_t_dst ) { + //The port does not exist anymore. We need to remember it! + //It doesn't matter if the destination port still exists, the file-writing below will only consider ports that are currently present and connected. + //printf("[jackpatch] We remember destination %s but it does not exist anymore. Making sure it fill not be forgotten.\n", dst_client_port); + remember_this_connection = 1; + } + } + if ( remember_this_connection ) { + //const char * pport = src_client_port; + //const char * pclient = dst_client_port; + + //This code is replicated below #TODO: create function. + char *s; + asprintf( &s, "%-40s |> %s\n", src_client_port, dst_client_port ); //prepare the magic string that is the step before creating a struct from with process_patch //port is source client:port and connection is the destination one. + if ( table_index >= table_size ) + { + table_size += table_increment; + table = (char**)realloc( table, table_size * sizeof( char *) ); + } + table[table_index++] = s; + // process_patch( s ); infinite loop! + // Verbose output that an individual connection was saved. + printf( "[jackpatch] ++ %s |> %s\n", src_client_port, dst_client_port ); + } + free ( src_client_port ); + free ( dst_client_port ); + } + + + clear_all_patches(); //Tabula Rasa. + + for ( port = ports; *port; port++ ) { + //*port is a full client:port jack name, not only the port. jack_port_t *p; p = jack_port_by_name( client, *port ); @@ -526,20 +609,18 @@ snapshot ( const char *file ) for ( connection = connections; *connection; connection++ ) { + //This code is replicated above #TODO: create function. char *s; - asprintf( &s, "%-40s |> %s\n", *port, *connection ); - + asprintf( &s, "%-40s |> %s\n", *port, *connection ); //prepare the magic string that is the step before creating a struct from with process_patch //port is source client:port and connection is the destination one. if ( table_index >= table_size ) { table_size += table_increment; table = (char**)realloc( table, table_size * sizeof( char *) ); } - table[table_index++] = s; - process_patch( s ); // Verbose output that an individual connection was saved. - // printf( "[jackpatch] ++ %s |> %s\n", *port, *connection ); + printf( "[jackpatch] ++ %s |> %s\n", *port, *connection ); } free( connections ); @@ -559,6 +640,7 @@ snapshot ( const char *file ) free(table); fclose( fp ); + } static int die_now = 0; @@ -873,7 +955,14 @@ main ( int argc, char **argv ) { if ( argc > 2 ) { - printf( "[jackpatch] Saving current graph to: %s\n", argv[2] ); + + //To not discard temporarily missing clients we need to load the current ones from file first. + if ( read_config( argv[2] ) ) // --save parameter + { + register_prexisting_ports(); + } + + printf( "[jackpatch] Standalone: Saving current graph to: %s\n", argv[2] ); snapshot( argv[2] ); die(); }