| @@ -72,7 +72,7 @@ struct patch_record { | |||||
| char *client; | char *client; | ||||
| char *port; | char *port; | ||||
| } src , dst; | } 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; | struct patch_record *next; | ||||
| }; | }; | ||||
| @@ -385,7 +385,7 @@ do_for_matching_patches ( const char *portname, void (*func)( struct patch_recor | |||||
| { | { | ||||
| struct patch_record *pr; | 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]; | char port[REAL_JACK_PORT_NAME_SIZE]; | ||||
| sscanf( portname, "%[^:]:%[^\n]", client, port ); | 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. | * 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 | void | ||||
| snapshot ( const char *file ) | snapshot ( const char *file ) | ||||
| { | { | ||||
| @@ -503,15 +516,85 @@ snapshot ( const char *file ) | |||||
| return; | 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; | const int table_increment = 16; | ||||
| int table_index = 0; | int table_index = 0; | ||||
| size_t table_size = table_increment; | size_t table_size = table_increment; | ||||
| char **table = (char**)malloc( sizeof( char * ) * 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++ ) | for ( port = ports; *port; port++ ) | ||||
| { | { | ||||
| //*port is a full client:port jack name, not only the port. | |||||
| jack_port_t *p; | jack_port_t *p; | ||||
| p = jack_port_by_name( client, *port ); | p = jack_port_by_name( client, *port ); | ||||
| @@ -526,20 +609,18 @@ snapshot ( const char *file ) | |||||
| for ( connection = connections; *connection; connection++ ) | for ( connection = connections; *connection; connection++ ) | ||||
| { | { | ||||
| //This code is replicated above #TODO: create function. | |||||
| char *s; | 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 ) | if ( table_index >= table_size ) | ||||
| { | { | ||||
| table_size += table_increment; | table_size += table_increment; | ||||
| table = (char**)realloc( table, table_size * sizeof( char *) ); | table = (char**)realloc( table, table_size * sizeof( char *) ); | ||||
| } | } | ||||
| table[table_index++] = s; | table[table_index++] = s; | ||||
| process_patch( s ); | process_patch( s ); | ||||
| // Verbose output that an individual connection was saved. | // Verbose output that an individual connection was saved. | ||||
| // printf( "[jackpatch] ++ %s |> %s\n", *port, *connection ); | |||||
| printf( "[jackpatch] ++ %s |> %s\n", *port, *connection ); | |||||
| } | } | ||||
| free( connections ); | free( connections ); | ||||
| @@ -559,6 +640,7 @@ snapshot ( const char *file ) | |||||
| free(table); | free(table); | ||||
| fclose( fp ); | fclose( fp ); | ||||
| } | } | ||||
| static int die_now = 0; | static int die_now = 0; | ||||
| @@ -873,7 +955,14 @@ main ( int argc, char **argv ) | |||||
| { | { | ||||
| if ( argc > 2 ) | 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] ); | snapshot( argv[2] ); | ||||
| die(); | die(); | ||||
| } | } | ||||