Mercurial > mplayer.hg
annotate sub/ass_mp.c @ 33040:a6be6a134ac0
Fix XVMC decoding (avcodec_open would fail if thread_count is set)
and simplify code a bit in the process.
author | reimar |
---|---|
date | Sun, 27 Mar 2011 13:09:27 +0000 |
parents | fbe5c829c69b |
children | 45e9c10b2f5b |
rev | line source |
---|---|
32209 | 1 /* |
2 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> | |
3 * | |
32210
f6ff1c427ff3
Adapt license header from libass to MPlayer boilerplate.
diego
parents:
32209
diff
changeset
|
4 * This file is part of MPlayer. |
32209 | 5 * |
32210
f6ff1c427ff3
Adapt license header from libass to MPlayer boilerplate.
diego
parents:
32209
diff
changeset
|
6 * MPlayer is free software; you can redistribute it and/or modify |
32209 | 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 * | |
32210
f6ff1c427ff3
Adapt license header from libass to MPlayer boilerplate.
diego
parents:
32209
diff
changeset
|
11 * MPlayer is distributed in the hope that it will be useful, |
32209 | 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 along | |
32210
f6ff1c427ff3
Adapt license header from libass to MPlayer boilerplate.
diego
parents:
32209
diff
changeset
|
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
32209 | 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 */ | |
20 | |
21 #include <inttypes.h> | |
22 #include <string.h> | |
23 #include <stdlib.h> | |
24 | |
25 #include "mp_msg.h" | |
26 #include "mpcommon.h" | |
27 #include "path.h" | |
32464
22888a8cb312
Do not use a path for including files in the same directory.
reimar
parents:
32461
diff
changeset
|
28 #include "subreader.h" |
32209 | 29 |
32464
22888a8cb312
Do not use a path for including files in the same directory.
reimar
parents:
32461
diff
changeset
|
30 #include "ass_mp.h" |
22888a8cb312
Do not use a path for including files in the same directory.
reimar
parents:
32461
diff
changeset
|
31 #include "eosd.h" |
32391
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
32 #include "mpcommon.h" |
32467 | 33 #include "sub.h" |
32209 | 34 #include "help_mp.h" |
32466
9e627a1793b1
Move font_load.[ch], font_load_ft.c and osd_font.h from libvo to sub.
cigaes
parents:
32464
diff
changeset
|
35 #include "font_load.h" |
32209 | 36 #include "stream/stream.h" |
37 | |
38 #ifdef CONFIG_FONTCONFIG | |
39 #include <fontconfig/fontconfig.h> | |
40 #endif | |
41 | |
42 // libass-related command line options | |
43 ASS_Library* ass_library; | |
44 int ass_enabled = 0; | |
45 float ass_font_scale = 1.; | |
46 float ass_line_spacing = 0.; | |
47 int ass_top_margin = 0; | |
48 int ass_bottom_margin = 0; | |
49 int extract_embedded_fonts = 1; | |
50 char **ass_force_style_list = NULL; | |
51 int ass_use_margins = 0; | |
52 char* ass_color = NULL; | |
53 char* ass_border_color = NULL; | |
54 char* ass_styles_file = NULL; | |
55 int ass_hinting = ASS_HINTING_NATIVE + 4; // native hinting for unscaled osd | |
56 | |
57 ASS_Track* ass_default_track(ASS_Library* library) { | |
58 ASS_Track* track = ass_new_track(library); | |
59 | |
60 track->track_type = TRACK_TYPE_ASS; | |
61 track->Timer = 100.; | |
62 track->PlayResY = 288; | |
63 track->WrapStyle = 0; | |
64 | |
65 if (ass_styles_file) | |
66 ass_read_styles(track, ass_styles_file, sub_cp); | |
67 | |
68 if (track->n_styles == 0) { | |
69 ASS_Style* style; | |
70 int sid; | |
71 double fs; | |
72 uint32_t c1, c2; | |
73 | |
74 sid = ass_alloc_style(track); | |
75 style = track->styles + sid; | |
76 style->Name = strdup("Default"); | |
77 style->FontName = (font_fontconfig >= 0 && sub_font_name) ? strdup(sub_font_name) : (font_fontconfig >= 0 && font_name) ? strdup(font_name) : strdup("Sans"); | |
78 style->treat_fontname_as_pattern = 1; | |
79 | |
80 fs = track->PlayResY * text_font_scale_factor / 100.; | |
81 // approximate autoscale coefficients | |
82 if (subtitle_autoscale == 2) | |
83 fs *= 1.3; | |
84 else if (subtitle_autoscale == 3) | |
85 fs *= 1.4; | |
86 style->FontSize = fs; | |
87 | |
88 if (ass_color) c1 = strtoll(ass_color, NULL, 16); | |
89 else c1 = 0xFFFF0000; | |
90 if (ass_border_color) c2 = strtoll(ass_border_color, NULL, 16); | |
91 else c2 = 0x00000000; | |
92 | |
93 style->PrimaryColour = c1; | |
94 style->SecondaryColour = c1; | |
95 style->OutlineColour = c2; | |
96 style->BackColour = 0x00000000; | |
97 style->BorderStyle = 1; | |
98 style->Alignment = 2; | |
99 style->Outline = 2; | |
100 style->MarginL = 10; | |
101 style->MarginR = 10; | |
102 style->MarginV = 5; | |
103 style->ScaleX = 1.; | |
104 style->ScaleY = 1.; | |
105 } | |
106 | |
107 ass_process_force_style(track); | |
108 return track; | |
109 } | |
110 | |
111 static int check_duplicate_plaintext_event(ASS_Track* track) | |
112 { | |
113 int i; | |
114 ASS_Event* evt = track->events + track->n_events - 1; | |
115 | |
116 for (i = 0; i<track->n_events - 1; ++i) // ignoring last event, it is the one we are comparing with | |
117 if (track->events[i].Start == evt->Start && | |
118 track->events[i].Duration == evt->Duration && | |
119 strcmp(track->events[i].Text, evt->Text) == 0) | |
120 return 1; | |
121 return 0; | |
122 } | |
123 | |
124 /** | |
125 * \brief Convert subtitle to ASS_Event for the given track | |
126 * \param track ASS_Track | |
127 * \param sub subtitle to convert | |
128 * \return event id | |
129 * note: assumes that subtitle is _not_ fps-based; caller must manually correct | |
130 * Start and Duration in other case. | |
131 **/ | |
132 int ass_process_subtitle(ASS_Track* track, subtitle* sub) | |
133 { | |
134 int eid; | |
135 ASS_Event* event; | |
136 int len = 0, j; | |
137 char* p; | |
138 char* end; | |
139 | |
140 eid = ass_alloc_event(track); | |
141 event = track->events + eid; | |
142 | |
143 event->Start = sub->start * 10; | |
144 event->Duration = (sub->end - sub->start) * 10; | |
145 event->Style = 0; | |
146 | |
147 for (j = 0; j < sub->lines; ++j) | |
148 len += sub->text[j] ? strlen(sub->text[j]) : 0; | |
149 | |
150 len += 2 * sub->lines; // '\N', including the one after the last line | |
151 len += 6; // {\anX} | |
152 len += 1; // '\0' | |
153 | |
154 event->Text = malloc(len); | |
155 end = event->Text + len; | |
156 p = event->Text; | |
157 | |
158 if (sub->alignment) | |
159 p += snprintf(p, end - p, "{\\an%d}", sub->alignment); | |
160 | |
161 for (j = 0; j < sub->lines; ++j) | |
162 p += snprintf(p, end - p, "%s\\N", sub->text[j]); | |
163 | |
164 if (sub->lines > 0) p-=2; // remove last "\N" | |
165 *p = 0; | |
166 | |
167 if (check_duplicate_plaintext_event(track)) { | |
168 ass_free_event(track, eid); | |
169 track->n_events--; | |
170 return -1; | |
171 } | |
172 | |
173 mp_msg(MSGT_ASS, MSGL_V, "plaintext event at %" PRId64 ", +%" PRId64 ": %s \n", | |
174 (int64_t)event->Start, (int64_t)event->Duration, event->Text); | |
175 | |
176 return eid; | |
177 } | |
178 | |
179 | |
180 /** | |
181 * \brief Convert subdata to ASS_Track | |
182 * \param subdata subtitles struct from subreader | |
183 * \param fps video framerate | |
184 * \return newly allocated ASS_Track, filled with subtitles from subdata | |
185 */ | |
186 ASS_Track* ass_read_subdata(ASS_Library* library, sub_data* subdata, double fps) { | |
187 ASS_Track* track; | |
188 int i; | |
189 | |
190 track = ass_default_track(library); | |
191 track->name = subdata->filename ? strdup(subdata->filename) : 0; | |
192 | |
193 for (i = 0; i < subdata->sub_num; ++i) { | |
194 int eid = ass_process_subtitle(track, subdata->subtitles + i); | |
195 if (eid < 0) | |
196 continue; | |
197 if (!subdata->sub_uses_time) { | |
198 track->events[eid].Start *= 100. / fps; | |
199 track->events[eid].Duration *= 100. / fps; | |
200 } | |
201 } | |
202 return track; | |
203 } | |
204 | |
205 ASS_Track* ass_read_stream(ASS_Library* library, const char *fname, char *charset) { | |
206 char *buf = NULL; | |
207 ASS_Track *track; | |
208 size_t sz = 0; | |
209 size_t buf_alloc = 0; | |
210 stream_t *fd; | |
211 | |
212 fd = open_stream(fname, NULL, NULL); | |
213 if (!fd) { | |
214 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FopenFailed, fname); | |
215 return NULL; | |
216 } | |
217 if (fd->end_pos > STREAM_BUFFER_SIZE) | |
218 /* read entire file if size is known */ | |
219 buf_alloc = fd->end_pos; | |
220 for (;;) { | |
221 int i; | |
222 if (buf_alloc >= 100*1024*1024) { | |
223 mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_RefusingToLoadSubtitlesLargerThan100M, fname); | |
224 sz = 0; | |
225 break; | |
226 } | |
227 if (buf_alloc < sz + STREAM_BUFFER_SIZE) | |
228 buf_alloc += STREAM_BUFFER_SIZE; | |
229 buf = realloc(buf, buf_alloc + 1); | |
230 i = stream_read(fd, buf + sz, buf_alloc - sz); | |
231 if (i <= 0) break; | |
232 sz += i; | |
233 } | |
234 free_stream(fd); | |
235 if (!sz) { | |
236 free(buf); | |
237 return NULL; | |
238 } | |
239 buf[sz] = 0; | |
240 buf = realloc(buf, sz + 1); | |
241 track = ass_read_memory(library, buf, sz, charset); | |
242 if (track) { | |
243 free(track->name); | |
244 track->name = strdup(fname); | |
245 } | |
246 free(buf); | |
247 return track; | |
248 } | |
249 | |
250 void ass_configure(ASS_Renderer* priv, int w, int h, int unscaled) { | |
251 int hinting; | |
252 ass_set_frame_size(priv, w, h); | |
253 ass_set_margins(priv, ass_top_margin, ass_bottom_margin, 0, 0); | |
254 ass_set_use_margins(priv, ass_use_margins); | |
255 ass_set_font_scale(priv, ass_font_scale); | |
256 if (!unscaled && (ass_hinting & 4)) | |
257 hinting = 0; | |
258 else | |
259 hinting = ass_hinting & 3; | |
260 ass_set_hinting(priv, hinting); | |
261 ass_set_line_spacing(priv, ass_line_spacing); | |
262 } | |
263 | |
264 void ass_configure_fonts(ASS_Renderer* priv) { | |
265 char *dir, *path, *family; | |
266 dir = get_path("fonts"); | |
267 if (font_fontconfig < 0 && sub_font_name) path = strdup(sub_font_name); | |
268 else if (font_fontconfig < 0 && font_name) path = strdup(font_name); | |
269 else path = get_path("subfont.ttf"); | |
270 if (font_fontconfig >= 0 && sub_font_name) family = strdup(sub_font_name); | |
271 else if (font_fontconfig >= 0 && font_name) family = strdup(font_name); | |
272 else family = 0; | |
273 | |
274 ass_set_fonts(priv, path, family, font_fontconfig, NULL, 1); | |
275 | |
276 free(dir); | |
277 free(path); | |
278 free(family); | |
279 } | |
280 | |
281 static void message_callback(int level, const char *format, va_list va, void *ctx) | |
282 { | |
283 int n; | |
284 char *str; | |
285 va_list dst; | |
286 | |
287 va_copy(dst, va); | |
288 n = vsnprintf(NULL, 0, format, va); | |
289 if (n > 0 && (str = malloc(n + 1))) { | |
290 vsnprintf(str, n + 1, format, dst); | |
291 mp_msg(MSGT_ASS, level, "[ass] %s\n", str); | |
292 free(str); | |
293 } | |
294 } | |
295 | |
296 ASS_Library* ass_init(void) { | |
297 ASS_Library* priv; | |
298 char* path = get_path("fonts"); | |
299 priv = ass_library_init(); | |
300 ass_set_message_cb(priv, message_callback, NULL); | |
301 ass_set_fonts_dir(priv, path); | |
302 ass_set_extract_fonts(priv, extract_embedded_fonts); | |
303 ass_set_style_overrides(priv, ass_force_style_list); | |
304 free(path); | |
305 return priv; | |
306 } | |
307 | |
308 int ass_force_reload = 0; // flag set if global ass-related settings were changed | |
309 | |
310 ASS_Image* ass_mp_render_frame(ASS_Renderer *priv, ASS_Track* track, long long now, int* detect_change) { | |
311 if (ass_force_reload) { | |
312 ass_set_margins(priv, ass_top_margin, ass_bottom_margin, 0, 0); | |
313 ass_set_use_margins(priv, ass_use_margins); | |
314 ass_set_font_scale(priv, ass_font_scale); | |
315 ass_force_reload = 0; | |
316 } | |
317 return ass_render_frame(priv, track, now, detect_change); | |
318 } | |
32391
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
319 |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
320 /* EOSD source for ASS subtitles. */ |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
321 |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
322 static ASS_Renderer *ass_renderer; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
323 static int prev_visibility; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
324 |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
325 static void eosd_ass_update(struct mp_eosd_source *src, const struct mp_eosd_settings *res, double ts) |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
326 { |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
327 long long ts_ms = (ts + sub_delay) * 1000 + .5; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
328 ASS_Image *aimg; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
329 struct mp_eosd_image *img; |
32426
fbee56276c87
Add a flag "initialized" to the mp_eosd_source structure.
cigaes
parents:
32397
diff
changeset
|
330 if (res->changed || !src->initialized) { |
32391
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
331 double dar = (double) (res->w - res->ml - res->mr) / (res->h - res->mt - res->mb); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
332 ass_configure(ass_renderer, res->w, res->h, res->unscaled); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
333 ass_set_margins(ass_renderer, res->mt, res->mb, res->ml, res->mr); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
334 ass_set_aspect_ratio(ass_renderer, dar, (double)res->srcw / res->srch); |
32426
fbee56276c87
Add a flag "initialized" to the mp_eosd_source structure.
cigaes
parents:
32397
diff
changeset
|
335 src->initialized = 1; |
32391
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
336 } |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
337 aimg = sub_visibility && ass_track && ts != MP_NOPTS_VALUE ? |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
338 ass_mp_render_frame(ass_renderer, ass_track, ts_ms, &src->changed) : |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
339 NULL; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
340 if (!aimg != !src->images) |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
341 src->changed = 2; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
342 if (src->changed) { |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
343 eosd_image_remove_all(src); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
344 while (aimg) { |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
345 img = eosd_image_alloc(); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
346 img->w = aimg->w; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
347 img->h = aimg->h; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
348 img->bitmap = aimg->bitmap; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
349 img->stride = aimg->stride; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
350 img->color = aimg->color; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
351 img->dst_x = aimg->dst_x; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
352 img->dst_y = aimg->dst_y; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
353 eosd_image_append(src, img); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
354 aimg = aimg->next; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
355 } |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
356 } |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
357 prev_visibility = sub_visibility; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
358 } |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
359 |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
360 static void eosd_ass_uninit(struct mp_eosd_source *src) |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
361 { |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
362 eosd_image_remove_all(src); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
363 ass_renderer_done(ass_renderer); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
364 } |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
365 |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
366 static struct mp_eosd_source eosd_ass = { |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
367 .uninit = eosd_ass_uninit, |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
368 .update = eosd_ass_update, |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
369 .z_index = 10, |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
370 }; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
371 |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
372 void eosd_ass_init(ASS_Library *ass_library) |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
373 { |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
374 ass_renderer = ass_renderer_init(ass_library); |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
375 if (!ass_renderer) |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
376 return; |
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
377 ass_configure_fonts(ass_renderer); |
32397
b3110e526e19
EOSD: add a function to test if a source has already been registered.
cigaes
parents:
32391
diff
changeset
|
378 if (!eosd_registered(&eosd_ass)) |
b3110e526e19
EOSD: add a function to test if a source has already been registered.
cigaes
parents:
32391
diff
changeset
|
379 eosd_register(&eosd_ass); |
32391
b4c3659d16b1
Use a dynamic list for the sources of EOSD elements.
cigaes
parents:
32210
diff
changeset
|
380 } |