Mercurial > mplayer.hg
annotate sub/ass_mp.c @ 34092:dbf5042ab255
Don't use the Windows style path separator character in Win32 GUI.
We use the Unix style path separator character throughout everywhere
else, so use it here as well.
Although Cygwin and MinGW tolerate a mixed Unix and Windows style, it
beautifies the messages.
author | ib |
---|---|
date | Thu, 06 Oct 2011 12:09:05 +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 } |