]> git.sesse.net Git - vlc/blob - modules/access/imem.c
imem: remove tab in sourcecode
[vlc] / modules / access / imem.c
1 /*****************************************************************************
2  * imem.c : Memory input for VLC
3  *****************************************************************************
4  * Copyright (C) 2009-2010 Laurent Aimar
5  * $Id$
6  *
7  * Author: Laurent Aimar <fenrir _AT_ videolan _DOT org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31 #include <limits.h>
32 #include <math.h>
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_access.h>
37 #include <vlc_demux.h>
38 #include <vlc_charset.h>
39
40 /*****************************************************************************
41  * Module descriptior
42  *****************************************************************************/
43 static int  OpenAccess (vlc_object_t *);
44 static void CloseAccess(vlc_object_t *);
45
46 static int  OpenDemux (vlc_object_t *);
47 static void CloseDemux(vlc_object_t *);
48
49 #define CACHING_TEXT N_("Caching value in ms")
50 #define CACHING_LONGTEXT N_(\
51     "Caching value for imem streams. This " \
52     "value should be set in milliseconds.")
53
54 #define ID_TEXT N_("ID")
55 #define ID_LONGTEXT N_(\
56     "Set the ID of the elementary stream")
57
58 #define GROUP_TEXT N_("Group")
59 #define GROUP_LONGTEXT N_(\
60     "Set the group of the elementary stream")
61
62 #define CAT_TEXT N_("Category")
63 #define CAT_LONGTEXT N_(\
64     "Set the category of the elementary stream")
65 static const int cat_values[] = {
66     0, 1, 2, 3, 4,
67 };
68 static const char *cat_texts[] = {
69     N_("Unknown"), N_("Audio"), N_("Video"), N_("Subtitle"), N_("Data")
70 };
71
72 #define CODEC_TEXT N_("Codec")
73 #define CODEC_LONGTEXT N_(\
74     "Set the codec of the elementary stream")
75
76 #define LANGUAGE_TEXT N_("Language")
77 #define LANGUAGE_LONGTEXT N_(\
78     "Language of the elementary stream as described by ISO639")
79
80 #define SAMPLERATE_TEXT N_("Sample rate")
81 #define SAMPLERATE_LONGTEXT N_(\
82     "Sample rate of an audio elementary stream")
83
84 #define CHANNELS_TEXT N_("Channels count")
85 #define CHANNELS_LONGTEXT N_(\
86     "Channels count of an audio elementary stream")
87
88 #define WIDTH_TEXT N_("Width")
89 #define WIDTH_LONGTEXT N_("Width of video or subtitle elementary streams")
90
91 #define HEIGHT_TEXT N_("Height")
92 #define HEIGHT_LONGTEXT N_("Height of video or subtitle elementary streams")
93
94 #define DAR_TEXT N_("Display aspect ratio")
95 #define DAR_LONGTEXT N_(\
96     "Display aspect ratio of a video elementary stream")
97
98 #define FPS_TEXT N_("Frame rate")
99 #define FPS_LONGTEXT N_(\
100     "Frame rate of a video elementary stream")
101
102 #define COOKIE_TEXT N_("Callback cookie string")
103 #define COOKIE_LONGTEXT N_(\
104     "Text identifier for the callback functions")
105
106 #define DATA_TEXT N_("Callback data")
107 #define DATA_LONGTEXT N_(\
108     "Data for the get and release functions")
109
110 #define GET_TEXT N_("Get function")
111 #define GET_LONGTEXT N_(\
112     "Address of the get callback function")
113
114 #define RELEASE_TEXT N_("Release function")
115 #define RELEASE_LONGTEXT N_(\
116     "Address of the release callback function")
117
118 vlc_module_begin()
119     set_shortname(N_("Memory input"))
120     set_description(N_("Memory input"))
121     set_category(CAT_INPUT)
122     set_subcategory(SUBCAT_INPUT_ACCESS)
123
124     add_integer("imem-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, true)
125         change_private()
126     add_string ("imem-get", "0", NULL, GET_TEXT, GET_LONGTEXT, true)
127         change_volatile()
128     add_string ("imem-release", "0", NULL, RELEASE_TEXT, RELEASE_LONGTEXT, true)
129         change_volatile()
130     add_string ("imem-cookie", NULL, NULL, COOKIE_TEXT, COOKIE_LONGTEXT, true)
131         change_volatile()
132         change_safe()
133     add_string ("imem-data", "0", NULL, DATA_TEXT, DATA_LONGTEXT, true)
134         change_volatile()
135
136     add_integer("imem-id", -1, NULL, ID_TEXT, ID_LONGTEXT, true)
137         change_private()
138         change_safe()
139     add_integer("imem-group", 0, NULL, GROUP_TEXT, GROUP_LONGTEXT, true)
140         change_private()
141         change_safe()
142     add_integer("imem-cat", 0, NULL, CAT_TEXT, CAT_LONGTEXT, true)
143         change_integer_list(cat_values, cat_texts, NULL)
144         change_private()
145         change_safe()
146     add_string ("imem-codec", NULL, NULL, CODEC_TEXT, CODEC_LONGTEXT, true)
147         change_private()
148         change_safe()
149     add_string( "imem-language", NULL, NULL, LANGUAGE_TEXT, LANGUAGE_LONGTEXT, false)
150         change_private()
151         change_safe()
152
153     add_integer("imem-samplerate", 0, NULL, SAMPLERATE_TEXT, SAMPLERATE_LONGTEXT, true)
154         change_private()
155         change_safe()
156     add_integer("imem-channels", 0, NULL, CHANNELS_TEXT, CHANNELS_LONGTEXT, true)
157         change_private()
158         change_safe()
159
160     add_integer("imem-width", 0, NULL, WIDTH_TEXT, WIDTH_LONGTEXT, true)
161         change_private()
162         change_safe()
163     add_integer("imem-height", 0, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT, true)
164         change_private()
165         change_safe()
166     add_string ("imem-dar", NULL, NULL, DAR_TEXT, DAR_LONGTEXT, true)
167         change_private()
168         change_safe()
169     add_string ("imem-fps", NULL, NULL, FPS_TEXT, FPS_LONGTEXT, true)
170         change_private()
171         change_safe()
172
173     add_shortcut("imem")
174     set_capability("access_demux", 0)
175     set_callbacks(OpenDemux, CloseDemux)
176
177     add_submodule()
178         add_shortcut("imem")
179         set_capability("access", 0)
180         set_callbacks(OpenAccess, CloseAccess)
181 vlc_module_end()
182
183 /*****************************************************************************
184  * Exported API
185  *****************************************************************************/
186
187 /* The clock origin for the DTS and PTS is assumed to be 0.
188  * A negative value means unknown.
189  *
190  * TODO define flags
191  */
192 typedef int  (*imem_get_t)(void *data, const char *cookie,
193                            int64_t *dts, int64_t *pts, unsigned *flags,
194                            size_t *, void **);
195 typedef void (*imem_release_t)(void *data, const char *cookie, size_t, void *);
196
197 /*****************************************************************************
198  * Local prototypes
199  *****************************************************************************/
200
201 /* */
202 static block_t *Block(access_t *);
203 static int ControlAccess(access_t *, int, va_list);
204
205 static int Demux(demux_t *);
206 static int ControlDemux(demux_t *, int, va_list);
207
208 /* */
209 typedef struct {
210     struct {
211         imem_get_t      get;
212         imem_release_t  release;
213         void           *data;
214         char           *cookie;
215     } source;
216
217     es_out_id_t  *es;
218
219     mtime_t      pts_delay;
220
221     mtime_t      dts;
222
223     mtime_t      deadline;
224 } imem_sys_t;
225
226 static void ParseMRL(vlc_object_t *, const char *);
227 #define var_InheritRational(a,b,c,d) var_InheritRational(VLC_OBJECT(a),b,c,d)
228 static int (var_InheritRational)(vlc_object_t *,
229                                  unsigned *num, unsigned *den,
230                                  const char *var);
231
232 /**
233  * It closes the common part of the access and access_demux
234  */
235 static void CloseCommon(imem_sys_t *sys)
236 {
237     free(sys->source.cookie);
238     free(sys);
239 }
240
241 /**
242  * It initializes the common part for imem access/access_demux.
243  */
244 static int OpenCommon(vlc_object_t *object, imem_sys_t **sys_ptr, const char *psz_path)
245 {
246     char *tmp;
247
248     /* */
249     imem_sys_t *sys = calloc(1, sizeof(*sys));
250     if (!sys)
251         return VLC_ENOMEM;
252
253     /* Read the user functions */
254     tmp = var_InheritString(object, "imem-get");
255     if (tmp)
256         sys->source.get = (imem_get_t)(intptr_t)strtoll(tmp, NULL, 0);
257     free(tmp);
258
259     tmp = var_InheritString(object, "imem-release");
260     if (tmp)
261         sys->source.release = (imem_release_t)(intptr_t)strtoll(tmp, NULL, 0);
262     free(tmp);
263
264     if (!sys->source.get || !sys->source.release) {
265         msg_Err(object, "Invalid get/release function pointers");
266         free(sys);
267         return VLC_EGENERIC;
268     }
269
270     tmp = var_InheritString(object, "imem-data");
271     if (tmp)
272         sys->source.data = (void *)(uintptr_t)strtoull(tmp, NULL, 0);
273     free(tmp);
274
275     /* Now we can parse the MRL (get/release must not be parsed to avoid
276      * security risks) */
277     if (*psz_path)
278         ParseMRL(object, psz_path);
279
280     sys->source.cookie = var_InheritString(object, "imem-cookie");
281
282     msg_Dbg(object, "Using get(%p), release(%p), data(%p), cookie(%s)",
283             sys->source.get, sys->source.release, sys->source.data,
284             sys->source.cookie ? sys->source.cookie : "(null)");
285
286     /* */
287     sys->pts_delay = var_InheritInteger(object, "imem-caching") * INT64_C(1000);
288     sys->dts       = 0;
289     sys->deadline  = VLC_TS_INVALID;
290
291     *sys_ptr = sys;
292     return VLC_SUCCESS;
293 }
294
295 /**
296  * It opens an imem access.
297  */
298 static int OpenAccess(vlc_object_t *object)
299 {
300     access_t   *access = (access_t *)object;
301     imem_sys_t *sys;
302
303     if (OpenCommon(object, &sys, access->psz_path))
304         return VLC_EGENERIC;
305
306     if (var_InheritInteger(object, "imem-cat") != 4) {
307         CloseCommon(sys);
308         return VLC_EGENERIC;
309     }
310
311     /* */
312     access_InitFields(access);
313     access->pf_control = ControlAccess;
314     access->pf_read    = NULL;
315     access->pf_block   = Block;
316     access->pf_seek    = NULL;
317     access->p_sys      = (access_sys_t*)sys;
318
319     return VLC_SUCCESS;
320 }
321
322 /**
323  * It closes an imem access
324  */
325 static void CloseAccess(vlc_object_t *object)
326 {
327     access_t *access = (access_t *)object;
328
329     CloseCommon((imem_sys_t*)access->p_sys);
330 }
331
332 /**
333  * It controls an imem access
334  */
335 static int ControlAccess(access_t *access, int i_query, va_list args)
336 {
337     imem_sys_t *sys = (imem_sys_t*)access->p_sys;
338
339     switch (i_query)
340     {
341     case ACCESS_CAN_SEEK:
342     case ACCESS_CAN_FASTSEEK: {
343         bool *b = va_arg( args, bool* );
344         *b = false;
345         return VLC_SUCCESS;
346     }
347     case ACCESS_CAN_PAUSE:
348     case ACCESS_CAN_CONTROL_PACE: {
349         bool *b = va_arg( args, bool* );
350         *b = true;
351         return VLC_SUCCESS;
352     }
353     case ACCESS_GET_PTS_DELAY: {
354         int64_t *delay = va_arg(args, int64_t *);
355         *delay = sys->pts_delay;
356         return VLC_SUCCESS;
357     }
358     case ACCESS_SET_PAUSE_STATE:
359         return VLC_SUCCESS;
360
361     case ACCESS_GET_TITLE_INFO:
362     case ACCESS_SET_TITLE:
363     case ACCESS_SET_SEEKPOINT:
364     case ACCESS_SET_PRIVATE_ID_STATE:
365     case ACCESS_GET_META:
366     case ACCESS_GET_PRIVATE_ID_STATE:
367     case ACCESS_GET_CONTENT_TYPE:
368     default:
369         return VLC_EGENERIC;
370     }
371 }
372
373 /**
374  * It retreives data using the get() callback, copies them,
375  * and then release them using the release() callback.
376  */
377 static block_t *Block(access_t *access)
378 {
379     imem_sys_t *sys = (imem_sys_t*)access->p_sys;
380
381     unsigned flags;
382     size_t buffer_size;
383     void   *buffer;
384
385     if (sys->source.get(sys->source.data, sys->source.cookie,
386                         NULL, NULL, &flags, &buffer_size, &buffer)) {
387         access->info.b_eof = true;
388         return NULL;
389     }
390
391     block_t *block = NULL;
392     if (buffer_size > 0) {
393         block = block_New(access, buffer_size);
394         if (block)
395             memcpy(block->p_buffer, buffer, buffer_size);
396     }
397
398     sys->source.release(sys->source.data, sys->source.cookie,
399                         buffer_size, buffer);
400     return block;
401 }
402
403 /**
404  * It opens an imem access_demux.
405  */
406 static int OpenDemux(vlc_object_t *object)
407 {
408     demux_t    *demux = (demux_t *)object;
409     imem_sys_t *sys;
410
411     if (OpenCommon(object, &sys, demux->psz_path))
412         return VLC_EGENERIC;
413
414     /* ES format */
415     es_format_t fmt;
416     es_format_Init(&fmt, UNKNOWN_ES, 0);
417
418     fmt.i_id = var_InheritInteger(object, "imem-id");
419     fmt.i_group = var_InheritInteger(object, "imem-group");
420
421     char *tmp = var_InheritString(object, "imem-codec");
422     if (tmp)
423         fmt.i_codec = vlc_fourcc_GetCodecFromString(UNKNOWN_ES, tmp);
424     free(tmp);
425
426     const int cat = var_InheritInteger(object, "imem-cat");
427     switch (cat) {
428     case 1: {
429         fmt.i_cat = AUDIO_ES;
430         fmt.audio.i_channels = var_InheritInteger(object, "imem-channels");
431         fmt.audio.i_rate = var_InheritInteger(object, "imem-samplerate");
432
433         msg_Dbg(object, "Audio %4.4s %d channels %d Hz",
434                 (const char *)&fmt.i_codec,
435                 fmt.audio.i_channels, fmt.audio.i_rate);
436         break;
437     }
438     case 2: {
439         fmt.i_cat = VIDEO_ES;
440         fmt.video.i_width  = var_InheritInteger(object, "imem-width");
441         fmt.video.i_height = var_InheritInteger(object, "imem-height");
442         unsigned num, den;
443         if (!var_InheritRational(object, &num, &den, "imem-dar") && num > 0 && den > 0) {
444             if (fmt.video.i_width > 0 && fmt.video.i_height > 0) {
445                 fmt.video.i_sar_num = num * fmt.video.i_height;
446                 fmt.video.i_sar_den = den * fmt.video.i_width;
447             }
448         }
449         if (!var_InheritRational(object, &num, &den, "imem-fps") && num > 0 && den > 0) {
450             fmt.video.i_frame_rate      = num;
451             fmt.video.i_frame_rate_base = den;
452         }
453
454         msg_Dbg(object, "Video %4.4s %dx%d  SAR %d:%d frame rate %u/%u",
455                 (const char *)&fmt.i_codec,
456                 fmt.video.i_width, fmt.video.i_height,
457                 fmt.video.i_sar_num, fmt.video.i_sar_den,
458                 fmt.video.i_frame_rate, fmt.video.i_frame_rate_base);
459         break;
460     }
461     case 3: {
462         fmt.i_cat = SPU_ES;
463         fmt.subs.spu.i_original_frame_width =
464             var_InheritInteger(object, "imem-width");
465         fmt.subs.spu.i_original_frame_height =
466             var_InheritInteger(object, "imem-height");
467
468         msg_Dbg(object, "Subtitle %4.4s",
469                 (const char *)&fmt.i_codec);
470         break;
471     }
472     default:
473         if (cat != 4)
474             msg_Err(object, "Invalid ES category");
475         es_format_Clean(&fmt);
476         CloseCommon(sys);
477         return VLC_EGENERIC;
478     }
479
480     fmt.psz_language = var_InheritString(object, "imem-language");
481
482     sys->es = es_out_Add(demux->out, &fmt);
483     es_format_Clean(&fmt);
484
485     if (!sys->es) {
486         CloseCommon(sys);
487         return VLC_EGENERIC;
488     }
489
490     /* */
491     demux->pf_control = ControlDemux;
492     demux->pf_demux   = Demux;
493     demux->p_sys      = (demux_sys_t*)sys;
494
495     demux->info.i_update = 0;
496     demux->info.i_title = 0;
497     demux->info.i_seekpoint = 0;
498     return VLC_SUCCESS;
499 }
500
501 /**
502  * It closes an imem access_demux
503  */
504 static void CloseDemux(vlc_object_t *object)
505 {
506     demux_t *demux = (demux_t *)object;
507
508     CloseCommon((imem_sys_t*)demux->p_sys);
509 }
510
511 /**
512  * It controls an imem access_demux
513  */
514 static int ControlDemux(demux_t *demux, int i_query, va_list args)
515 {
516     imem_sys_t *sys = (imem_sys_t*)demux->p_sys;
517
518     switch (i_query)
519     {
520     case DEMUX_CAN_PAUSE:
521     case DEMUX_CAN_CONTROL_PACE: {
522         bool *b = va_arg(args, bool *);
523         *b = true;
524         return VLC_SUCCESS;
525     }
526     case DEMUX_SET_PAUSE_STATE:
527         return VLC_SUCCESS;
528
529     case DEMUX_GET_PTS_DELAY: {
530         int64_t *delay = va_arg(args, int64_t *);
531         *delay = sys->pts_delay;
532         return VLC_SUCCESS;
533     }
534     case DEMUX_GET_POSITION: {
535         double *position = va_arg(args, double *);
536         *position = 0.0;
537         return VLC_SUCCESS;
538     }
539     case DEMUX_GET_TIME: {
540         int64_t *t = va_arg(args, int64_t *);
541         *t = sys->dts;
542         return VLC_SUCCESS;
543     }
544     case DEMUX_GET_LENGTH: {
545         int64_t *l = va_arg(args, int64_t *);
546         *l = 0;
547         return VLC_SUCCESS;
548     }
549     case DEMUX_SET_NEXT_DEMUX_TIME:
550         sys->deadline = va_arg(args, int64_t);
551         return VLC_SUCCESS;
552
553     /* */
554     case DEMUX_CAN_SEEK:
555     case DEMUX_SET_POSITION:
556     case DEMUX_SET_TIME:
557     default:
558         return VLC_EGENERIC;
559     }
560
561     return VLC_EGENERIC;
562 }
563
564 /**
565  * It retreives data using the get() callback, sends them to es_out
566  * and the release it using the release() callback.
567  */
568 static int Demux(demux_t *demux)
569 {
570     imem_sys_t *sys = (imem_sys_t*)demux->p_sys;
571
572     if (sys->deadline == VLC_TS_INVALID)
573         sys->deadline = sys->dts + 1;
574
575     for (;;) {
576         if (sys->deadline <= sys->dts)
577             break;
578
579         /* */
580         int64_t dts, pts;
581         unsigned flags;
582         size_t buffer_size;
583         void   *buffer;
584
585         if (sys->source.get(sys->source.data, sys->source.cookie,
586                             &dts, &pts, &flags, &buffer_size, &buffer))
587             return 0;
588
589         if (dts < 0)
590             dts = pts;
591
592         if (buffer_size > 0) {
593             block_t *block = block_New(demux, buffer_size);
594             if (block) {
595                 block->i_dts = dts >= 0 ? (1 + dts) : VLC_TS_INVALID;
596                 block->i_pts = pts >= 0 ? (1 + pts) : VLC_TS_INVALID;
597                 memcpy(block->p_buffer, buffer, buffer_size);
598
599                 es_out_Control(demux->out, ES_OUT_SET_PCR, block->i_dts);
600                 es_out_Send(demux->out, sys->es, block);
601             }
602         }
603
604         sys->dts = dts;
605
606         sys->source.release(sys->source.data, sys->source.cookie,
607                             buffer_size, buffer);
608     }
609     sys->deadline = VLC_TS_INVALID;
610     return 1;
611 }
612
613 /**
614  * It parses a rational number (it also accepts basic float number).
615  *
616  * It returns an error if the rational number cannot be parsed (0/0 is valid).
617  */
618 static int (var_InheritRational)(vlc_object_t *object,
619                                  unsigned *num, unsigned *den,
620                                  const char *var)
621 {
622     /* */
623     *num = 0;
624     *den = 0;
625
626     /* */
627     char *tmp = var_InheritString(object, var);
628     if (!tmp)
629         goto error;
630
631     char *next;
632     unsigned n = strtol(tmp,  &next, 0);
633     unsigned d = strtol(*next ? &next[1] : "0", NULL, 0);
634
635     if (*next == '.') {
636         /* Interpret as a float number */
637         double r = us_atof(tmp);
638         double c = ceil(r);
639         if (c >= UINT_MAX)
640             goto error;
641         unsigned m = c;
642         if (m > 0) {
643             d = UINT_MAX / m;
644             n = r * d;
645         } else {
646             n = 0;
647             d = 0;
648         }
649     }
650
651     if (n > 0 && d > 0)
652         vlc_ureduce(num, den, n, d, 0);
653
654     free(tmp);
655     return VLC_SUCCESS;
656
657 error:
658     free(tmp);
659     return VLC_EGENERIC;
660 }
661
662 /**
663  * Parse the MRL and extract configuration from it.
664  *
665  * Syntax: option1=value1[:option2=value2[...]]
666  *
667  * XXX get and release are not supported on purpose.
668  */
669 static void ParseMRL(vlc_object_t *object, const char *psz_path)
670 {
671     static const struct {
672         const char *name;
673         int        type;
674     } options[] = {
675         { "caching",    VLC_VAR_INTEGER },
676         { "id",         VLC_VAR_INTEGER },
677         { "group",      VLC_VAR_INTEGER },
678         { "cat",        VLC_VAR_INTEGER },
679         { "samplerate", VLC_VAR_INTEGER },
680         { "channels",   VLC_VAR_INTEGER },
681         { "width",      VLC_VAR_INTEGER },
682         { "height",     VLC_VAR_INTEGER },
683         { "cookie",     VLC_VAR_STRING },
684         { "codec",      VLC_VAR_STRING },
685         { "language",   VLC_VAR_STRING },
686         { "dar",        VLC_VAR_STRING },
687         { "fps",        VLC_VAR_STRING },
688         { NULL, -1 }
689     };
690
691     char *dup = strdup(psz_path);
692     if (!dup)
693         return;
694     char *current = dup;
695
696     while (current) {
697         char *next = strchr(current, ':');
698         if (next)
699             *next++ = '\0';
700
701         char *option = current;
702         char *value = strchr(current, '=');
703         if (value) {
704             *value++ = '\0';
705             msg_Dbg(object, "option '%s' value '%s'", option, value);
706         } else {
707             msg_Dbg(object, "option '%s' without value (unsupported)", option);
708         }
709
710         char *name;
711         if (asprintf(&name, "imem-%s", option) < 0)
712             name = NULL;
713         for (unsigned i = 0; name && options[i].name; i++) {
714             if (strcmp(options[i].name, option))
715                 continue;
716             /* */
717             var_Create(object, name, options[i].type | VLC_VAR_DOINHERIT);
718             if (options[i].type == VLC_VAR_INTEGER && value) {
719                 var_SetInteger(object, name, strtol(value, NULL, 0));
720             } else if (options[i].type == VLC_VAR_STRING && value) {
721                 var_SetString(object, name, value);
722             }
723             break;
724         }
725         free(name);
726
727         /* */
728         current = next;
729     }
730     free(dup);
731 }