tizen 2.3.1 release
[external/alsa-lib.git] / src / ucm / utils.c
1 /*
2  *  This library is free software; you can redistribute it and/or
3  *  modify it under the terms of the GNU Lesser General Public
4  *  License as published by the Free Software Foundation; either
5  *  version 2 of the License, or (at your option) any later version.
6  *
7  *  This library is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  Lesser General Public License for more details.
11  *
12  *  You should have received a copy of the GNU Lesser General Public
13  *  License along with this library; if not, write to the Free Software  
14  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15  *
16  *  Support for the verb/device/modifier core logic and API,
17  *  command line tool and file parser was kindly sponsored by
18  *  Texas Instruments Inc.
19  *  Support for multiple active modifiers and devices,
20  *  transition sequences, multiple client access and user defined use
21  *  cases was kindly sponsored by Wolfson Microelectronics PLC.
22  *
23  *  Copyright (C) 2008-2010 SlimLogic Ltd
24  *  Copyright (C) 2010 Wolfson Microelectronics PLC
25  *  Copyright (C) 2010 Texas Instruments Inc.
26  *  Copyright (C) 2010 Red Hat Inc.
27  *  Authors: Liam Girdwood <lrg@slimlogic.co.uk>
28  *               Stefan Schmidt <stefan@slimlogic.co.uk>
29  *               Justin Xu <justinx@slimlogic.co.uk>
30  *               Jaroslav Kysela <perex@perex.cz>
31  */
32
33 #include "ucm_local.h"
34
35 void uc_mgr_error(const char *fmt,...)
36 {
37         va_list va;
38         va_start(va, fmt);
39         fprintf(stderr, "ucm: ");
40         vfprintf(stderr, fmt, va);
41         va_end(va);
42 }
43
44 void uc_mgr_stdout(const char *fmt,...)
45 {
46         va_list va;
47         va_start(va, fmt);
48         vfprintf(stdout, fmt, va);
49         va_end(va);
50 }
51
52 int uc_mgr_config_load(const char *file, snd_config_t **cfg)
53 {
54         FILE *fp;
55         snd_input_t *in;
56         snd_config_t *top;
57         int err;
58
59         fp = fopen(file, "r");
60         if (fp == NULL) {
61                 err = -errno;
62                 goto __err;
63         }
64         err = snd_input_stdio_attach(&in, fp, 1);
65         if (err < 0) {
66               __err:
67                 uc_error("could not open configuration file %s", file);
68                 return err;
69         }
70         err = snd_config_top(&top);
71         if (err < 0)
72                 return err;
73         err = snd_config_load(top, in);
74         if (err < 0) {
75                 uc_error("could not load configuration file %s", file);
76                 snd_config_delete(top);
77                 return err;
78         }
79         err = snd_input_close(in);
80         if (err < 0) {
81                 snd_config_delete(top);
82                 return err;
83         }
84         *cfg = top;
85         return 0;
86 }
87
88 void uc_mgr_free_value(struct list_head *base)
89 {
90         struct list_head *pos, *npos;
91         struct ucm_value *val;
92         
93         list_for_each_safe(pos, npos, base) {
94                 val = list_entry(pos, struct ucm_value, list);
95                 free(val->name);
96                 free(val->data);
97                 list_del(&val->list);
98                 free(val);
99         }
100 }
101
102 void uc_mgr_free_dev_list(struct dev_list *dev_list)
103 {
104         struct list_head *pos, *npos;
105         struct dev_list_node *dlist;
106         
107         list_for_each_safe(pos, npos, &dev_list->list) {
108                 dlist = list_entry(pos, struct dev_list_node, list);
109                 free(dlist->name);
110                 list_del(&dlist->list);
111                 free(dlist);
112         }
113 }
114
115 void uc_mgr_free_sequence_element(struct sequence_element *seq)
116 {
117         if (seq == NULL)
118                 return;
119         switch (seq->type) {
120         case SEQUENCE_ELEMENT_TYPE_CSET:
121         case SEQUENCE_ELEMENT_TYPE_EXEC:
122                 free(seq->data.exec);
123                 break;
124         default:
125                 break;
126         }
127         free(seq);
128 }
129
130 void uc_mgr_free_sequence(struct list_head *base)
131 {
132         struct list_head *pos, *npos;
133         struct sequence_element *seq;
134         
135         list_for_each_safe(pos, npos, base) {
136                 seq = list_entry(pos, struct sequence_element, list);
137                 list_del(&seq->list);
138                 uc_mgr_free_sequence_element(seq);
139         }
140 }
141
142 void uc_mgr_free_transition_element(struct transition_sequence *tseq)
143 {
144         free(tseq->name);
145         uc_mgr_free_sequence(&tseq->transition_list);
146         free(tseq);
147 }
148
149 void uc_mgr_free_transition(struct list_head *base)
150 {
151         struct list_head *pos, *npos;
152         struct transition_sequence *tseq;
153         
154         list_for_each_safe(pos, npos, base) {
155                 tseq = list_entry(pos, struct transition_sequence, list);
156                 list_del(&tseq->list);
157                 uc_mgr_free_transition_element(tseq);
158         }
159 }
160
161 void uc_mgr_free_modifier(struct list_head *base)
162 {
163         struct list_head *pos, *npos;
164         struct use_case_modifier *mod;
165         
166         list_for_each_safe(pos, npos, base) {
167                 mod = list_entry(pos, struct use_case_modifier, list);
168                 free(mod->name);
169                 free(mod->comment);
170                 uc_mgr_free_sequence(&mod->enable_list);
171                 uc_mgr_free_sequence(&mod->disable_list);
172                 uc_mgr_free_transition(&mod->transition_list);
173                 uc_mgr_free_dev_list(&mod->dev_list);
174                 uc_mgr_free_value(&mod->value_list);
175                 list_del(&mod->list);
176                 free(mod);
177         }
178 }
179
180 void uc_mgr_free_device(struct list_head *base)
181 {
182         struct list_head *pos, *npos;
183         struct use_case_device *dev;
184         
185         list_for_each_safe(pos, npos, base) {
186                 dev = list_entry(pos, struct use_case_device, list);
187                 free(dev->name);
188                 free(dev->comment);
189                 uc_mgr_free_sequence(&dev->enable_list);
190                 uc_mgr_free_sequence(&dev->disable_list);
191                 uc_mgr_free_transition(&dev->transition_list);
192                 uc_mgr_free_dev_list(&dev->dev_list);
193                 uc_mgr_free_value(&dev->value_list);
194                 list_del(&dev->list);
195                 free(dev);
196         }
197 }
198
199 void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr)
200 {
201         struct list_head *pos, *npos;
202         struct use_case_verb *verb;
203
204         list_for_each_safe(pos, npos, &uc_mgr->verb_list) {
205                 verb = list_entry(pos, struct use_case_verb, list);
206                 free(verb->name);
207                 free(verb->comment);
208                 uc_mgr_free_sequence(&verb->enable_list);
209                 uc_mgr_free_sequence(&verb->disable_list);
210                 uc_mgr_free_transition(&verb->transition_list);
211                 uc_mgr_free_value(&verb->value_list);
212                 uc_mgr_free_device(&verb->device_list);
213                 uc_mgr_free_modifier(&verb->modifier_list);
214                 list_del(&verb->list);
215                 free(verb);
216         }
217         uc_mgr_free_sequence(&uc_mgr->default_list);
218         uc_mgr_free_value(&uc_mgr->value_list);
219         free(uc_mgr->comment);
220         uc_mgr->comment = NULL;
221         uc_mgr->active_verb = NULL;
222         INIT_LIST_HEAD(&uc_mgr->active_devices);
223         INIT_LIST_HEAD(&uc_mgr->active_modifiers);
224         if (uc_mgr->ctl != NULL) {
225                 snd_ctl_close(uc_mgr->ctl);
226                 uc_mgr->ctl = NULL;
227         }
228         free(uc_mgr->ctl_dev);
229         uc_mgr->ctl_dev = NULL;
230 }
231
232 void uc_mgr_free(snd_use_case_mgr_t *uc_mgr)
233 {
234         uc_mgr_free_verb(uc_mgr);
235         free(uc_mgr->card_name);
236         free(uc_mgr);
237 }