root/daemon/room_load.c @ d9183f0417a9b7bce5e08abf8523b77f9e92cf01

Revision d9183f0417a9b7bce5e08abf8523b77f9e92cf01, 24.5 KB (checked in by Nedko Arnaudov <nedko@…>, 3 years ago)

ladishd: fix load of project dict

  • Property mode set to 100644
Line 
1/* -*- Mode: C ; c-basic-offset: 2 -*- */
2/*
3 * LADI Session Handler (ladish)
4 *
5 * Copyright (C) 2010 Nedko Arnaudov <nedko@arnaudov.name>
6 *
7 **************************************************************************
8 * This file contains the parts of room object implementation
9 * that are related to project load functionality
10 **************************************************************************
11 *
12 * LADI Session Handler is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * LADI Session Handler is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
24 * or write to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 */
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <expat.h>
33
34#include "room_internal.h"
35#include "../common/catdup.h"
36#include "load.h"
37#include "../proxies/notify_proxy.h"
38#include "escape.h"
39#include "studio.h"
40#include "recent_projects.h"
41
42#define context_ptr ((struct ladish_parse_context *)data)
43#define room_ptr ((struct ladish_room *)context_ptr->room)
44
45static void callback_chrdata(void * data, const XML_Char * s, int len)
46{
47  if (context_ptr->error)
48  {
49    return;
50  }
51
52  if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_PARAMETER ||
53      context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_KEY ||
54      context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_APPLICATION)
55  {
56    if (context_ptr->data_used + len >= sizeof(context_ptr->data))
57    {
58      log_error("xml parse max char data length reached");
59      context_ptr->error = XML_TRUE;
60      return;
61    }
62
63    memcpy(context_ptr->data + context_ptr->data_used, s, len);
64    context_ptr->data_used += len;
65  }
66}
67
68static void callback_elstart(void * data, const char * el, const char ** attr)
69{
70  const char * name;
71  const char * uuid_str;
72  uuid_t uuid;
73  const char * uuid2_str;
74  uuid_t uuid2;
75  ladish_port_handle port1;
76  ladish_port_handle port2;
77  uint32_t port_type;
78  uint32_t port_flags;
79  size_t len;
80
81  if (context_ptr->error)
82  {
83    return;
84  }
85
86  if (context_ptr->depth + 1 >= MAX_STACK_DEPTH)
87  {
88    log_error("xml parse max stack depth reached");
89    context_ptr->error = XML_TRUE;
90    return;
91  }
92
93  if (strcmp(el, "project") == 0)
94  {
95    //log_info("<project>");
96    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_PROJECT;
97
98    if (!ladish_get_name_and_uuid_attributes("/project", attr, &name, &uuid_str, uuid))
99    {
100      context_ptr->error = XML_TRUE;
101      return;
102    }
103
104    len = strlen(name) + 1;
105    room_ptr->project_name = malloc(len);
106    if (room_ptr->project_name == NULL)
107    {
108      log_error("malloc() failed for project name with length %zu", len);
109      context_ptr->error = XML_TRUE;
110      return;
111    }
112
113    unescape(name, len, room_ptr->project_name);
114
115    log_info("Project '%s' with uuid %s", room_ptr->project_name, uuid_str);
116
117    uuid_copy(room_ptr->project_uuid, uuid);
118
119    return;
120  }
121
122  if (strcmp(el, "jack") == 0)
123  {
124    //log_info("<jack>");
125    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_JACK;
126    return;
127  }
128
129  if (strcmp(el, "clients") == 0)
130  {
131    //log_info("<clients>");
132    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_CLIENTS;
133    return;
134  }
135
136  if (strcmp(el, "room") == 0)
137  {
138    //log_info("<room>");
139    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_ROOM;
140    return;
141  }
142
143  if (strcmp(el, "client") == 0)
144  {
145    //log_info("<client>");
146    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_CLIENT;
147    if (context_ptr->client != NULL)
148    {
149        log_error("nested clients");
150        context_ptr->error = XML_TRUE;
151        return;
152    }
153
154    if (context_ptr->depth == 3 &&
155        context_ptr->element[0] == PARSE_CONTEXT_PROJECT &&
156        context_ptr->element[1] == PARSE_CONTEXT_JACK &&
157        context_ptr->element[2] == PARSE_CONTEXT_CLIENTS)
158    {
159      if (!ladish_get_name_and_uuid_attributes("/project/jack/clients/client", attr, &name, &uuid_str, uuid))
160      {
161        context_ptr->error = XML_TRUE;
162        return;
163      }
164
165      log_info("jack client \"%s\" with uuid %s", name, uuid_str);
166
167      context_ptr->client = ladish_graph_find_client_by_uuid(ladish_studio_get_jack_graph(), uuid);
168      if (context_ptr->client != NULL)
169      {
170        log_info("Found existing client");
171        return;
172      }
173
174      if (!ladish_client_create(uuid, &context_ptr->client))
175      {
176        log_error("ladish_client_create() failed.");
177        context_ptr->error = XML_TRUE;
178        ASSERT(context_ptr->client == NULL);
179        return;
180      }
181
182      if (!ladish_graph_add_client(ladish_studio_get_jack_graph(), context_ptr->client, name, true))
183      {
184        log_error("ladish_graph_add_client() failed to add client '%s' to JACK graph", name);
185        context_ptr->error = XML_TRUE;
186        ladish_client_destroy(context_ptr->client);
187        context_ptr->client = NULL;
188      }
189
190      return;
191    }
192
193    if (context_ptr->depth == 2 &&
194        context_ptr->element[0] == PARSE_CONTEXT_PROJECT &&
195        context_ptr->element[1] == PARSE_CONTEXT_CLIENTS)
196    {
197      if (!ladish_get_name_and_uuid_attributes("/room/clients/client", attr, &name, &uuid_str, uuid))
198      {
199        context_ptr->error = XML_TRUE;
200        return;
201      }
202
203      log_info("room client \"%s\" with uuid %s", name, uuid_str);
204
205      context_ptr->client = ladish_graph_find_client_by_uuid(room_ptr->graph, uuid);
206      if (context_ptr->client != NULL)
207      {
208        log_info("Found existing client");
209        return;
210      }
211
212      if (!ladish_client_create(uuid, &context_ptr->client))
213      {
214        log_error("ladish_client_create() failed.");
215        context_ptr->error = XML_TRUE;
216        ASSERT(context_ptr->client == NULL);
217        return;
218      }
219
220      if (!ladish_graph_add_client(room_ptr->graph, context_ptr->client, name, true))
221      {
222        log_error("ladish_graph_add_client() failed to add client '%s' to room graph", name);
223        context_ptr->error = XML_TRUE;
224        ladish_client_destroy(context_ptr->client);
225        context_ptr->client = NULL;
226      }
227
228      return;
229    }
230
231    log_error("client element in wrong place");
232    ladish_dump_element_stack(context_ptr);
233    context_ptr->error = XML_TRUE;
234    return;
235  }
236
237  if (strcmp(el, "ports") == 0)
238  {
239    //log_info("<ports>");
240    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_PORTS;
241    return;
242  }
243
244  if (strcmp(el, "port") == 0)
245  {
246    //log_info("<port>");
247    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_PORT;
248
249    if (context_ptr->port != NULL)
250    {
251        log_error("nested ports");
252        context_ptr->error = XML_TRUE;
253        return;
254    }
255
256    if (context_ptr->depth >= 3 &&
257        context_ptr->element[context_ptr->depth - 3] == PARSE_CONTEXT_CLIENTS &&
258        context_ptr->element[context_ptr->depth - 2] == PARSE_CONTEXT_CLIENT &&
259        context_ptr->element[context_ptr->depth - 1] == PARSE_CONTEXT_PORTS)
260    {
261      //log_info("client port");
262      if (context_ptr->client == NULL)
263      {
264        log_error("client-less port");
265        context_ptr->error = XML_TRUE;
266        return;
267      }
268
269      if (context_ptr->depth == 5 && context_ptr->element[0] == PARSE_CONTEXT_PROJECT && context_ptr->element[1] == PARSE_CONTEXT_JACK)
270      {
271        if (!ladish_get_name_and_uuid_attributes("/project/jack/clients/client/ports/port", attr, &name, &uuid_str, uuid))
272        {
273          context_ptr->error = XML_TRUE;
274          return;
275        }
276
277        log_info("jack port \"%s\" with uuid %s", name, uuid_str);
278
279        if (!ladish_port_create(uuid, false, &context_ptr->port))
280        {
281          log_error("ladish_port_create() failed.");
282          return;
283        }
284
285        ladish_port_set_vgraph(context_ptr->port, room_ptr->graph);
286
287        if (!ladish_graph_add_port(ladish_studio_get_jack_graph(), context_ptr->client, context_ptr->port, name, 0, 0, true))
288        {
289          log_error("ladish_graph_add_port() failed.");
290          ladish_port_destroy(context_ptr->port);
291          context_ptr->port = NULL;
292        }
293
294        return;
295      }
296      else if (context_ptr->depth == 4 && context_ptr->element[0] == PARSE_CONTEXT_PROJECT)
297      {
298        if (!ladish_get_name_and_uuid_attributes("/project/clients/client/ports/port", attr, &name, &uuid_str, uuid))
299        {
300          context_ptr->error = XML_TRUE;
301          return;
302        }
303
304        context_ptr->port = ladish_graph_find_port_by_uuid(room_ptr->graph, uuid, false, NULL);
305        if (context_ptr->port != NULL)
306        {
307          if (!ladish_port_is_link(context_ptr->port))
308          {
309            log_info("port \"%s\" with uuid %s already exists in room graph and is not a room-studio link", name, uuid_str);
310            context_ptr->error = XML_TRUE;
311          }
312          return;
313        }
314
315        /* there can be two ports with same uuid in the jack graph so we search for a port
316           with vgraph for the room where porject is being loaded to */
317        context_ptr->port = ladish_graph_find_port_by_uuid(ladish_studio_get_jack_graph(), uuid, false, room_ptr->graph);
318        if (context_ptr->port == NULL)
319        {
320          log_info("app port \"%s\" with uuid %s not found in the jack graph", name, uuid_str);
321          context_ptr->error = XML_TRUE;
322          ladish_graph_dump(ladish_studio_get_jack_graph());
323          return;
324        }
325
326        log_info("app port \"%s\" with uuid %s", name, uuid_str);
327
328        if (!ladish_graph_add_port(room_ptr->graph, context_ptr->client, context_ptr->port, name, 0, 0, true))
329        {
330          log_error("ladish_graph_add_port() failed.");
331          ladish_port_destroy(context_ptr->port);
332          context_ptr->port = NULL;
333          return;
334        }
335
336        return;
337      }
338    }
339    else if (context_ptr->depth == 2 &&
340             context_ptr->element[0] == PARSE_CONTEXT_PROJECT &&
341             context_ptr->element[1] == PARSE_CONTEXT_ROOM)
342    {
343      ASSERT(context_ptr->room != NULL);
344      //log_info("room port");
345
346      if (!ladish_get_name_and_uuid_attributes("/project/room/port", attr, &name, &uuid_str, uuid))
347      {
348        context_ptr->error = XML_TRUE;
349        return;
350      }
351
352      log_info("room port \"%s\" with uuid %s", name, uuid_str);
353
354      if (!ladish_parse_port_type_and_direction_attributes("/project/room/port", attr, &port_type, &port_flags))
355      {
356        context_ptr->error = XML_TRUE;
357        return;
358      }
359
360      context_ptr->port = ladish_graph_find_port_by_uuid(room_ptr->graph, uuid, false, NULL);
361      if (context_ptr->port == NULL)
362      {
363        log_error("Cannot find room link port.");
364        context_ptr->port = NULL;
365      }
366
367      return;
368    }
369
370    log_error("port element in wrong place");
371    ladish_dump_element_stack(context_ptr);
372    context_ptr->error = XML_TRUE;
373
374    return;
375  }
376
377  if (strcmp(el, "connections") == 0)
378  {
379    //log_info("<connections>");
380    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_CONNECTIONS;
381    return;
382  }
383
384  if (strcmp(el, "connection") == 0)
385  {
386    //log_info("<connection>");
387    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_CONNECTION;
388
389    uuid_str = ladish_get_uuid_attribute(attr, "port1", uuid, false);
390    if (uuid_str == NULL)
391    {
392      log_error("/room/connections/connection \"port1\" attribute is not available.");
393      context_ptr->error = XML_TRUE;
394      return;
395    }
396
397    uuid2_str = ladish_get_uuid_attribute(attr, "port2", uuid2, false);
398    if (uuid2_str == NULL)
399    {
400      log_error("/room/connections/connection \"port2\" attribute is not available.");
401      context_ptr->error = XML_TRUE;
402      return;
403    }
404
405    log_info("room connection between port %s and port %s", uuid_str, uuid2_str);
406
407    port1 = ladish_graph_find_port_by_uuid(room_ptr->graph, uuid, true, NULL);
408    if (port1 == NULL)
409    {
410      log_error("room client with unknown port %s", uuid_str);
411      context_ptr->error = XML_TRUE;
412      return;
413    }
414
415    port2 = ladish_graph_find_port_by_uuid(room_ptr->graph, uuid2, true, NULL);
416    if (port2 == NULL)
417    {
418      log_error("room client with unknown port %s", uuid2_str);
419      context_ptr->error = XML_TRUE;
420      return;
421    }
422
423    context_ptr->connection_id = ladish_graph_add_connection(room_ptr->graph, port1, port2, true);
424    if (context_ptr->connection_id == 0)
425    {
426      log_error("ladish_graph_add_connection() failed.");
427      return;
428    }
429
430    return;
431  }
432
433  if (strcmp(el, "applications") == 0)
434  {
435    //log_info("<applications>");
436    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_APPLICATIONS;
437    return;
438  }
439
440  if (strcmp(el, "application") == 0)
441  {
442    //log_info("<application>");
443    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_APPLICATION;
444
445    name = ladish_get_string_attribute(attr, "name");
446    if (name == NULL)
447    {
448      log_error("application \"name\" attribute is not available.");
449      context_ptr->error = XML_TRUE;
450      return;
451    }
452
453    if (ladish_get_bool_attribute(attr, "terminal", &context_ptr->terminal) == NULL)
454    {
455      log_error("application \"terminal\" attribute is not available. name=\"%s\"", name);
456      context_ptr->error = XML_TRUE;
457      return;
458    }
459
460    if (ladish_get_bool_attribute(attr, "autorun", &context_ptr->autorun) == NULL)
461    {
462      log_error("application \"autorun\" attribute is not available. name=\"%s\"", name);
463      context_ptr->error = XML_TRUE;
464      return;
465    }
466
467    if (ladish_get_byte_attribute(attr, "level", &context_ptr->level) == NULL)
468    {
469      log_error("application \"level\" attribute is not available. name=\"%s\"", name);
470      context_ptr->error = XML_TRUE;
471      return;
472    }
473
474    context_ptr->str = strdup(name);
475    if (context_ptr->str == NULL)
476    {
477      log_error("strdup() failed");
478      context_ptr->error = XML_TRUE;
479      return;
480    }
481
482    context_ptr->data_used = 0;
483    return;
484  }
485
486  if (strcmp(el, "dict") == 0)
487  {
488    //log_info("<dict>");
489    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_DICT;
490
491    if (context_ptr->dict != NULL)
492    {
493        log_error("nested dicts");
494        context_ptr->error = XML_TRUE;
495        return;
496    }
497
498    if (context_ptr->depth == 1 &&
499        context_ptr->element[0] == PARSE_CONTEXT_PROJECT)
500    {
501      context_ptr->dict = ladish_graph_get_dict(room_ptr->graph);
502      ASSERT(context_ptr->dict != NULL);
503    }
504    else if (context_ptr->depth > 0 &&
505             context_ptr->element[context_ptr->depth - 1] == PARSE_CONTEXT_CLIENT)
506    {
507      ASSERT(context_ptr->client != NULL);
508      context_ptr->dict = ladish_client_get_dict(context_ptr->client);
509      ASSERT(context_ptr->dict != NULL);
510    }
511    else if (context_ptr->depth > 0 &&
512             context_ptr->element[context_ptr->depth - 1] == PARSE_CONTEXT_PORT)
513    {
514      ASSERT(context_ptr->port != NULL);
515      context_ptr->dict = ladish_port_get_dict(context_ptr->port);
516      ASSERT(context_ptr->dict != NULL);
517    }
518    else if (context_ptr->depth > 0 &&
519             context_ptr->element[context_ptr->depth - 1] == PARSE_CONTEXT_CONNECTION)
520    {
521      ASSERT(context_ptr->port != NULL);
522      context_ptr->dict = ladish_graph_get_connection_dict(room_ptr->graph, context_ptr->connection_id);
523      ASSERT(context_ptr->dict != NULL);
524    }
525    else
526    {
527      log_error("unexpected dict XML element");
528      context_ptr->error = XML_TRUE;
529      return;
530    }
531
532    return;
533  }
534
535  if (strcmp(el, "key") == 0)
536  {
537    //log_info("<key>");
538    context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_KEY;
539
540    if (context_ptr->dict == NULL)
541    {
542        log_error("dict-less key");
543        context_ptr->error = XML_TRUE;
544        return;
545    }
546
547    name = ladish_get_string_attribute(attr, "name");
548    if (name == NULL)
549    {
550      log_error("dict/key \"name\" attribute is not available.");
551      context_ptr->error = XML_TRUE;
552      return;
553    }
554
555    context_ptr->str = strdup(name);
556    if (context_ptr->str == NULL)
557    {
558      log_error("strdup() failed");
559      context_ptr->error = XML_TRUE;
560      return;
561    }
562
563    context_ptr->data_used = 0;
564
565    return;
566  }
567
568  log_error("unknown element \"%s\"", el);
569  context_ptr->error = XML_TRUE;
570}
571
572static void callback_elend(void * data, const char * el)
573{
574  if (context_ptr->error)
575  {
576    return;
577  }
578
579  //log_info("element end (depth = %d, element = %u)", context_ptr->depth, context_ptr->element[context_ptr->depth]);
580
581  if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_KEY &&
582      context_ptr->depth > 0 &&
583      context_ptr->element[context_ptr->depth - 1] == PARSE_CONTEXT_DICT)
584  {
585    ASSERT(context_ptr->dict != NULL);
586    context_ptr->data[context_ptr->data_used] = 0;
587    log_info("dict key '%s' with value '%s'", context_ptr->str, context_ptr->data);
588    if (!ladish_dict_set(context_ptr->dict, context_ptr->str, context_ptr->data))
589    {
590      log_error("ladish_dict_set() failed");
591      context_ptr->error = XML_TRUE;
592      return;
593    }
594  }
595  else if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_ROOM)
596  {
597    //log_info("</room>");
598  }
599  else if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_JACK)
600  {
601    //log_info("</jack>");
602  }
603  else if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_DICT)
604  {
605    //log_info("</dict>");
606    ASSERT(context_ptr->dict != NULL);
607    context_ptr->dict = NULL;
608  }
609  else if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_CLIENT)
610  {
611    //log_info("</client>");
612    ASSERT(context_ptr->client != NULL);
613    context_ptr->client = NULL;
614  }
615  else if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_PORT)
616  {
617    //log_info("</port>");
618    ASSERT(context_ptr->port != NULL);
619    context_ptr->port = NULL;
620  }
621  else if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_APPLICATION)
622  {
623    context_ptr->data[unescape(context_ptr->data, context_ptr->data_used, context_ptr->data)] = 0;
624    unescape(context_ptr->str, strlen(context_ptr->str) + 1, context_ptr->str);
625
626    log_info("application '%s' (%s, %s, level %u) with commandline '%s'", context_ptr->str, context_ptr->terminal ? "terminal" : "shell", context_ptr->autorun ? "autorun" : "stopped", (unsigned int)context_ptr->level, context_ptr->data);
627
628    if (ladish_app_supervisor_add(room_ptr->app_supervisor, context_ptr->str, context_ptr->autorun, context_ptr->data, context_ptr->terminal, context_ptr->level) == NULL)
629    {
630      log_error("ladish_app_supervisor_add() failed.");
631      context_ptr->error = XML_TRUE;
632    }
633  }
634
635  context_ptr->depth--;
636
637  if (context_ptr->str != NULL)
638  {
639    free(context_ptr->str);
640    context_ptr->str = NULL;
641  }
642
643  return;
644}
645
646#undef room_ptr
647#undef context_ptr
648
649#define room_ptr ((struct ladish_room *)room_handle)
650
651bool ladish_room_load_project(ladish_room_handle room_handle, const char * project_dir)
652{
653  char * path;
654  struct stat st;
655  XML_Parser parser;
656  int bytes_read;
657  void * buffer;
658  int fd;
659  enum XML_Status xmls;
660  struct ladish_parse_context parse_context;
661  bool ret;
662
663  log_info("Loading project '%s' into room '%s'", project_dir, room_ptr->name);
664
665  ASSERT(room_ptr->project_state == ROOM_PROJECT_STATE_UNLOADED);
666  ASSERT(room_ptr->project_dir == NULL);
667  ASSERT(room_ptr->project_name == NULL);
668  ASSERT(!ladish_app_supervisor_has_apps(room_ptr->app_supervisor));
669  ASSERT(!ladish_graph_has_visible_connections(room_ptr->graph));
670
671  ret = false;
672
673  room_ptr->project_dir = strdup(project_dir);
674  if (room_ptr->project_dir == NULL)
675  {
676    log_error("strdup() failed to for project dir");
677    goto exit;
678  }
679
680  path = catdup(project_dir, LADISH_PROJECT_FILENAME);
681  if (path == NULL)
682  {
683    log_error("catdup() failed to compose xml file path");
684    goto exit;
685  }
686
687  if (stat(path, &st) != 0)
688  {
689    log_error("failed to stat '%s': %d (%s)", path, errno, strerror(errno));
690    goto free_path;
691  }
692
693  fd = open(path, O_RDONLY);
694  if (fd == -1)
695  {
696    log_error("failed to open '%s': %d (%s)", path, errno, strerror(errno));
697    goto free_path;
698  }
699
700  parser = XML_ParserCreate(NULL);
701  if (parser == NULL)
702  {
703    log_error("XML_ParserCreate() failed to create parser object.");
704    goto close;
705  }
706
707  //log_info("conf file size is %llu bytes", (unsigned long long)st.st_size);
708
709  /* we are expecting that conf file has small enough size to fit in memory */
710
711  buffer = XML_GetBuffer(parser, st.st_size);
712  if (buffer == NULL)
713  {
714    log_error("XML_GetBuffer() failed.");
715    goto free_parser;
716  }
717
718  bytes_read = read(fd, buffer, st.st_size);
719  if (bytes_read != st.st_size)
720  {
721    log_error("read() returned unexpected result.");
722    goto free_parser;
723  }
724
725  //log_info("\n----------\n%s\n-----------\n", buffer);
726  //goto free_parser;
727
728  parse_context.error = XML_FALSE;
729  parse_context.depth = -1;
730  parse_context.str = NULL;
731  parse_context.client = NULL;
732  parse_context.port = NULL;
733  parse_context.dict = NULL;
734  parse_context.room = room_handle;
735
736  XML_SetElementHandler(parser, callback_elstart, callback_elend);
737  XML_SetCharacterDataHandler(parser, callback_chrdata);
738  XML_SetUserData(parser, &parse_context);
739
740  xmls = XML_ParseBuffer(parser, bytes_read, XML_TRUE);
741  if (xmls == XML_STATUS_ERROR && !parse_context.error)
742  {
743    log_error("XML_ParseBuffer() failed.");
744  }
745  if (xmls == XML_STATUS_ERROR || parse_context.error)
746  {
747    goto free_parser;
748  }
749
750  ladish_interlink_clients(room_ptr->graph, room_ptr->app_supervisor);
751  /* ladish_graph_dump(ladish_studio_get_jack_graph()); */
752  /* ladish_graph_dump(room_ptr->graph); */
753
754  ladish_app_supervisor_set_directory(room_ptr->app_supervisor, project_dir);
755  ladish_graph_trick_dicts(room_ptr->graph);
756  ladish_try_connect_hidden_connections(room_ptr->graph);
757  ladish_app_supervisor_autorun(room_ptr->app_supervisor);
758
759  ladish_recent_project_use(room_ptr->project_dir);
760  ladish_room_emit_project_properties_changed(room_ptr);
761
762  ret = true;
763
764free_parser:
765  XML_ParserFree(parser);
766close:
767  close(fd);
768free_path:
769  free(path);
770exit:
771  if (!ret)
772  {
773    ladish_room_clear_project(room_ptr);
774    ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Project load failed", LADISH_CHECK_LOG_TEXT);
775  }
776  else
777  {
778    room_ptr->project_state = ROOM_PROJECT_STATE_LOADED;
779  }
780
781  return ret;
782}
783
784#undef room_ptr
785
786#define context_ptr ((struct ladish_parse_context *)data)
787
788static void project_name_elstart_callback(void * data, const char * el, const char ** attr)
789{
790  const char * name;
791  const char * uuid_str;
792  uuid_t uuid;
793  size_t len;
794
795  if (strcmp(el, "project") == 0)
796  {
797    if (ladish_get_name_and_uuid_attributes("/project", attr, &name, &uuid_str, uuid))
798    {
799      len = strlen(name) + 1;
800      context_ptr->str = malloc(len);
801      if (context_ptr->str == NULL)
802      {
803        log_error("malloc() failed for project name with length %zu", len);
804      }
805
806      unescape(name, len, context_ptr->str);
807    }
808
809    XML_StopParser(context_ptr->parser, XML_TRUE);
810    return;
811  }
812}
813
814#undef context_ptr
815
816char * ladish_get_project_name(const char * project_dir)
817{
818  char * path;
819  struct stat st;
820  XML_Parser parser;
821  int bytes_read;
822  void * buffer;
823  int fd;
824  enum XML_Status xmls;
825  struct ladish_parse_context parse_context;
826
827  parse_context.str = NULL;
828
829  path = catdup(project_dir, LADISH_PROJECT_FILENAME);
830  if (path == NULL)
831  {
832    log_error("catdup() failed to compose xml file path");
833    goto exit;
834  }
835
836  if (stat(path, &st) != 0)
837  {
838    log_error("failed to stat '%s': %d (%s)", path, errno, strerror(errno));
839    goto free_path;
840  }
841
842  fd = open(path, O_RDONLY);
843  if (fd == -1)
844  {
845    log_error("failed to open '%s': %d (%s)", path, errno, strerror(errno));
846    goto free_path;
847  }
848
849  parser = XML_ParserCreate(NULL);
850  if (parser == NULL)
851  {
852    log_error("XML_ParserCreate() failed to create parser object.");
853    goto close;
854  }
855
856  /* we are expecting that conf file has small enough size to fit in memory */
857
858  buffer = XML_GetBuffer(parser, st.st_size);
859  if (buffer == NULL)
860  {
861    log_error("XML_GetBuffer() failed.");
862    goto free_parser;
863  }
864
865  bytes_read = read(fd, buffer, st.st_size);
866  if (bytes_read != st.st_size)
867  {
868    log_error("read() returned unexpected result.");
869    goto free_parser;
870  }
871
872  XML_SetElementHandler(parser, project_name_elstart_callback, NULL);
873  XML_SetUserData(parser, &parse_context);
874
875  parse_context.parser = parser;
876
877  xmls = XML_ParseBuffer(parser, bytes_read, XML_TRUE);
878  if (xmls == XML_STATUS_ERROR)
879  {
880    log_error("XML_ParseBuffer() failed.");
881  }
882
883free_parser:
884  XML_ParserFree(parser);
885close:
886  close(fd);
887free_path:
888  free(path);
889exit:
890  return parse_context.str;
891}
Note: See TracBrowser for help on using the browser.