• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2006 Lennart Poettering
5 
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10 
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15 
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include <stdlib.h>
25 #include <string.h>
26 #include <string.h>
27 #include <stdio.h>
28 
29 #include <pulse/xmalloc.h>
30 
31 #include <pulsecore/source.h>
32 #include <pulsecore/sink.h>
33 #include <pulsecore/core-subscribe.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/macro.h>
36 
37 #include "namereg.h"
38 
39 struct namereg_entry {
40     pa_namereg_type_t type;
41     char *name;
42     void *data;
43 };
44 
is_valid_char(char c)45 static bool is_valid_char(char c) {
46     return
47         (c >= 'a' && c <= 'z') ||
48         (c >= 'A' && c <= 'Z') ||
49         (c >= '0' && c <= '9') ||
50         c == '.' ||
51         c == '-' ||
52         c == '_';
53 }
54 
pa_namereg_is_valid_name(const char * name)55 bool pa_namereg_is_valid_name(const char *name) {
56     const char *c;
57 
58     pa_assert(name);
59 
60     if (*name == 0)
61         return false;
62 
63     for (c = name; *c && (c-name < PA_NAME_MAX); c++)
64         if (!is_valid_char(*c))
65             return false;
66 
67     if (*c)
68         return false;
69 
70     return true;
71 }
72 
pa_namereg_is_valid_name_or_wildcard(const char * name,pa_namereg_type_t type)73 bool pa_namereg_is_valid_name_or_wildcard(const char *name, pa_namereg_type_t type) {
74 
75     pa_assert(name);
76 
77     if (pa_namereg_is_valid_name(name))
78         return true;
79 
80     if (type == PA_NAMEREG_SINK &&
81         pa_streq(name, "@DEFAULT_SINK@"))
82         return true;
83 
84     if (type == PA_NAMEREG_SOURCE &&
85         (pa_streq(name, "@DEFAULT_SOURCE@") ||
86          pa_streq(name, "@DEFAULT_MONITOR@")))
87         return true;
88 
89     return false;
90 }
91 
pa_namereg_make_valid_name(const char * name)92 char* pa_namereg_make_valid_name(const char *name) {
93     const char *a;
94     char *b, *n;
95 
96     if (*name == 0)
97         return NULL;
98 
99     n = pa_xnew(char, strlen(name)+1);
100 
101     for (a = name, b = n; *a && (a-name < PA_NAME_MAX); a++, b++)
102         *b = (char) (is_valid_char(*a) ? *a : '_');
103 
104     *b = 0;
105 
106     return n;
107 }
108 
pa_namereg_register(pa_core * c,const char * name,pa_namereg_type_t type,void * data,bool fail)109 const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, bool fail) {
110     struct namereg_entry *e;
111     char *n = NULL;
112 
113     pa_assert(c);
114     pa_assert(name);
115     pa_assert(data);
116 
117     if (!*name)
118         return NULL;
119 
120     if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE || type == PA_NAMEREG_CARD) &&
121         !pa_namereg_is_valid_name(name)) {
122 
123         if (fail)
124             return NULL;
125 
126         if (!(name = n = pa_namereg_make_valid_name(name)))
127             return NULL;
128     }
129 
130     if ((e = pa_hashmap_get(c->namereg, name)) && fail) {
131         pa_xfree(n);
132         return NULL;
133     }
134 
135     if (e) {
136         unsigned i;
137         size_t l = strlen(name);
138         char *k;
139 
140         if (l+4 > PA_NAME_MAX) {
141             pa_xfree(n);
142             return NULL;
143         }
144 
145         k = pa_xmalloc(l+4);
146 
147         for (i = 2; i <= 99; i++) {
148             pa_snprintf(k, l+4, "%s.%u", name, i);
149 
150             if (!(e = pa_hashmap_get(c->namereg, k)))
151                 break;
152         }
153 
154         if (e) {
155             pa_xfree(n);
156             pa_xfree(k);
157             return NULL;
158         }
159 
160         pa_xfree(n);
161         n = k;
162     }
163 
164     e = pa_xnew(struct namereg_entry, 1);
165     e->type = type;
166     e->name = n ? n : pa_xstrdup(name);
167     e->data = data;
168 
169     pa_assert_se(pa_hashmap_put(c->namereg, e->name, e) >= 0);
170 
171     return e->name;
172 }
173 
pa_namereg_unregister(pa_core * c,const char * name)174 void pa_namereg_unregister(pa_core *c, const char *name) {
175     struct namereg_entry *e;
176 
177     pa_assert(c);
178     pa_assert(name);
179 
180     pa_assert_se(e = pa_hashmap_remove(c->namereg, name));
181     pa_xfree(e->name);
182     pa_xfree(e);
183 }
184 
pa_namereg_get(pa_core * c,const char * name,pa_namereg_type_t type)185 void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type) {
186     struct namereg_entry *e;
187     uint32_t idx;
188     pa_assert(c);
189 
190     if (type == PA_NAMEREG_SOURCE && (!name || pa_streq(name, "@DEFAULT_SOURCE@"))) {
191         return c->default_source;
192 
193     } else if (type == PA_NAMEREG_SINK && (!name || pa_streq(name, "@DEFAULT_SINK@"))) {
194         return c->default_sink;
195 
196     } else if (type == PA_NAMEREG_SOURCE && name && pa_streq(name, "@DEFAULT_MONITOR@")) {
197         if (c->default_sink)
198             return c->default_sink->monitor_source;
199         else
200             return NULL;
201     }
202 
203     if (!name)
204         return NULL;
205 
206     if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE || type == PA_NAMEREG_CARD) &&
207         !pa_namereg_is_valid_name(name))
208         return NULL;
209 
210     if ((e = pa_hashmap_get(c->namereg, name)))
211         if (e->type == type)
212             return e->data;
213 
214     if (pa_atou(name, &idx) < 0)
215         return NULL;
216 
217     if (type == PA_NAMEREG_SINK)
218         return pa_idxset_get_by_index(c->sinks, idx);
219     else if (type == PA_NAMEREG_SOURCE)
220         return pa_idxset_get_by_index(c->sources, idx);
221     else if (type == PA_NAMEREG_SAMPLE && c->scache)
222         return pa_idxset_get_by_index(c->scache, idx);
223     else if (type == PA_NAMEREG_CARD)
224         return pa_idxset_get_by_index(c->cards, idx);
225 
226     return NULL;
227 }
228