Changeset fc0a6b14be0e874b439939795eef038d9ded08d8

Show
Ignore:
Timestamp:
08/30/10 04:51:31 (3 years ago)
Author:
Nedko Arnaudov <nedko@…>
Children:
8f20db7de0d6a8b30db9a47957b2125c8328cd27
Parents:
e06f5b73dda002bb01796ae8e6370256f7412929
git-committer:
Nedko Arnaudov <nedko@arnaudov.name> / 2010-08-30T04:51:31Z+0300
Message:

daemon: move reusable signal emit code for graph objects to dedicated functions

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • daemon/graph.c

    re06f5b7 rfc0a6b1  
    8686}; 
    8787 
    88 static struct ladish_graph_port * ladish_graph_find_port_by_id_internal(struct ladish_graph * graph_ptr, uint64_t port_id) 
    89 { 
    90   struct list_head * node_ptr; 
    91   struct ladish_graph_port * port_ptr; 
    92  
    93   list_for_each(node_ptr, &graph_ptr->ports) 
    94   { 
    95     port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph); 
    96     if (port_ptr->id == port_id) 
    97     { 
    98       return port_ptr; 
    99     } 
    100   } 
    101  
    102   return NULL; 
    103 } 
    104  
    105 //#define LOG_PORT_LOOKUP 
    106  
    107 static struct ladish_graph_port * 
    108 ladish_graph_find_port_by_uuid_internal( 
    109   struct ladish_graph * graph_ptr, 
    110   struct ladish_graph_client * client_ptr, 
    111   const uuid_t uuid, 
    112   bool use_link_override_uuids) 
    113 { 
    114   struct list_head * node_ptr; 
    115   struct ladish_graph_port * port_ptr; 
    116   uuid_t current_uuid; 
    117 #if defined(LOG_PORT_LOOKUP) 
    118   char uuid1_str[37]; 
    119   char uuid2_str[37]; 
    120  
    121   log_info("searching by uuid for port in graph %s", ladish_graph_get_description((ladish_graph_handle)graph_ptr)); 
    122   uuid_unparse(uuid, uuid1_str); 
    123 #endif 
    124  
    125   list_for_each(node_ptr, &graph_ptr->ports) 
    126   { 
    127     port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph); 
    128  
    129     if (client_ptr != NULL && port_ptr->client_ptr != client_ptr) 
    130     { 
    131       continue; 
    132     } 
    133  
    134 #if defined(LOG_PORT_LOOKUP) 
    135     if (port_ptr->link) 
    136     { 
    137       uuid_unparse(port_ptr->link_uuid_override, uuid2_str); 
    138       log_info("comparing link uuid %s with %s", uuid2_str, uuid1_str); 
    139     } 
    140 #endif 
    141  
    142     if (use_link_override_uuids && port_ptr->link && uuid_compare(port_ptr->link_uuid_override, uuid) == 0) 
    143     { 
    144 #if defined(LOG_PORT_LOOKUP) 
    145       log_info("found link port %p of client '%s'", port_ptr->port, port_ptr->client_ptr->name); 
    146 #endif 
    147       return port_ptr; 
    148     } 
    149  
    150     ladish_port_get_uuid(port_ptr->port, current_uuid); 
    151 #if defined(LOG_PORT_LOOKUP) 
    152     uuid_unparse(current_uuid, uuid2_str); 
    153     log_info("comparing port uuid %s with %s", uuid2_str, uuid1_str); 
    154 #endif 
    155     if (uuid_compare(current_uuid, uuid) == 0) 
    156     { 
    157 #if defined(LOG_PORT_LOOKUP) 
    158       log_info("found port %p of client '%s'", port_ptr->port, port_ptr->client_ptr->name); 
    159 #endif 
    160       return port_ptr; 
    161     } 
    162   } 
    163  
    164   return NULL; 
    165 } 
    166  
    167 static struct ladish_graph_connection * ladish_graph_find_connection_by_id(struct ladish_graph * graph_ptr, uint64_t connection_id) 
    168 { 
    169   struct list_head * node_ptr; 
    170   struct ladish_graph_connection * connection_ptr; 
    171  
    172   list_for_each(node_ptr, &graph_ptr->connections) 
    173   { 
    174     connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings); 
    175     if (connection_ptr->id == connection_id) 
    176     { 
    177       return connection_ptr; 
    178     } 
    179   } 
    180  
    181   return NULL; 
    182 } 
    183  
    184 static 
    185 struct ladish_graph_connection * 
    186 ladish_graph_find_connection_by_ports( 
    187   struct ladish_graph * graph_ptr, 
    188   struct ladish_graph_port * port1_ptr, 
    189   struct ladish_graph_port * port2_ptr) 
    190 { 
    191   struct list_head * node_ptr; 
    192   struct ladish_graph_connection * connection_ptr; 
    193  
    194   list_for_each(node_ptr, &graph_ptr->connections) 
    195   { 
    196     connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings); 
    197     if ((connection_ptr->port1_ptr == port1_ptr && connection_ptr->port2_ptr == port2_ptr) || 
    198         (connection_ptr->port1_ptr == port2_ptr && connection_ptr->port2_ptr == port1_ptr)) 
    199     { 
    200       return connection_ptr; 
    201     } 
    202   } 
    203  
    204   return NULL; 
    205 } 
    206  
    207 #define graph_ptr ((struct ladish_graph *)call_ptr->iface_context) 
    208  
    209 static void get_all_ports(struct dbus_method_call * call_ptr) 
    210 { 
    211   DBusMessageIter iter, sub_iter; 
    212  
    213   call_ptr->reply = dbus_message_new_method_return(call_ptr->message); 
    214   if (call_ptr->reply == NULL) 
    215   { 
    216     goto fail; 
    217   } 
    218  
    219   dbus_message_iter_init_append(call_ptr->reply, &iter); 
    220  
    221   if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) 
    222   { 
    223     goto fail_unref; 
    224   } 
    225  
    226   if (!dbus_message_iter_close_container(&iter, &sub_iter)) 
    227   { 
    228     goto fail_unref; 
    229   } 
    230  
    231   return; 
    232  
    233 fail_unref: 
    234   dbus_message_unref(call_ptr->reply); 
    235   call_ptr->reply = NULL; 
    236  
    237 fail: 
    238   log_error("Ran out of memory trying to construct method return"); 
    239 } 
    240  
    241 static void get_graph(struct dbus_method_call * call_ptr) 
    242 { 
    243   dbus_uint64_t known_version; 
    244   dbus_uint64_t current_version; 
    245   DBusMessageIter iter; 
    246   DBusMessageIter clients_array_iter; 
    247   DBusMessageIter connections_array_iter; 
    248   DBusMessageIter client_struct_iter; 
    249   struct list_head * client_node_ptr; 
    250   struct ladish_graph_client * client_ptr; 
    251   DBusMessageIter ports_array_iter; 
    252   struct list_head * port_node_ptr; 
    253   struct ladish_graph_port * port_ptr; 
    254   DBusMessageIter port_struct_iter; 
    255   struct list_head * connection_node_ptr; 
    256   struct ladish_graph_connection * connection_ptr; 
    257   DBusMessageIter connection_struct_iter; 
    258  
    259   //log_info("get_graph() called"); 
    260  
    261   if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &known_version, DBUS_TYPE_INVALID)) 
    262   { 
    263     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s",  call_ptr->method_name, g_dbus_error.message); 
    264     dbus_error_free(&g_dbus_error); 
    265     return; 
    266   } 
    267  
    268   //log_info("Getting graph, known version is %" PRIu64, known_version); 
    269  
    270   call_ptr->reply = dbus_message_new_method_return(call_ptr->message); 
    271   if (call_ptr->reply == NULL) 
    272   { 
    273     log_error("Ran out of memory trying to construct method return"); 
    274     goto exit; 
    275   } 
    276  
    277   dbus_message_iter_init_append(call_ptr->reply, &iter); 
    278  
    279   current_version = graph_ptr->graph_version; 
    280   if (known_version > current_version) 
    281   { 
    282     lash_dbus_error( 
    283       call_ptr, 
    284       LASH_DBUS_ERROR_INVALID_ARGS, 
    285       "known graph version %" PRIu64 " is newer than actual version %" PRIu64, 
    286       known_version, 
    287       current_version); 
    288     goto exit; 
    289   } 
    290  
    291   if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &current_version)) 
    292   { 
    293     goto nomem; 
    294   } 
    295  
    296   if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter)) 
    297   { 
    298     goto nomem; 
    299   } 
    300  
    301   if (known_version < current_version) 
    302   { 
    303     list_for_each(client_node_ptr, &graph_ptr->clients) 
    304     { 
    305       client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings); 
    306  
    307       if (client_ptr->hidden) 
    308       { 
    309         continue; 
    310       } 
    311  
    312       if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter)) 
    313       { 
    314         goto nomem_close_clients_array; 
    315       } 
    316  
    317       if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id)) 
    318       { 
    319         goto nomem_close_client_struct; 
    320       } 
    321  
    322       log_info("client '%s' (%llu)", client_ptr->name, (unsigned long long)client_ptr->id); 
    323       if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name)) 
    324       { 
    325         goto nomem_close_client_struct; 
    326       } 
    327  
    328       if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter)) 
    329       { 
    330         goto nomem_close_client_struct; 
    331       } 
    332  
    333       list_for_each(port_node_ptr, &client_ptr->ports) 
    334       { 
    335         port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client); 
    336  
    337         if (port_ptr->hidden) 
    338         { 
    339           continue; 
    340         } 
    341  
    342         if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter)) 
    343         { 
    344           goto nomem_close_ports_array; 
    345         } 
    346  
    347         if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id)) 
    348         { 
    349           goto nomem_close_port_struct; 
    350         } 
    351  
    352         if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name)) 
    353         { 
    354           goto nomem_close_port_struct; 
    355         } 
    356  
    357         if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags)) 
    358         { 
    359           goto nomem_close_port_struct; 
    360         } 
    361  
    362         if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type)) 
    363         { 
    364           goto nomem_close_port_struct; 
    365         } 
    366  
    367         if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter)) 
    368         { 
    369           goto nomem_close_ports_array; 
    370         } 
    371       } 
    372  
    373       if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter)) 
    374       { 
    375         goto nomem_close_client_struct; 
    376       } 
    377  
    378       if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter)) 
    379       { 
    380         goto nomem_close_clients_array; 
    381       } 
    382     } 
    383   } 
    384  
    385   if (!dbus_message_iter_close_container(&iter, &clients_array_iter)) 
    386   { 
    387     goto nomem; 
    388   } 
    389  
    390   if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter)) 
    391   { 
    392     goto nomem; 
    393   } 
    394  
    395   if (known_version < current_version) 
    396   { 
    397     list_for_each(connection_node_ptr, &graph_ptr->connections) 
    398     { 
    399       connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings); 
    400  
    401       if (connection_ptr->hidden) 
    402       { 
    403         continue; 
    404       } 
    405  
    406       if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter)) 
    407       { 
    408         goto nomem_close_connections_array; 
    409       } 
    410  
    411       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->client_ptr->id)) 
    412       { 
    413         goto nomem_close_connection_struct; 
    414       } 
    415  
    416       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->client_ptr->name)) 
    417       { 
    418         goto nomem_close_connection_struct; 
    419       } 
    420  
    421       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->id)) 
    422       { 
    423         goto nomem_close_connection_struct; 
    424       } 
    425  
    426       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->name)) 
    427       { 
    428         goto nomem_close_connection_struct; 
    429       } 
    430  
    431       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->client_ptr->id)) 
    432       { 
    433         goto nomem_close_connection_struct; 
    434       } 
    435  
    436       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->client_ptr->name)) 
    437       { 
    438         goto nomem_close_connection_struct; 
    439       } 
    440  
    441       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->id)) 
    442       { 
    443         goto nomem_close_connection_struct; 
    444       } 
    445  
    446       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->name)) 
    447       { 
    448         goto nomem_close_connection_struct; 
    449       } 
    450  
    451       if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id)) 
    452       { 
    453         goto nomem_close_connection_struct; 
    454       } 
    455  
    456       if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter)) 
    457       { 
    458         goto nomem_close_connections_array; 
    459       } 
    460     } 
    461   } 
    462  
    463   if (!dbus_message_iter_close_container(&iter, &connections_array_iter)) 
    464   { 
    465     goto nomem; 
    466   } 
    467  
    468   return; 
    469  
    470 nomem_close_connection_struct: 
    471   dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter); 
    472  
    473 nomem_close_connections_array: 
    474   dbus_message_iter_close_container(&iter, &connections_array_iter); 
    475   goto nomem; 
    476  
    477 nomem_close_port_struct: 
    478   dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter); 
    479  
    480 nomem_close_ports_array: 
    481   dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter); 
    482  
    483 nomem_close_client_struct: 
    484   dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter); 
    485  
    486 nomem_close_clients_array: 
    487   dbus_message_iter_close_container(&iter, &clients_array_iter); 
    488  
    489 nomem: 
    490   dbus_message_unref(call_ptr->reply); 
    491   call_ptr->reply = NULL; 
    492   log_error("Ran out of memory trying to construct method return"); 
    493  
    494 exit: 
    495   return; 
    496 } 
    497  
    498 static void connect_ports_by_name(struct dbus_method_call * call_ptr) 
    499 { 
    500   log_info("connect_ports_by_name() called."); 
    501   lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect by name is not implemented yet"); 
    502 } 
    503  
    504 static void connect_ports_by_id(struct dbus_method_call * call_ptr) 
    505 { 
    506   dbus_uint64_t port1_id; 
    507   dbus_uint64_t port2_id; 
    508   struct ladish_graph_port * port1_ptr; 
    509   struct ladish_graph_port * port2_ptr; 
    510  
    511   if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID)) 
    512   { 
    513     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message); 
    514     dbus_error_free(&g_dbus_error); 
    515     return; 
    516   } 
    517  
    518   log_info("connect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id); 
    519  
    520   if (graph_ptr->connect_handler == NULL) 
    521   { 
    522     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect requests on graph %s cannot be handlined", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
    523     return; 
    524   } 
    525  
    526   port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id); 
    527   if (port1_ptr == NULL) 
    528   { 
    529     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port1_id); 
    530     return; 
    531   } 
    532  
    533   port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id); 
    534   if (port2_ptr == NULL) 
    535   { 
    536     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port2_id); 
    537     return; 
    538   } 
    539  
    540   log_info("connecting '%s':'%s' to '%s':'%s'", port1_ptr->client_ptr->name, port1_ptr->name, port2_ptr->client_ptr->name, port2_ptr->name); 
    541  
    542   if (graph_ptr->connect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, port1_ptr->port, port2_ptr->port)) 
    543   { 
    544     method_return_new_void(call_ptr); 
    545   } 
    546   else 
    547   { 
    548     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect failed"); 
    549   } 
    550 } 
    551  
    552 static void disconnect_ports(struct dbus_method_call * call_ptr, struct ladish_graph_connection * connection_ptr) 
    553 { 
    554   log_info( 
    555     "disconnecting '%s':'%s' from '%s':'%s'", 
    556     connection_ptr->port1_ptr->client_ptr->name, 
    557     connection_ptr->port1_ptr->name, 
    558     connection_ptr->port2_ptr->client_ptr->name, 
    559     connection_ptr->port2_ptr->name); 
    560  
    561   connection_ptr->changing = true; 
    562   if (graph_ptr->disconnect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, connection_ptr->id)) 
    563   { 
    564     method_return_new_void(call_ptr); 
    565   } 
    566   else 
    567   { 
    568     connection_ptr->changing = false; 
    569     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect failed"); 
    570   } 
    571 } 
    572  
    573 static void disconnect_ports_by_name(struct dbus_method_call * call_ptr) 
    574 { 
    575   log_info("disconnect_ports_by_name() called."); 
    576   lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect by name is not implemented yet"); 
    577 } 
    578  
    579 static void disconnect_ports_by_id(struct dbus_method_call * call_ptr) 
    580 { 
    581   dbus_uint64_t port1_id; 
    582   dbus_uint64_t port2_id; 
    583   struct ladish_graph_port * port1_ptr; 
    584   struct ladish_graph_port * port2_ptr; 
    585   struct ladish_graph_connection * connection_ptr; 
    586  
    587   if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID)) 
    588   { 
    589     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message); 
    590     dbus_error_free(&g_dbus_error); 
    591     return; 
    592   } 
    593  
    594   log_info("disconnect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id); 
    595  
    596   if (graph_ptr->disconnect_handler == NULL) 
    597   { 
    598     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect requests on graph %s cannot be handlined", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
    599     return; 
    600   } 
    601  
    602   port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id); 
    603   if (port1_ptr == NULL) 
    604   { 
    605     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port1_id); 
    606     return; 
    607   } 
    608  
    609   port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id); 
    610   if (port2_ptr == NULL) 
    611   { 
    612     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port2_id); 
    613     return; 
    614   } 
    615  
    616   connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr); 
    617   if (connection_ptr == NULL) 
    618   { 
    619     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect not connected ports %"PRIu64" and %"PRIu64, port1_id, port2_id); 
    620     return; 
    621   } 
    622  
    623   disconnect_ports(call_ptr, connection_ptr); 
    624 } 
    625  
    626 static void disconnect_ports_by_connection_id(struct dbus_method_call * call_ptr) 
    627 { 
    628   dbus_uint64_t connection_id; 
    629   struct ladish_graph_connection * connection_ptr; 
    630  
    631   if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &connection_id, DBUS_TYPE_INVALID)) 
    632   { 
    633     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message); 
    634     dbus_error_free(&g_dbus_error); 
    635     return; 
    636   } 
    637  
    638   log_info("disconnect_ports_by_connection_id(%"PRIu64") called.", connection_id); 
    639  
    640   connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id); 
    641   if (connection_ptr == NULL) 
    642   { 
    643     lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot find connection with id %"PRIu64, connection_id); 
    644     return; 
    645   } 
    646  
    647   disconnect_ports(call_ptr, connection_ptr); 
    648 } 
    649  
    650 static void get_client_pid(struct dbus_method_call * call_ptr) 
    651 { 
    652   int64_t pid = 0; 
    653   method_return_new_single(call_ptr, DBUS_TYPE_INT64, &pid); 
    654 } 
    655  
    656 #undef graph_ptr 
    657  
    658 bool ladish_graph_create(ladish_graph_handle * graph_handle_ptr, const char * opath) 
    659 { 
    660   struct ladish_graph * graph_ptr; 
    661  
    662   graph_ptr = malloc(sizeof(struct ladish_graph)); 
    663   if (graph_ptr == NULL) 
    664   { 
    665     log_error("malloc() failed to allocate struct graph_implementator"); 
    666     return false; 
    667   } 
    668  
    669   if (opath != NULL) 
    670   { 
    671     graph_ptr->opath = strdup(opath); 
    672     if (graph_ptr->opath == NULL) 
    673     { 
    674       log_error("strdup() failed for graph opath"); 
    675       free(graph_ptr); 
    676       return false; 
    677     } 
    678   } 
    679   else 
    680   { 
    681     graph_ptr->opath = NULL; 
    682   } 
    683  
    684   if (!ladish_dict_create(&graph_ptr->dict)) 
    685   { 
    686     log_error("ladish_dict_create() failed for graph"); 
    687     if (graph_ptr->opath != NULL) 
    688     { 
    689       free(graph_ptr->opath); 
    690     } 
    691     free(graph_ptr); 
    692     return false; 
    693   } 
    694  
    695   INIT_LIST_HEAD(&graph_ptr->clients); 
    696   INIT_LIST_HEAD(&graph_ptr->ports); 
    697   INIT_LIST_HEAD(&graph_ptr->connections); 
    698  
    699   graph_ptr->graph_version = 1; 
    700   graph_ptr->next_client_id = 1; 
    701   graph_ptr->next_port_id = 1; 
    702   graph_ptr->next_connection_id = 1; 
    703  
    704   graph_ptr->context = NULL; 
    705   graph_ptr->connect_handler = NULL; 
    706   graph_ptr->disconnect_handler = NULL; 
    707  
    708   graph_ptr->persist = true; 
    709  
    710   *graph_handle_ptr = (ladish_graph_handle)graph_ptr; 
    711   return true; 
    712 } 
    713  
    714 static 
    715 struct ladish_graph_client * 
    716 ladish_graph_find_client( 
    717   struct ladish_graph * graph_ptr, 
    718   ladish_client_handle client) 
    719 { 
    720   struct list_head * node_ptr; 
    721   struct ladish_graph_client * client_ptr; 
    722  
    723   list_for_each(node_ptr, &graph_ptr->clients) 
    724   { 
    725     client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings); 
    726     if (client_ptr->client == client) 
    727     { 
    728       return client_ptr; 
    729     } 
    730   } 
    731  
    732   return NULL; 
    733 } 
    734  
    735 static 
    736 struct ladish_graph_port * 
    737 ladish_graph_find_port( 
    738   struct ladish_graph * graph_ptr, 
    739   ladish_port_handle port) 
    740 { 
    741   struct list_head * node_ptr; 
    742   struct ladish_graph_port * port_ptr; 
    743  
    744   //log_info("searching port %p", port); 
    745  
    746   list_for_each(node_ptr, &graph_ptr->ports) 
    747   { 
    748     port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph); 
    749     //log_info("checking port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port); 
    750     if (port_ptr->port == port) 
    751     { 
    752       return port_ptr; 
    753     } 
    754   } 
    755  
    756   return NULL; 
    757 } 
    758  
    759 static 
    760 struct ladish_graph_port * 
    761 ladish_graph_find_port_by_jack_id_internal( 
    762   struct ladish_graph * graph_ptr, 
    763   uint64_t port_id, 
    764   bool room, 
    765   bool studio) 
    766 { 
    767   struct list_head * node_ptr; 
    768   struct ladish_graph_port * port_ptr; 
    769  
    770   ASSERT(room || studio); 
    771  
    772   list_for_each(node_ptr, &graph_ptr->ports) 
    773   { 
    774     port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph); 
    775     //log_info("checking jack port id of port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port); 
    776     if ((studio && ladish_port_get_jack_id(port_ptr->port) == port_id) || 
    777         (room && port_ptr->link && ladish_port_get_jack_id_room(port_ptr->port) == port_id)) 
    778     { 
    779       //log_info("found"); 
    780       return port_ptr; 
    781     } 
    782   } 
    783  
    784   return NULL; 
    785 } 
    786  
    787 #if 0 
    788 static 
    789 struct ladish_graph_port * 
    790 ladish_graph_find_client_port( 
    791   struct ladish_graph * graph_ptr, 
    792   struct ladish_graph_client * client_ptr, 
    793   ladish_port_handle port) 
    794 { 
    795   struct list_head * node_ptr; 
    796   struct ladish_graph_port * port_ptr; 
    797  
    798   list_for_each(node_ptr, &client_ptr->ports) 
    799   { 
    800     port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client); 
    801     if (port_ptr->port == port) 
    802     { 
    803       return port_ptr; 
    804     } 
    805   } 
    806  
    807   return NULL; 
    808 } 
    809 #endif 
    810  
    811 static void ladish_graph_hide_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr) 
    812 { 
    813   ASSERT(!connection_ptr->hidden); 
    814   connection_ptr->hidden = true; 
    815   graph_ptr->graph_version++; 
    816  
    817   if (graph_ptr->opath != NULL) 
    818   { 
    819     dbus_signal_emit( 
    820       g_dbus_connection, 
    821       graph_ptr->opath, 
    822       JACKDBUS_IFACE_PATCHBAY, 
    823       "PortsDisconnected", 
    824       "ttstststst", 
    825       &graph_ptr->graph_version, 
    826       &connection_ptr->port1_ptr->client_ptr->id, 
    827       &connection_ptr->port1_ptr->client_ptr->name, 
    828       &connection_ptr->port1_ptr->id, 
    829       &connection_ptr->port1_ptr->name, 
    830       &connection_ptr->port2_ptr->client_ptr->id, 
    831       &connection_ptr->port2_ptr->client_ptr->name, 
    832       &connection_ptr->port2_ptr->id, 
    833       &connection_ptr->port2_ptr->name, 
    834       &connection_ptr->id); 
    835   } 
    836 } 
    837  
    838 static void ladish_graph_show_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
    839 { 
    840   if (port_ptr->client_ptr->hidden) 
    841   { 
    842     port_ptr->client_ptr->hidden = false; 
    843     graph_ptr->graph_version++; 
    844     if (graph_ptr->opath != NULL) 
    845     { 
    846       dbus_signal_emit( 
    847         g_dbus_connection, 
    848         graph_ptr->opath, 
    849         JACKDBUS_IFACE_PATCHBAY, 
    850         "ClientAppeared", 
    851         "tts", 
    852         &graph_ptr->graph_version, 
    853         &port_ptr->client_ptr->id, 
    854         &port_ptr->client_ptr->name); 
    855     } 
    856   } 
    857  
    858   ASSERT(port_ptr->hidden); 
    859   port_ptr->hidden = false; 
    860   graph_ptr->graph_version++; 
    861   if (graph_ptr->opath != NULL) 
    862   { 
    863     dbus_signal_emit( 
    864       g_dbus_connection, 
    865       graph_ptr->opath, 
    866       JACKDBUS_IFACE_PATCHBAY, 
    867       "PortAppeared", 
    868       "ttstsuu", 
    869       &graph_ptr->graph_version, 
    870       &port_ptr->client_ptr->id, 
    871       &port_ptr->client_ptr->name, 
    872       &port_ptr->id, 
    873       &port_ptr->name, 
    874       &port_ptr->flags, 
    875       &port_ptr->type); 
    876  
    877     ladish_try_connect_hidden_connections((ladish_graph_handle)graph_ptr); 
    878   } 
    879 } 
    880  
    881 static void ladish_graph_hide_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
    882 { 
    883   ASSERT(!port_ptr->hidden); 
    884   port_ptr->hidden = true; 
    885   graph_ptr->graph_version++; 
    886  
    887   if (graph_ptr->opath != NULL) 
    888   { 
    889     dbus_signal_emit( 
    890       g_dbus_connection, 
    891       graph_ptr->opath, 
    892       JACKDBUS_IFACE_PATCHBAY, 
    893       "PortDisappeared", 
    894       "ttsts", 
    895       &graph_ptr->graph_version, 
    896       &port_ptr->client_ptr->id, 
    897       &port_ptr->client_ptr->name, 
    898       &port_ptr->id, 
    899       &port_ptr->name); 
    900   } 
    901 } 
    902  
    903 static void ladish_graph_hide_client_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr) 
    904 { 
    905   ASSERT(!client_ptr->hidden); 
    906   client_ptr->hidden = true; 
    907   graph_ptr->graph_version++; 
    908  
    909   if (graph_ptr->opath != NULL) 
    910   { 
    911     dbus_signal_emit( 
    912       g_dbus_connection, 
    913       graph_ptr->opath, 
    914       JACKDBUS_IFACE_PATCHBAY, 
    915       "ClientDisappeared", 
    916       "tts", 
    917       &graph_ptr->graph_version, 
    918       &client_ptr->id, 
    919       &client_ptr->name); 
    920   } 
    921 } 
    922  
    923 static void ladish_hide_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
    924 { 
    925   struct list_head * node_ptr; 
    926   struct ladish_graph_connection * connection_ptr; 
    927  
    928   log_info("hidding connections of port %"PRIu64, port_ptr->id); 
    929  
     88static void ladish_graph_emit_ports_disconnected(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr) 
     89{ 
    93090  ASSERT(graph_ptr->opath != NULL); 
    93191 
    932   list_for_each(node_ptr, &graph_ptr->connections) 
    933   { 
    934     connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings); 
    935     if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr)) 
    936     { 
    937       log_info("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id); 
    938       ladish_graph_hide_connection_internal(graph_ptr, connection_ptr); 
    939     } 
    940   } 
    941 } 
    942  
    943 static void ladish_graph_remove_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr) 
    944 { 
    945   list_del(&connection_ptr->siblings); 
    946   graph_ptr->graph_version++; 
    947  
    948   if (!connection_ptr->hidden && graph_ptr->opath != NULL) 
    949   { 
    950     dbus_signal_emit( 
    951       g_dbus_connection, 
    952       graph_ptr->opath, 
    953       JACKDBUS_IFACE_PATCHBAY, 
    954       "PortsDisconnected", 
    955       "ttstststst", 
    956       &graph_ptr->graph_version, 
    957       &connection_ptr->port1_ptr->client_ptr->id, 
    958       &connection_ptr->port1_ptr->client_ptr->name, 
    959       &connection_ptr->port1_ptr->id, 
    960       &connection_ptr->port1_ptr->name, 
    961       &connection_ptr->port2_ptr->client_ptr->id, 
    962       &connection_ptr->port2_ptr->client_ptr->name, 
    963       &connection_ptr->port2_ptr->id, 
    964       &connection_ptr->port2_ptr->name, 
    965       &connection_ptr->id); 
    966   } 
    967  
    968   ladish_dict_destroy(connection_ptr->dict); 
    969   free(connection_ptr); 
    970 } 
    971  
    972 static void ladish_graph_remove_port_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
    973 { 
    974   struct list_head * node_ptr; 
    975   struct list_head * temp_node_ptr; 
    976   struct ladish_graph_connection * connection_ptr; 
    977  
    978   list_for_each_safe(node_ptr, temp_node_ptr, &graph_ptr->connections) 
    979   { 
    980     connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings); 
    981     if (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr) 
    982     { 
    983       log_info("removing connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id); 
    984       ladish_graph_remove_connection_internal(graph_ptr, connection_ptr); 
    985     } 
    986   } 
    987 } 
    988  
    989 static 
    990 void 
    991 ladish_graph_remove_port_internal( 
    992   struct ladish_graph * graph_ptr, 
    993   struct ladish_graph_client * client_ptr, 
    994   struct ladish_graph_port * port_ptr) 
    995 { 
    996   ladish_graph_remove_port_connections(graph_ptr, port_ptr); 
    997  
    998   ladish_port_del_ref(port_ptr->port); 
    999  
    1000   list_del(&port_ptr->siblings_client); 
    1001   list_del(&port_ptr->siblings_graph); 
    1002  
    1003   log_info("removing port '%s':'%s' (%"PRIu64":%"PRIu64") from graph %s", client_ptr->name, port_ptr->name, client_ptr->id, port_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
    1004   if (graph_ptr->opath != NULL && !port_ptr->hidden) 
    1005   { 
    1006     dbus_signal_emit( 
    1007       g_dbus_connection, 
    1008       graph_ptr->opath, 
    1009       JACKDBUS_IFACE_PATCHBAY, 
    1010       "PortDisappeared", 
    1011       "ttsts", 
    1012       &graph_ptr->graph_version, 
    1013       &client_ptr->id, 
    1014       &client_ptr->name, 
    1015       &port_ptr->id, 
    1016       &port_ptr->name); 
    1017   } 
    1018  
    1019   free(port_ptr->name); 
    1020   free(port_ptr); 
    1021 } 
    1022  
    1023 static 
    1024 void 
    1025 ladish_graph_remove_client_internal( 
    1026   struct ladish_graph * graph_ptr, 
    1027   struct ladish_graph_client * client_ptr, 
    1028   bool destroy_client, 
    1029   ladish_graph_simple_port_callback port_callback) 
    1030 { 
    1031   struct ladish_graph_port * port_ptr; 
    1032  
    1033   while (!list_empty(&client_ptr->ports)) 
    1034   { 
    1035     port_ptr = list_entry(client_ptr->ports.next, struct ladish_graph_port, siblings_client); 
    1036     if (port_callback != NULL) 
    1037     { 
    1038       port_callback(port_ptr->port); 
    1039     } 
    1040     ladish_graph_remove_port_internal(graph_ptr, client_ptr, port_ptr); 
    1041   } 
    1042  
    1043   graph_ptr->graph_version++; 
    1044   list_del(&client_ptr->siblings); 
    1045   log_info("removing client '%s' (%"PRIu64") from graph %s", client_ptr->name, client_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
    1046   if (graph_ptr->opath != NULL && !client_ptr->hidden) 
    1047   { 
    1048     dbus_signal_emit( 
    1049       g_dbus_connection, 
    1050       graph_ptr->opath, 
    1051       JACKDBUS_IFACE_PATCHBAY, 
    1052       "ClientDisappeared", 
    1053       "tts", 
    1054       &graph_ptr->graph_version, 
    1055       &client_ptr->id, 
    1056       &client_ptr->name); 
    1057   } 
    1058  
    1059   free(client_ptr->name); 
    1060  
    1061   if (destroy_client) 
    1062   { 
    1063     ladish_client_destroy(client_ptr->client); 
    1064   } 
    1065  
    1066   free(client_ptr); 
    1067 } 
    1068  
    1069 bool ladish_graph_client_looks_empty_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr) 
    1070 { 
    1071   struct list_head * node_ptr; 
    1072   struct ladish_graph_port * port_ptr; 
    1073  
    1074   list_for_each(node_ptr, &client_ptr->ports) 
    1075   { 
    1076     port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client); 
    1077     if (!port_ptr->hidden) 
    1078     { 
    1079       //log_info("port '%s' is visible, client '%s' does not look empty", port_ptr->name, client_ptr->name); 
    1080       return false; 
    1081     } 
    1082     else 
    1083     { 
    1084       //log_info("port '%s' is invisible", port_ptr->name); 
    1085     } 
    1086   } 
    1087  
    1088   //log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
    1089   return true; 
    1090 } 
    1091  
    1092 #define graph_ptr ((struct ladish_graph *)graph_handle) 
    1093  
    1094 void ladish_graph_destroy(ladish_graph_handle graph_handle) 
    1095 { 
    1096   ladish_graph_clear(graph_handle, NULL); 
    1097   ladish_dict_destroy(graph_ptr->dict); 
    1098   if (graph_ptr->opath != NULL) 
    1099   { 
    1100     free(graph_ptr->opath); 
    1101   } 
    1102   free(graph_ptr); 
    1103 } 
    1104  
    1105 const char * ladish_graph_get_opath(ladish_graph_handle graph_handle) 
    1106 { 
    1107   return graph_ptr->opath; 
    1108 } 
    1109  
    1110 const char * ladish_graph_get_description(ladish_graph_handle graph_handle) 
    1111 { 
    1112   return graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"; 
    1113 } 
    1114  
    1115 void 
    1116 ladish_graph_set_connection_handlers( 
    1117   ladish_graph_handle graph_handle, 
    1118   void * graph_context, 
    1119   ladish_graph_connect_request_handler connect_handler, 
    1120   ladish_graph_disconnect_request_handler disconnect_handler) 
    1121 { 
    1122   log_info("setting connection handlers for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
    1123   graph_ptr->context = graph_context; 
    1124   graph_ptr->connect_handler = connect_handler; 
    1125   graph_ptr->disconnect_handler = disconnect_handler; 
    1126 } 
    1127  
    1128 void ladish_graph_clear(ladish_graph_handle graph_handle, ladish_graph_simple_port_callback port_callback) 
    1129 { 
    1130   struct ladish_graph_client * client_ptr; 
    1131   struct ladish_graph_connection * connection_ptr; 
    1132  
    1133   log_info("ladish_graph_clear() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
    1134  
    1135   while (!list_empty(&graph_ptr->connections)) 
    1136   { 
    1137     connection_ptr = list_entry(graph_ptr->connections.next, struct ladish_graph_connection, siblings); 
    1138     ladish_graph_remove_connection_internal(graph_ptr, connection_ptr); 
    1139   } 
    1140  
    1141   while (!list_empty(&graph_ptr->clients)) 
    1142   { 
    1143     client_ptr = list_entry(graph_ptr->clients.next, struct ladish_graph_client, siblings); 
    1144     ladish_graph_remove_client_internal(graph_ptr, client_ptr, true, port_callback); 
    1145   } 
    1146 } 
    1147  
    1148 void * ladish_graph_get_dbus_context(ladish_graph_handle graph_handle) 
    1149 { 
    1150   return graph_handle; 
    1151 } 
    1152  
    1153 ladish_dict_handle ladish_graph_get_dict(ladish_graph_handle graph_handle) 
    1154 { 
    1155   return graph_ptr->dict; 
    1156 } 
    1157  
    1158 void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t connection_id) 
    1159 { 
    1160   struct ladish_graph_connection * connection_ptr; 
    1161  
    1162   log_info("ladish_graph_show_connection() called."); 
    1163  
    1164   connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id); 
    1165   if (connection_ptr == NULL) 
    1166   { 
    1167     ASSERT_NO_PASS; 
    1168     return; 
    1169   } 
    1170  
     92  dbus_signal_emit( 
     93    g_dbus_connection, 
     94    graph_ptr->opath, 
     95    JACKDBUS_IFACE_PATCHBAY, 
     96    "PortsDisconnected", 
     97    "ttstststst", 
     98    &graph_ptr->graph_version, 
     99    &connection_ptr->port1_ptr->client_ptr->id, 
     100    &connection_ptr->port1_ptr->client_ptr->name, 
     101    &connection_ptr->port1_ptr->id, 
     102    &connection_ptr->port1_ptr->name, 
     103    &connection_ptr->port2_ptr->client_ptr->id, 
     104    &connection_ptr->port2_ptr->client_ptr->name, 
     105    &connection_ptr->port2_ptr->id, 
     106    &connection_ptr->port2_ptr->name, 
     107    &connection_ptr->id); 
     108} 
     109 
     110static void ladish_graph_emit_ports_connected(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr) 
     111{ 
    1171112  ASSERT(graph_ptr->opath != NULL); 
    1172   ASSERT(connection_ptr->hidden); 
    1173   connection_ptr->hidden = false; 
    1174   connection_ptr->changing = false; 
    1175   graph_ptr->graph_version++; 
    1176113 
    1177114  dbus_signal_emit( 
     
    1193130} 
    1194131 
     132static void ladish_graph_emit_client_appeared(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr) 
     133{ 
     134  ASSERT(graph_ptr->opath != NULL); 
     135 
     136  dbus_signal_emit( 
     137    g_dbus_connection, 
     138    graph_ptr->opath, 
     139    JACKDBUS_IFACE_PATCHBAY, 
     140    "ClientAppeared", 
     141    "tts", 
     142    &graph_ptr->graph_version, 
     143    &client_ptr->id, 
     144    &client_ptr->name); 
     145} 
     146 
     147static void ladish_graph_emit_client_disappeared(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr) 
     148{ 
     149  ASSERT(graph_ptr->opath != NULL); 
     150 
     151  dbus_signal_emit( 
     152    g_dbus_connection, 
     153    graph_ptr->opath, 
     154    JACKDBUS_IFACE_PATCHBAY, 
     155    "ClientDisappeared", 
     156    "tts", 
     157    &graph_ptr->graph_version, 
     158    &client_ptr->id, 
     159    &client_ptr->name); 
     160} 
     161 
     162static void ladish_graph_emit_port_appeared(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
     163{ 
     164  ASSERT(graph_ptr->opath != NULL); 
     165 
     166  dbus_signal_emit( 
     167    g_dbus_connection, 
     168    graph_ptr->opath, 
     169    JACKDBUS_IFACE_PATCHBAY, 
     170    "PortAppeared", 
     171    "ttstsuu", 
     172    &graph_ptr->graph_version, 
     173    &port_ptr->client_ptr->id, 
     174    &port_ptr->client_ptr->name, 
     175    &port_ptr->id, 
     176    &port_ptr->name, 
     177    &port_ptr->flags, 
     178    &port_ptr->type); 
     179} 
     180 
     181static void ladish_graph_emit_port_disappeared(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
     182{ 
     183  ASSERT(graph_ptr->opath != NULL); 
     184 
     185  dbus_signal_emit( 
     186    g_dbus_connection, 
     187    graph_ptr->opath, 
     188    JACKDBUS_IFACE_PATCHBAY, 
     189    "PortDisappeared", 
     190    "ttsts", 
     191    &graph_ptr->graph_version, 
     192    &port_ptr->client_ptr->id, 
     193    &port_ptr->client_ptr->name, 
     194    &port_ptr->id, 
     195    &port_ptr->name); 
     196} 
     197 
     198static struct ladish_graph_port * ladish_graph_find_port_by_id_internal(struct ladish_graph * graph_ptr, uint64_t port_id) 
     199{ 
     200  struct list_head * node_ptr; 
     201  struct ladish_graph_port * port_ptr; 
     202 
     203  list_for_each(node_ptr, &graph_ptr->ports) 
     204  { 
     205    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph); 
     206    if (port_ptr->id == port_id) 
     207    { 
     208      return port_ptr; 
     209    } 
     210  } 
     211 
     212  return NULL; 
     213} 
     214 
     215//#define LOG_PORT_LOOKUP 
     216 
     217static struct ladish_graph_port * 
     218ladish_graph_find_port_by_uuid_internal( 
     219  struct ladish_graph * graph_ptr, 
     220  struct ladish_graph_client * client_ptr, 
     221  const uuid_t uuid, 
     222  bool use_link_override_uuids) 
     223{ 
     224  struct list_head * node_ptr; 
     225  struct ladish_graph_port * port_ptr; 
     226  uuid_t current_uuid; 
     227#if defined(LOG_PORT_LOOKUP) 
     228  char uuid1_str[37]; 
     229  char uuid2_str[37]; 
     230 
     231  log_info("searching by uuid for port in graph %s", ladish_graph_get_description((ladish_graph_handle)graph_ptr)); 
     232  uuid_unparse(uuid, uuid1_str); 
     233#endif 
     234 
     235  list_for_each(node_ptr, &graph_ptr->ports) 
     236  { 
     237    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph); 
     238 
     239    if (client_ptr != NULL && port_ptr->client_ptr != client_ptr) 
     240    { 
     241      continue; 
     242    } 
     243 
     244#if defined(LOG_PORT_LOOKUP) 
     245    if (port_ptr->link) 
     246    { 
     247      uuid_unparse(port_ptr->link_uuid_override, uuid2_str); 
     248      log_info("comparing link uuid %s with %s", uuid2_str, uuid1_str); 
     249    } 
     250#endif 
     251 
     252    if (use_link_override_uuids && port_ptr->link && uuid_compare(port_ptr->link_uuid_override, uuid) == 0) 
     253    { 
     254#if defined(LOG_PORT_LOOKUP) 
     255      log_info("found link port %p of client '%s'", port_ptr->port, port_ptr->client_ptr->name); 
     256#endif 
     257      return port_ptr; 
     258    } 
     259 
     260    ladish_port_get_uuid(port_ptr->port, current_uuid); 
     261#if defined(LOG_PORT_LOOKUP) 
     262    uuid_unparse(current_uuid, uuid2_str); 
     263    log_info("comparing port uuid %s with %s", uuid2_str, uuid1_str); 
     264#endif 
     265    if (uuid_compare(current_uuid, uuid) == 0) 
     266    { 
     267#if defined(LOG_PORT_LOOKUP) 
     268      log_info("found port %p of client '%s'", port_ptr->port, port_ptr->client_ptr->name); 
     269#endif 
     270      return port_ptr; 
     271    } 
     272  } 
     273 
     274  return NULL; 
     275} 
     276 
     277static struct ladish_graph_connection * ladish_graph_find_connection_by_id(struct ladish_graph * graph_ptr, uint64_t connection_id) 
     278{ 
     279  struct list_head * node_ptr; 
     280  struct ladish_graph_connection * connection_ptr; 
     281 
     282  list_for_each(node_ptr, &graph_ptr->connections) 
     283  { 
     284    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings); 
     285    if (connection_ptr->id == connection_id) 
     286    { 
     287      return connection_ptr; 
     288    } 
     289  } 
     290 
     291  return NULL; 
     292} 
     293 
     294static 
     295struct ladish_graph_connection * 
     296ladish_graph_find_connection_by_ports( 
     297  struct ladish_graph * graph_ptr, 
     298  struct ladish_graph_port * port1_ptr, 
     299  struct ladish_graph_port * port2_ptr) 
     300{ 
     301  struct list_head * node_ptr; 
     302  struct ladish_graph_connection * connection_ptr; 
     303 
     304  list_for_each(node_ptr, &graph_ptr->connections) 
     305  { 
     306    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings); 
     307    if ((connection_ptr->port1_ptr == port1_ptr && connection_ptr->port2_ptr == port2_ptr) || 
     308        (connection_ptr->port1_ptr == port2_ptr && connection_ptr->port2_ptr == port1_ptr)) 
     309    { 
     310      return connection_ptr; 
     311    } 
     312  } 
     313 
     314  return NULL; 
     315} 
     316 
     317#define graph_ptr ((struct ladish_graph *)call_ptr->iface_context) 
     318 
     319static void get_all_ports(struct dbus_method_call * call_ptr) 
     320{ 
     321  DBusMessageIter iter, sub_iter; 
     322 
     323  call_ptr->reply = dbus_message_new_method_return(call_ptr->message); 
     324  if (call_ptr->reply == NULL) 
     325  { 
     326    goto fail; 
     327  } 
     328 
     329  dbus_message_iter_init_append(call_ptr->reply, &iter); 
     330 
     331  if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) 
     332  { 
     333    goto fail_unref; 
     334  } 
     335 
     336  if (!dbus_message_iter_close_container(&iter, &sub_iter)) 
     337  { 
     338    goto fail_unref; 
     339  } 
     340 
     341  return; 
     342 
     343fail_unref: 
     344  dbus_message_unref(call_ptr->reply); 
     345  call_ptr->reply = NULL; 
     346 
     347fail: 
     348  log_error("Ran out of memory trying to construct method return"); 
     349} 
     350 
     351static void get_graph(struct dbus_method_call * call_ptr) 
     352{ 
     353  dbus_uint64_t known_version; 
     354  dbus_uint64_t current_version; 
     355  DBusMessageIter iter; 
     356  DBusMessageIter clients_array_iter; 
     357  DBusMessageIter connections_array_iter; 
     358  DBusMessageIter client_struct_iter; 
     359  struct list_head * client_node_ptr; 
     360  struct ladish_graph_client * client_ptr; 
     361  DBusMessageIter ports_array_iter; 
     362  struct list_head * port_node_ptr; 
     363  struct ladish_graph_port * port_ptr; 
     364  DBusMessageIter port_struct_iter; 
     365  struct list_head * connection_node_ptr; 
     366  struct ladish_graph_connection * connection_ptr; 
     367  DBusMessageIter connection_struct_iter; 
     368 
     369  //log_info("get_graph() called"); 
     370 
     371  if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &known_version, DBUS_TYPE_INVALID)) 
     372  { 
     373    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s",  call_ptr->method_name, g_dbus_error.message); 
     374    dbus_error_free(&g_dbus_error); 
     375    return; 
     376  } 
     377 
     378  //log_info("Getting graph, known version is %" PRIu64, known_version); 
     379 
     380  call_ptr->reply = dbus_message_new_method_return(call_ptr->message); 
     381  if (call_ptr->reply == NULL) 
     382  { 
     383    log_error("Ran out of memory trying to construct method return"); 
     384    goto exit; 
     385  } 
     386 
     387  dbus_message_iter_init_append(call_ptr->reply, &iter); 
     388 
     389  current_version = graph_ptr->graph_version; 
     390  if (known_version > current_version) 
     391  { 
     392    lash_dbus_error( 
     393      call_ptr, 
     394      LASH_DBUS_ERROR_INVALID_ARGS, 
     395      "known graph version %" PRIu64 " is newer than actual version %" PRIu64, 
     396      known_version, 
     397      current_version); 
     398    goto exit; 
     399  } 
     400 
     401  if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &current_version)) 
     402  { 
     403    goto nomem; 
     404  } 
     405 
     406  if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter)) 
     407  { 
     408    goto nomem; 
     409  } 
     410 
     411  if (known_version < current_version) 
     412  { 
     413    list_for_each(client_node_ptr, &graph_ptr->clients) 
     414    { 
     415      client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings); 
     416 
     417      if (client_ptr->hidden) 
     418      { 
     419        continue; 
     420      } 
     421 
     422      if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter)) 
     423      { 
     424        goto nomem_close_clients_array; 
     425      } 
     426 
     427      if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id)) 
     428      { 
     429        goto nomem_close_client_struct; 
     430      } 
     431 
     432      log_info("client '%s' (%llu)", client_ptr->name, (unsigned long long)client_ptr->id); 
     433      if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name)) 
     434      { 
     435        goto nomem_close_client_struct; 
     436      } 
     437 
     438      if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter)) 
     439      { 
     440        goto nomem_close_client_struct; 
     441      } 
     442 
     443      list_for_each(port_node_ptr, &client_ptr->ports) 
     444      { 
     445        port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client); 
     446 
     447        if (port_ptr->hidden) 
     448        { 
     449          continue; 
     450        } 
     451 
     452        if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter)) 
     453        { 
     454          goto nomem_close_ports_array; 
     455        } 
     456 
     457        if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id)) 
     458        { 
     459          goto nomem_close_port_struct; 
     460        } 
     461 
     462        if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name)) 
     463        { 
     464          goto nomem_close_port_struct; 
     465        } 
     466 
     467        if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags)) 
     468        { 
     469          goto nomem_close_port_struct; 
     470        } 
     471 
     472        if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type)) 
     473        { 
     474          goto nomem_close_port_struct; 
     475        } 
     476 
     477        if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter)) 
     478        { 
     479          goto nomem_close_ports_array; 
     480        } 
     481      } 
     482 
     483      if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter)) 
     484      { 
     485        goto nomem_close_client_struct; 
     486      } 
     487 
     488      if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter)) 
     489      { 
     490        goto nomem_close_clients_array; 
     491      } 
     492    } 
     493  } 
     494 
     495  if (!dbus_message_iter_close_container(&iter, &clients_array_iter)) 
     496  { 
     497    goto nomem; 
     498  } 
     499 
     500  if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter)) 
     501  { 
     502    goto nomem; 
     503  } 
     504 
     505  if (known_version < current_version) 
     506  { 
     507    list_for_each(connection_node_ptr, &graph_ptr->connections) 
     508    { 
     509      connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings); 
     510 
     511      if (connection_ptr->hidden) 
     512      { 
     513        continue; 
     514      } 
     515 
     516      if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter)) 
     517      { 
     518        goto nomem_close_connections_array; 
     519      } 
     520 
     521      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->client_ptr->id)) 
     522      { 
     523        goto nomem_close_connection_struct; 
     524      } 
     525 
     526      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->client_ptr->name)) 
     527      { 
     528        goto nomem_close_connection_struct; 
     529      } 
     530 
     531      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->id)) 
     532      { 
     533        goto nomem_close_connection_struct; 
     534      } 
     535 
     536      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->name)) 
     537      { 
     538        goto nomem_close_connection_struct; 
     539      } 
     540 
     541      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->client_ptr->id)) 
     542      { 
     543        goto nomem_close_connection_struct; 
     544      } 
     545 
     546      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->client_ptr->name)) 
     547      { 
     548        goto nomem_close_connection_struct; 
     549      } 
     550 
     551      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->id)) 
     552      { 
     553        goto nomem_close_connection_struct; 
     554      } 
     555 
     556      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->name)) 
     557      { 
     558        goto nomem_close_connection_struct; 
     559      } 
     560 
     561      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id)) 
     562      { 
     563        goto nomem_close_connection_struct; 
     564      } 
     565 
     566      if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter)) 
     567      { 
     568        goto nomem_close_connections_array; 
     569      } 
     570    } 
     571  } 
     572 
     573  if (!dbus_message_iter_close_container(&iter, &connections_array_iter)) 
     574  { 
     575    goto nomem; 
     576  } 
     577 
     578  return; 
     579 
     580nomem_close_connection_struct: 
     581  dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter); 
     582 
     583nomem_close_connections_array: 
     584  dbus_message_iter_close_container(&iter, &connections_array_iter); 
     585  goto nomem; 
     586 
     587nomem_close_port_struct: 
     588  dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter); 
     589 
     590nomem_close_ports_array: 
     591  dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter); 
     592 
     593nomem_close_client_struct: 
     594  dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter); 
     595 
     596nomem_close_clients_array: 
     597  dbus_message_iter_close_container(&iter, &clients_array_iter); 
     598 
     599nomem: 
     600  dbus_message_unref(call_ptr->reply); 
     601  call_ptr->reply = NULL; 
     602  log_error("Ran out of memory trying to construct method return"); 
     603 
     604exit: 
     605  return; 
     606} 
     607 
     608static void connect_ports_by_name(struct dbus_method_call * call_ptr) 
     609{ 
     610  log_info("connect_ports_by_name() called."); 
     611  lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect by name is not implemented yet"); 
     612} 
     613 
     614static void connect_ports_by_id(struct dbus_method_call * call_ptr) 
     615{ 
     616  dbus_uint64_t port1_id; 
     617  dbus_uint64_t port2_id; 
     618  struct ladish_graph_port * port1_ptr; 
     619  struct ladish_graph_port * port2_ptr; 
     620 
     621  if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID)) 
     622  { 
     623    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message); 
     624    dbus_error_free(&g_dbus_error); 
     625    return; 
     626  } 
     627 
     628  log_info("connect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id); 
     629 
     630  if (graph_ptr->connect_handler == NULL) 
     631  { 
     632    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect requests on graph %s cannot be handlined", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
     633    return; 
     634  } 
     635 
     636  port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id); 
     637  if (port1_ptr == NULL) 
     638  { 
     639    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port1_id); 
     640    return; 
     641  } 
     642 
     643  port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id); 
     644  if (port2_ptr == NULL) 
     645  { 
     646    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port2_id); 
     647    return; 
     648  } 
     649 
     650  log_info("connecting '%s':'%s' to '%s':'%s'", port1_ptr->client_ptr->name, port1_ptr->name, port2_ptr->client_ptr->name, port2_ptr->name); 
     651 
     652  if (graph_ptr->connect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, port1_ptr->port, port2_ptr->port)) 
     653  { 
     654    method_return_new_void(call_ptr); 
     655  } 
     656  else 
     657  { 
     658    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect failed"); 
     659  } 
     660} 
     661 
     662static void disconnect_ports(struct dbus_method_call * call_ptr, struct ladish_graph_connection * connection_ptr) 
     663{ 
     664  log_info( 
     665    "disconnecting '%s':'%s' from '%s':'%s'", 
     666    connection_ptr->port1_ptr->client_ptr->name, 
     667    connection_ptr->port1_ptr->name, 
     668    connection_ptr->port2_ptr->client_ptr->name, 
     669    connection_ptr->port2_ptr->name); 
     670 
     671  connection_ptr->changing = true; 
     672  if (graph_ptr->disconnect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, connection_ptr->id)) 
     673  { 
     674    method_return_new_void(call_ptr); 
     675  } 
     676  else 
     677  { 
     678    connection_ptr->changing = false; 
     679    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect failed"); 
     680  } 
     681} 
     682 
     683static void disconnect_ports_by_name(struct dbus_method_call * call_ptr) 
     684{ 
     685  log_info("disconnect_ports_by_name() called."); 
     686  lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect by name is not implemented yet"); 
     687} 
     688 
     689static void disconnect_ports_by_id(struct dbus_method_call * call_ptr) 
     690{ 
     691  dbus_uint64_t port1_id; 
     692  dbus_uint64_t port2_id; 
     693  struct ladish_graph_port * port1_ptr; 
     694  struct ladish_graph_port * port2_ptr; 
     695  struct ladish_graph_connection * connection_ptr; 
     696 
     697  if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID)) 
     698  { 
     699    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message); 
     700    dbus_error_free(&g_dbus_error); 
     701    return; 
     702  } 
     703 
     704  log_info("disconnect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id); 
     705 
     706  if (graph_ptr->disconnect_handler == NULL) 
     707  { 
     708    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect requests on graph %s cannot be handlined", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
     709    return; 
     710  } 
     711 
     712  port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id); 
     713  if (port1_ptr == NULL) 
     714  { 
     715    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port1_id); 
     716    return; 
     717  } 
     718 
     719  port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id); 
     720  if (port2_ptr == NULL) 
     721  { 
     722    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port2_id); 
     723    return; 
     724  } 
     725 
     726  connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr); 
     727  if (connection_ptr == NULL) 
     728  { 
     729    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect not connected ports %"PRIu64" and %"PRIu64, port1_id, port2_id); 
     730    return; 
     731  } 
     732 
     733  disconnect_ports(call_ptr, connection_ptr); 
     734} 
     735 
     736static void disconnect_ports_by_connection_id(struct dbus_method_call * call_ptr) 
     737{ 
     738  dbus_uint64_t connection_id; 
     739  struct ladish_graph_connection * connection_ptr; 
     740 
     741  if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &connection_id, DBUS_TYPE_INVALID)) 
     742  { 
     743    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message); 
     744    dbus_error_free(&g_dbus_error); 
     745    return; 
     746  } 
     747 
     748  log_info("disconnect_ports_by_connection_id(%"PRIu64") called.", connection_id); 
     749 
     750  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id); 
     751  if (connection_ptr == NULL) 
     752  { 
     753    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot find connection with id %"PRIu64, connection_id); 
     754    return; 
     755  } 
     756 
     757  disconnect_ports(call_ptr, connection_ptr); 
     758} 
     759 
     760static void get_client_pid(struct dbus_method_call * call_ptr) 
     761{ 
     762  int64_t pid = 0; 
     763  method_return_new_single(call_ptr, DBUS_TYPE_INT64, &pid); 
     764} 
     765 
     766#undef graph_ptr 
     767 
     768bool ladish_graph_create(ladish_graph_handle * graph_handle_ptr, const char * opath) 
     769{ 
     770  struct ladish_graph * graph_ptr; 
     771 
     772  graph_ptr = malloc(sizeof(struct ladish_graph)); 
     773  if (graph_ptr == NULL) 
     774  { 
     775    log_error("malloc() failed to allocate struct graph_implementator"); 
     776    return false; 
     777  } 
     778 
     779  if (opath != NULL) 
     780  { 
     781    graph_ptr->opath = strdup(opath); 
     782    if (graph_ptr->opath == NULL) 
     783    { 
     784      log_error("strdup() failed for graph opath"); 
     785      free(graph_ptr); 
     786      return false; 
     787    } 
     788  } 
     789  else 
     790  { 
     791    graph_ptr->opath = NULL; 
     792  } 
     793 
     794  if (!ladish_dict_create(&graph_ptr->dict)) 
     795  { 
     796    log_error("ladish_dict_create() failed for graph"); 
     797    if (graph_ptr->opath != NULL) 
     798    { 
     799      free(graph_ptr->opath); 
     800    } 
     801    free(graph_ptr); 
     802    return false; 
     803  } 
     804 
     805  INIT_LIST_HEAD(&graph_ptr->clients); 
     806  INIT_LIST_HEAD(&graph_ptr->ports); 
     807  INIT_LIST_HEAD(&graph_ptr->connections); 
     808 
     809  graph_ptr->graph_version = 1; 
     810  graph_ptr->next_client_id = 1; 
     811  graph_ptr->next_port_id = 1; 
     812  graph_ptr->next_connection_id = 1; 
     813 
     814  graph_ptr->context = NULL; 
     815  graph_ptr->connect_handler = NULL; 
     816  graph_ptr->disconnect_handler = NULL; 
     817 
     818  graph_ptr->persist = true; 
     819 
     820  *graph_handle_ptr = (ladish_graph_handle)graph_ptr; 
     821  return true; 
     822} 
     823 
     824static 
     825struct ladish_graph_client * 
     826ladish_graph_find_client( 
     827  struct ladish_graph * graph_ptr, 
     828  ladish_client_handle client) 
     829{ 
     830  struct list_head * node_ptr; 
     831  struct ladish_graph_client * client_ptr; 
     832 
     833  list_for_each(node_ptr, &graph_ptr->clients) 
     834  { 
     835    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings); 
     836    if (client_ptr->client == client) 
     837    { 
     838      return client_ptr; 
     839    } 
     840  } 
     841 
     842  return NULL; 
     843} 
     844 
     845static 
     846struct ladish_graph_port * 
     847ladish_graph_find_port( 
     848  struct ladish_graph * graph_ptr, 
     849  ladish_port_handle port) 
     850{ 
     851  struct list_head * node_ptr; 
     852  struct ladish_graph_port * port_ptr; 
     853 
     854  //log_info("searching port %p", port); 
     855 
     856  list_for_each(node_ptr, &graph_ptr->ports) 
     857  { 
     858    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph); 
     859    //log_info("checking port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port); 
     860    if (port_ptr->port == port) 
     861    { 
     862      return port_ptr; 
     863    } 
     864  } 
     865 
     866  return NULL; 
     867} 
     868 
     869static 
     870struct ladish_graph_port * 
     871ladish_graph_find_port_by_jack_id_internal( 
     872  struct ladish_graph * graph_ptr, 
     873  uint64_t port_id, 
     874  bool room, 
     875  bool studio) 
     876{ 
     877  struct list_head * node_ptr; 
     878  struct ladish_graph_port * port_ptr; 
     879 
     880  ASSERT(room || studio); 
     881 
     882  list_for_each(node_ptr, &graph_ptr->ports) 
     883  { 
     884    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph); 
     885    //log_info("checking jack port id of port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port); 
     886    if ((studio && ladish_port_get_jack_id(port_ptr->port) == port_id) || 
     887        (room && port_ptr->link && ladish_port_get_jack_id_room(port_ptr->port) == port_id)) 
     888    { 
     889      //log_info("found"); 
     890      return port_ptr; 
     891    } 
     892  } 
     893 
     894  return NULL; 
     895} 
     896 
     897#if 0 
     898static 
     899struct ladish_graph_port * 
     900ladish_graph_find_client_port( 
     901  struct ladish_graph * graph_ptr, 
     902  struct ladish_graph_client * client_ptr, 
     903  ladish_port_handle port) 
     904{ 
     905  struct list_head * node_ptr; 
     906  struct ladish_graph_port * port_ptr; 
     907 
     908  list_for_each(node_ptr, &client_ptr->ports) 
     909  { 
     910    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client); 
     911    if (port_ptr->port == port) 
     912    { 
     913      return port_ptr; 
     914    } 
     915  } 
     916 
     917  return NULL; 
     918} 
     919#endif 
     920 
     921static void ladish_graph_hide_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr) 
     922{ 
     923  ASSERT(!connection_ptr->hidden); 
     924  connection_ptr->hidden = true; 
     925  graph_ptr->graph_version++; 
     926 
     927  if (graph_ptr->opath != NULL) 
     928  { 
     929    ladish_graph_emit_ports_disconnected(graph_ptr, connection_ptr); 
     930  } 
     931} 
     932 
     933static void ladish_graph_show_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
     934{ 
     935  if (port_ptr->client_ptr->hidden) 
     936  { 
     937    port_ptr->client_ptr->hidden = false; 
     938    graph_ptr->graph_version++; 
     939    if (graph_ptr->opath != NULL) 
     940    { 
     941      ladish_graph_emit_client_appeared(graph_ptr, port_ptr->client_ptr); 
     942    } 
     943  } 
     944 
     945  ASSERT(port_ptr->hidden); 
     946  port_ptr->hidden = false; 
     947  graph_ptr->graph_version++; 
     948  if (graph_ptr->opath != NULL) 
     949  { 
     950    ladish_graph_emit_port_appeared(graph_ptr, port_ptr); 
     951    ladish_try_connect_hidden_connections((ladish_graph_handle)graph_ptr); 
     952  } 
     953} 
     954 
     955static void ladish_graph_hide_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
     956{ 
     957  ASSERT(!port_ptr->hidden); 
     958  port_ptr->hidden = true; 
     959  graph_ptr->graph_version++; 
     960 
     961  if (graph_ptr->opath != NULL) 
     962  { 
     963    ladish_graph_emit_port_disappeared(graph_ptr, port_ptr); 
     964  } 
     965} 
     966 
     967static void ladish_graph_hide_client_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr) 
     968{ 
     969  ASSERT(!client_ptr->hidden); 
     970  client_ptr->hidden = true; 
     971  graph_ptr->graph_version++; 
     972 
     973  if (graph_ptr->opath != NULL) 
     974  { 
     975    ladish_graph_emit_client_disappeared(graph_ptr, client_ptr); 
     976  } 
     977} 
     978 
     979static void ladish_hide_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
     980{ 
     981  struct list_head * node_ptr; 
     982  struct ladish_graph_connection * connection_ptr; 
     983 
     984  log_info("hidding connections of port %"PRIu64, port_ptr->id); 
     985 
     986  ASSERT(graph_ptr->opath != NULL); 
     987 
     988  list_for_each(node_ptr, &graph_ptr->connections) 
     989  { 
     990    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings); 
     991    if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr)) 
     992    { 
     993      log_info("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id); 
     994      ladish_graph_hide_connection_internal(graph_ptr, connection_ptr); 
     995    } 
     996  } 
     997} 
     998 
     999static void ladish_graph_remove_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr) 
     1000{ 
     1001  list_del(&connection_ptr->siblings); 
     1002  graph_ptr->graph_version++; 
     1003 
     1004  if (!connection_ptr->hidden && graph_ptr->opath != NULL) 
     1005  { 
     1006    ladish_graph_emit_ports_disconnected(graph_ptr, connection_ptr); 
     1007  } 
     1008 
     1009  ladish_dict_destroy(connection_ptr->dict); 
     1010  free(connection_ptr); 
     1011} 
     1012 
     1013static void ladish_graph_remove_port_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr) 
     1014{ 
     1015  struct list_head * node_ptr; 
     1016  struct list_head * temp_node_ptr; 
     1017  struct ladish_graph_connection * connection_ptr; 
     1018 
     1019  list_for_each_safe(node_ptr, temp_node_ptr, &graph_ptr->connections) 
     1020  { 
     1021    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings); 
     1022    if (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr) 
     1023    { 
     1024      log_info("removing connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id); 
     1025      ladish_graph_remove_connection_internal(graph_ptr, connection_ptr); 
     1026    } 
     1027  } 
     1028} 
     1029 
     1030static 
     1031void 
     1032ladish_graph_remove_port_internal( 
     1033  struct ladish_graph * graph_ptr, 
     1034  struct ladish_graph_client * client_ptr, 
     1035  struct ladish_graph_port * port_ptr) 
     1036{ 
     1037  ladish_graph_remove_port_connections(graph_ptr, port_ptr); 
     1038 
     1039  ladish_port_del_ref(port_ptr->port); 
     1040 
     1041  list_del(&port_ptr->siblings_client); 
     1042  list_del(&port_ptr->siblings_graph); 
     1043 
     1044  log_info("removing port '%s':'%s' (%"PRIu64":%"PRIu64") from graph %s", client_ptr->name, port_ptr->name, client_ptr->id, port_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
     1045  if (graph_ptr->opath != NULL && !port_ptr->hidden) 
     1046  { 
     1047    ASSERT(port_ptr->client_ptr == client_ptr); 
     1048    ladish_graph_emit_port_disappeared(graph_ptr, port_ptr); 
     1049  } 
     1050 
     1051  free(port_ptr->name); 
     1052  free(port_ptr); 
     1053} 
     1054 
     1055static 
     1056void 
     1057ladish_graph_remove_client_internal( 
     1058  struct ladish_graph * graph_ptr, 
     1059  struct ladish_graph_client * client_ptr, 
     1060  bool destroy_client, 
     1061  ladish_graph_simple_port_callback port_callback) 
     1062{ 
     1063  struct ladish_graph_port * port_ptr; 
     1064 
     1065  while (!list_empty(&client_ptr->ports)) 
     1066  { 
     1067    port_ptr = list_entry(client_ptr->ports.next, struct ladish_graph_port, siblings_client); 
     1068    if (port_callback != NULL) 
     1069    { 
     1070      port_callback(port_ptr->port); 
     1071    } 
     1072    ladish_graph_remove_port_internal(graph_ptr, client_ptr, port_ptr); 
     1073  } 
     1074 
     1075  graph_ptr->graph_version++; 
     1076  list_del(&client_ptr->siblings); 
     1077  log_info("removing client '%s' (%"PRIu64") from graph %s", client_ptr->name, client_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
     1078  if (graph_ptr->opath != NULL && !client_ptr->hidden) 
     1079  { 
     1080    ladish_graph_emit_client_disappeared(graph_ptr, client_ptr); 
     1081  } 
     1082 
     1083  free(client_ptr->name); 
     1084 
     1085  if (destroy_client) 
     1086  { 
     1087    ladish_client_destroy(client_ptr->client); 
     1088  } 
     1089 
     1090  free(client_ptr); 
     1091} 
     1092 
     1093bool ladish_graph_client_looks_empty_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr) 
     1094{ 
     1095  struct list_head * node_ptr; 
     1096  struct ladish_graph_port * port_ptr; 
     1097 
     1098  list_for_each(node_ptr, &client_ptr->ports) 
     1099  { 
     1100    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client); 
     1101    if (!port_ptr->hidden) 
     1102    { 
     1103      //log_info("port '%s' is visible, client '%s' does not look empty", port_ptr->name, client_ptr->name); 
     1104      return false; 
     1105    } 
     1106    else 
     1107    { 
     1108      //log_info("port '%s' is invisible", port_ptr->name); 
     1109    } 
     1110  } 
     1111 
     1112  //log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
     1113  return true; 
     1114} 
     1115 
     1116#define graph_ptr ((struct ladish_graph *)graph_handle) 
     1117 
     1118void ladish_graph_destroy(ladish_graph_handle graph_handle) 
     1119{ 
     1120  ladish_graph_clear(graph_handle, NULL); 
     1121  ladish_dict_destroy(graph_ptr->dict); 
     1122  if (graph_ptr->opath != NULL) 
     1123  { 
     1124    free(graph_ptr->opath); 
     1125  } 
     1126  free(graph_ptr); 
     1127} 
     1128 
     1129const char * ladish_graph_get_opath(ladish_graph_handle graph_handle) 
     1130{ 
     1131  return graph_ptr->opath; 
     1132} 
     1133 
     1134const char * ladish_graph_get_description(ladish_graph_handle graph_handle) 
     1135{ 
     1136  return graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"; 
     1137} 
     1138 
     1139void 
     1140ladish_graph_set_connection_handlers( 
     1141  ladish_graph_handle graph_handle, 
     1142  void * graph_context, 
     1143  ladish_graph_connect_request_handler connect_handler, 
     1144  ladish_graph_disconnect_request_handler disconnect_handler) 
     1145{ 
     1146  log_info("setting connection handlers for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
     1147  graph_ptr->context = graph_context; 
     1148  graph_ptr->connect_handler = connect_handler; 
     1149  graph_ptr->disconnect_handler = disconnect_handler; 
     1150} 
     1151 
     1152void ladish_graph_clear(ladish_graph_handle graph_handle, ladish_graph_simple_port_callback port_callback) 
     1153{ 
     1154  struct ladish_graph_client * client_ptr; 
     1155  struct ladish_graph_connection * connection_ptr; 
     1156 
     1157  log_info("ladish_graph_clear() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK"); 
     1158 
     1159  while (!list_empty(&graph_ptr->connections)) 
     1160  { 
     1161    connection_ptr = list_entry(graph_ptr->connections.next, struct ladish_graph_connection, siblings); 
     1162    ladish_graph_remove_connection_internal(graph_ptr, connection_ptr); 
     1163  } 
     1164 
     1165  while (!list_empty(&graph_ptr->clients)) 
     1166  { 
     1167    client_ptr = list_entry(graph_ptr->clients.next, struct ladish_graph_client, siblings); 
     1168    ladish_graph_remove_client_internal(graph_ptr, client_ptr, true, port_callback); 
     1169  } 
     1170} 
     1171 
     1172void * ladish_graph_get_dbus_context(ladish_graph_handle graph_handle) 
     1173{ 
     1174  return graph_handle; 
     1175} 
     1176 
     1177ladish_dict_handle ladish_graph_get_dict(ladish_graph_handle graph_handle) 
     1178{ 
     1179  return graph_ptr->dict; 
     1180} 
     1181 
     1182void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t connection_id) 
     1183{ 
     1184  struct ladish_graph_connection * connection_ptr; 
     1185 
     1186  log_info("ladish_graph_show_connection() called."); 
     1187 
     1188  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id); 
     1189  if (connection_ptr == NULL) 
     1190  { 
     1191    ASSERT_NO_PASS; 
     1192    return; 
     1193  } 
     1194 
     1195  ASSERT(graph_ptr->opath != NULL); 
     1196  ASSERT(connection_ptr->hidden); 
     1197  connection_ptr->hidden = false; 
     1198  connection_ptr->changing = false; 
     1199  graph_ptr->graph_version++; 
     1200 
     1201  ladish_graph_emit_ports_connected(graph_ptr, connection_ptr); 
     1202} 
     1203 
    11951204void ladish_graph_show_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle) 
    11961205{ 
     
    12711280  if (graph_ptr->opath != NULL) 
    12721281  { 
    1273     dbus_signal_emit( 
    1274       g_dbus_connection, 
    1275       graph_ptr->opath, 
    1276       JACKDBUS_IFACE_PATCHBAY, 
    1277       "ClientAppeared", 
    1278       "tts", 
    1279       &graph_ptr->graph_version, 
    1280       &client_ptr->id, 
    1281       &client_ptr->name); 
     1282    ladish_graph_emit_client_appeared(graph_ptr, client_ptr); 
    12821283  } 
    12831284} 
     
    13321333  if (!hidden && graph_ptr->opath != NULL) 
    13331334  { 
    1334     dbus_signal_emit( 
    1335       g_dbus_connection, 
    1336       graph_ptr->opath, 
    1337       JACKDBUS_IFACE_PATCHBAY, 
    1338       "ClientAppeared", 
    1339       "tts", 
    1340       &graph_ptr->graph_version, 
    1341       &client_ptr->id, 
    1342       &client_ptr->name); 
     1335    ladish_graph_emit_client_appeared(graph_ptr, client_ptr); 
    13431336  } 
    13441337 
     
    14791472  if (!hidden && graph_ptr->opath != NULL) 
    14801473  { 
    1481     dbus_signal_emit( 
    1482       g_dbus_connection, 
    1483       graph_ptr->opath, 
    1484       JACKDBUS_IFACE_PATCHBAY, 
    1485       "PortsConnected", 
    1486       "ttstststst", 
    1487       &graph_ptr->graph_version, 
    1488       &port1_ptr->client_ptr->id, 
    1489       &port1_ptr->client_ptr->name, 
    1490       &port1_ptr->id, 
    1491       &port1_ptr->name, 
    1492       &port2_ptr->client_ptr->id, 
    1493       &port2_ptr->client_ptr->name, 
    1494       &port2_ptr->id, 
    1495       &port2_ptr->name, 
    1496       &connection_ptr->id); 
     1474    ladish_graph_emit_ports_connected(graph_ptr, connection_ptr); 
    14971475  } 
    14981476