1 /*
2 * LASH
3 *
4 * Copyright (C) 2002 Robert Ham <rah@bash.sh>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <lash/internal_headers.h>
22
23 #include "config.h"
24 #include "client.h"
25 #include "jack_patch.h"
26 #include "alsa_patch.h"
27
28 client_t *
client_new(lash_connect_params_t * params)29 client_new(lash_connect_params_t * params)
30 {
31 client_t *client;
32
33 client = lash_malloc0(sizeof(client_t));
34
35 return client;
36 }
37
38 void
client_destroy(client_t * client)39 client_destroy(client_t * client)
40 {
41 client_set_name(client, NULL);
42 client_set_jack_client_name(client, NULL);
43 client_set_class(client, NULL);
44 client_set_requested_project(client, NULL);
45 client_set_working_dir(client, NULL);
46 if (client->store)
47 store_destroy(client->store);
48 free(client);
49 }
50
51 const char *
client_get_id_str(client_t * client)52 client_get_id_str(client_t * client)
53 {
54 static char id_str[37];
55
56 uuid_unparse(client->id, id_str);
57
58 return id_str;
59 }
60
61 const char *
client_get_identity(client_t * client)62 client_get_identity(client_t * client)
63 {
64 static char *identity = NULL;
65 static size_t identity_len = 0;
66
67 if (!identity) {
68 identity_len = 37;
69 identity = lash_malloc(identity_len);
70 }
71
72 if (!client->name) {
73 uuid_unparse(client->id, identity);
74 } else {
75 size_t name_len;
76
77 name_len = strlen(client->name) + 1;
78 if (name_len > identity_len) {
79 identity_len = name_len;
80 identity = lash_realloc(identity, identity_len);
81 }
82 strcpy(identity, client->name);
83 }
84
85 return identity;
86 }
87
88 void
client_set_name(client_t * client,const char * name)89 client_set_name(client_t * client, const char *name)
90 {
91 set_string_property(client->name, name);
92 }
93
94 void
client_set_conn_id(client_t * client,unsigned long id)95 client_set_conn_id(client_t * client, unsigned long id)
96 {
97 client->conn_id = id;
98 }
99
100 void
client_set_class(client_t * client,const char * class)101 client_set_class(client_t * client, const char *class)
102 {
103 set_string_property(client->class, class);
104 }
105
106 void
client_set_working_dir(client_t * client,const char * working_dir)107 client_set_working_dir(client_t * client, const char *working_dir)
108 {
109 set_string_property(client->working_dir, working_dir);
110 }
111
112 void
client_set_requested_project(client_t * client,const char * requested_project)113 client_set_requested_project(client_t * client, const char *requested_project)
114 {
115 set_string_property(client->requested_project, requested_project);
116 }
117
118 void
client_set_from_connect_params(client_t * client,lash_connect_params_t * params)119 client_set_from_connect_params(client_t * client,
120 lash_connect_params_t * params)
121 {
122 uuid_copy(client->id, params->id);
123 client->flags = params->flags;
124 client_set_class(client, params->class);
125 client_set_working_dir(client, params->working_dir);
126 client_set_requested_project(client, params->project);
127 client->argc = params->argc;
128 client->argv = params->argv;
129
130 params->argv = NULL;
131 }
132
133 void
client_set_id(client_t * client,uuid_t id)134 client_set_id(client_t * client, uuid_t id)
135 {
136 uuid_copy(client->id, id);
137 }
138
139 void
client_generate_id(client_t * client)140 client_generate_id(client_t * client)
141 {
142 uuid_generate(client->id);
143 }
144
145 int
client_store_open(client_t * client,const char * dir)146 client_store_open(client_t * client, const char *dir)
147 {
148 int err;
149
150 if (client->store) {
151 store_write(client->store);
152 store_destroy(client->store);
153 }
154
155 client->store = store_new();
156 store_set_dir(client->store, dir);
157
158 err = store_open(client->store);
159 if (err)
160 fprintf(stderr,
161 "%s: WARNING: the store for client '%s' (in directory '%s') could not be read. You should resolve this before saving the project. You may also wish to restart the client after it has been resolved, as it will not be given any data from the store.\n",
162 __FUNCTION__, client_get_id_str(client), client->store->dir);
163
164 return err;
165 }
166
167 lash_config_t *
client_store_get_config(client_t * client,const char * key)168 client_store_get_config(client_t * client, const char *key)
169 {
170 return store_get_config(client->store, key);
171 }
172
173 int
client_store_write(client_t * client)174 client_store_write(client_t * client)
175 {
176 return store_write(client->store);
177 }
178
179 int
client_store_close(client_t * client)180 client_store_close(client_t * client)
181 {
182 int err;
183
184 if (!client->store)
185 return 0;
186
187 err = store_write(client->store);
188
189 store_destroy(client->store);
190
191 client->store = NULL;
192
193 return err;
194 }
195
196 void
client_set_jack_client_name(client_t * client,const char * name)197 client_set_jack_client_name(client_t * client, const char *name)
198 {
199 set_string_property(client->jack_client_name, name);
200 }
201
202 void
client_set_alsa_client_id(client_t * client,unsigned char id)203 client_set_alsa_client_id(client_t * client, unsigned char id)
204 {
205 client->alsa_client_id = id;
206 }
207
208 void
client_parse_xml(client_t * client,xmlNodePtr parent)209 client_parse_xml(client_t * client, xmlNodePtr parent)
210 {
211 xmlNodePtr xmlnode, argnode;
212 xmlChar *content;
213 jack_patch_t *jack_patch;
214 #ifdef HAVE_ALSA
215 alsa_patch_t *alsa_patch;
216 #endif
217
218 LASH_PRINT_DEBUG("parsing client");
219
220 for (xmlnode = parent->children; xmlnode; xmlnode = xmlnode->next) {
221 if (strcmp(CAST_BAD(xmlnode->name), "class") == 0) {
222 content = xmlNodeGetContent(xmlnode);
223 client_set_class(client, CAST_BAD content);
224 xmlFree(content);
225 } else if (strcmp(CAST_BAD(xmlnode->name), "id") == 0) {
226 content = xmlNodeGetContent(xmlnode);
227 uuid_parse(CAST_BAD content, client->id);
228 xmlFree(content);
229 } else if (strcmp(CAST_BAD(xmlnode->name), "flags") == 0) {
230 content = xmlNodeGetContent(xmlnode);
231 client->flags = strtoul(CAST_BAD content, NULL, 10);
232 xmlFree(content);
233 } else if (strcmp(CAST_BAD(xmlnode->name), "working_directory") == 0) {
234 content = xmlNodeGetContent(xmlnode);
235 client_set_working_dir(client, CAST_BAD content);
236 xmlFree(content);
237 } else if (strcmp(CAST_BAD(xmlnode->name), "arg_set") == 0) {
238 for (argnode = xmlnode->children; argnode;
239 argnode = argnode->next)
240 if (strcmp(CAST_BAD argnode->name, "arg") == 0) {
241 client->argc++;
242
243 content = xmlNodeGetContent(argnode);
244
245 if (!client->argv)
246 client->argv = lash_malloc(sizeof(char *));
247 else
248 client->argv =
249 lash_realloc(client->argv,
250 sizeof(char *) * client->argc);
251
252 /* don't like this unsigned/signed char business, so I want a string from strdup */
253 client->argv[client->argc - 1] =
254 lash_strdup(CAST_BAD content);
255
256 xmlFree(content);
257 }
258 } else if (strcmp(CAST_BAD(xmlnode->name), "jack_patch_set") == 0) {
259 for (argnode = xmlnode->children; argnode;
260 argnode = argnode->next)
261 if (strcmp(CAST_BAD argnode->name, "jack_patch") == 0) {
262 jack_patch = jack_patch_new();
263 jack_patch_parse_xml(jack_patch, argnode);
264 client->jack_patches =
265 lash_list_append(client->jack_patches, jack_patch);
266 }
267 } else if (strcmp(CAST_BAD(xmlnode->name), "alsa_patch_set") == 0) {
268 #ifdef HAVE_ALSA
269 for (argnode = xmlnode->children; argnode; argnode = argnode->next) {
270 if (strcmp(CAST_BAD argnode->name, "alsa_patch") == 0) {
271 alsa_patch = alsa_patch_new();
272 alsa_patch_parse_xml(alsa_patch, argnode);
273 client->alsa_patches =
274 lash_list_append(client->alsa_patches, alsa_patch);
275 }
276 }
277 #else
278 LASH_PRINT_DEBUG("Warning: Session contains ALSA information, but LASH"
279 " is built without ALSA support.");
280 #endif
281 }
282 }
283
284 LASH_DEBUGARGS("parsed client of class %s", client->class);
285 }
286
287 /* EOF */
288