| @@ -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(); | |||
| } | |||