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