]> code.delx.au - pulseaudio/blob - polyp/autoload.c
d6207962d3a88cdd372a40aeefd4841de22d5b0a
[pulseaudio] / polyp / autoload.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio 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 General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "autoload.h"
31 #include "module.h"
32 #include "xmalloc.h"
33 #include "memchunk.h"
34 #include "sound-file.h"
35 #include "log.h"
36 #include "scache.h"
37 #include "subscribe.h"
38
39 static void entry_free(struct pa_autoload_entry *e) {
40 assert(e);
41 pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_REMOVE, PA_INVALID_INDEX);
42 pa_xfree(e->name);
43 pa_xfree(e->module);
44 pa_xfree(e->argument);
45 pa_xfree(e);
46 }
47
48 static void entry_remove_and_free(struct pa_autoload_entry *e) {
49 assert(e && e->core);
50
51 pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL);
52 pa_hashmap_remove(e->core->autoload_hashmap, e->name);
53 entry_free(e);
54 }
55
56 static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) {
57 struct pa_autoload_entry *e = NULL;
58 assert(c && name);
59
60 if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name)))
61 return NULL;
62
63 e = pa_xmalloc(sizeof(struct pa_autoload_entry));
64 e->core = c;
65 e->name = pa_xstrdup(name);
66 e->module = e->argument = NULL;
67 e->in_action = 0;
68
69 if (!c->autoload_hashmap)
70 c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
71 assert(c->autoload_hashmap);
72
73 pa_hashmap_put(c->autoload_hashmap, e->name, e);
74
75 if (!c->autoload_idxset)
76 c->autoload_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
77 pa_idxset_put(c->autoload_idxset, e, &e->index);
78
79 pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, e->index);
80
81 return e;
82 }
83
84 int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument, uint32_t *index) {
85 struct pa_autoload_entry *e = NULL;
86 assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));
87
88 if (!(e = entry_new(c, name)))
89 return -1;
90
91 e->module = pa_xstrdup(module);
92 e->argument = pa_xstrdup(argument);
93 e->type = type;
94
95 if (index)
96 *index = e->index;
97
98 return 0;
99 }
100
101 int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type) {
102 struct pa_autoload_entry *e;
103 assert(c && name && type);
104
105 if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type)
106 return -1;
107
108 entry_remove_and_free(e);
109 return 0;
110 }
111
112 int pa_autoload_remove_by_index(struct pa_core *c, uint32_t index) {
113 struct pa_autoload_entry *e;
114 assert(c && index != PA_IDXSET_INVALID);
115
116 if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, index)))
117 return -1;
118
119 entry_remove_and_free(e);
120 return 0;
121 }
122
123 void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type) {
124 struct pa_autoload_entry *e;
125 struct pa_module *m;
126 assert(c && name);
127
128 if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || (e->type != type))
129 return;
130
131 if (e->in_action)
132 return;
133
134 e->in_action = 1;
135
136 if (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) {
137 if ((m = pa_module_load(c, e->module, e->argument)))
138 m->auto_unload = 1;
139 }
140
141 e->in_action = 0;
142 }
143
144 static void free_func(void *p, void *userdata) {
145 struct pa_autoload_entry *e = p;
146 pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL);
147 entry_free(e);
148 }
149
150 void pa_autoload_free(struct pa_core *c) {
151 if (c->autoload_hashmap) {
152 pa_hashmap_free(c->autoload_hashmap, free_func, NULL);
153 c->autoload_hashmap = NULL;
154 }
155
156 if (c->autoload_idxset) {
157 pa_idxset_free(c->autoload_idxset, NULL, NULL);
158 c->autoload_idxset = NULL;
159 }
160 }
161
162 const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type) {
163 struct pa_autoload_entry *e;
164 assert(c && name);
165
166 if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type)
167 return NULL;
168
169 return e;
170 }
171
172 const struct pa_autoload_entry* pa_autoload_get_by_index(struct pa_core *c, uint32_t index) {
173 struct pa_autoload_entry *e;
174 assert(c && index != PA_IDXSET_INVALID);
175
176 if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, index)))
177 return NULL;
178
179 return e;
180 }