/// Wrapper around FromLocale, to avoid the need to call LocaleFree() static inline std::string sFromLocale( const std::string &rLocale ) { const char *s = FromLocale( rLocale.c_str() ); std::string res = s; LocaleFree( s ); return res; }
/** * Opens a system file handle relative to an existing directory handle. * * @param dir directory file descriptor * @param filename file path to open (with UTF-8 encoding) * @param flags open() flags, see the C library open() documentation * @return a file handle on success, -1 on error (see errno). * @note Contrary to standard open(), this function returns file handles * with the close-on-exec flag enabled. */ int vlc_openat (int dir, const char *filename, int flags, ...) { unsigned int mode = 0; va_list ap; va_start (ap, flags); if (flags & O_CREAT) mode = va_arg (ap, unsigned int); va_end (ap); #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif const char *local_name = ToLocale (filename); if (local_name == NULL) { errno = ENOENT; return -1; } #ifdef HAVE_OPENAT int fd = openat (dir, local_name, flags, mode); if (fd != -1) fcntl (fd, F_SETFD, FD_CLOEXEC); #else int fd = -1; errno = ENOSYS; #endif LocaleFree (local_name); return fd; }
/** * Opens a system file handle. * * @param filename file path to open (with UTF-8 encoding) * @param flags open() flags, see the C library open() documentation * @return a file handle on success, -1 on error (see errno). * @note Contrary to standard open(), this function returns file handles * with the close-on-exec flag enabled. */ int vlc_open (const char *filename, int flags, ...) { unsigned int mode = 0; va_list ap; va_start (ap, flags); if (flags & O_CREAT) mode = va_arg (ap, unsigned int); va_end (ap); const char *local_name = ToLocale (filename); if (local_name == NULL) { errno = ENOENT; return -1; } int fd = open (local_name, flags, mode); if (fd != -1) fcntl (fd, F_SETFD, FD_CLOEXEC); LocaleFree (local_name); return fd; }
/** * Moves a file atomically. This only works within a single file system. * * @param oldpath path to the file before the move * @param newpath intended path to the file after the move * @return A 0 return value indicates success. A -1 return value indicates an * error, and an error code is stored in errno */ int vlc_rename (const char *oldpath, const char *newpath) { const char *lo = ToLocale (oldpath); if (lo == NULL) goto error; const char *ln = ToLocale (newpath); if (ln == NULL) { LocaleFree (lo); error: errno = ENOENT; return -1; } int ret = rename (lo, ln); LocaleFree (lo); LocaleFree (ln); return ret; }
/** * Removes a file. * * @param filename a UTF-8 string with the name of the file you want to delete. * @return A 0 return value indicates success. A -1 return value indicates an * error, and an error code is stored in errno */ int vlc_unlink (const char *filename) { const char *local_name = ToLocale (filename); if (unlikely(local_name == NULL)) { errno = ENOENT; return -1; } int ret = unlink (local_name); LocaleFree (local_name); return ret; }
/** * Opens a DIR pointer. * * @param dirname UTF-8 representation of the directory name * @return a pointer to the DIR struct, or NULL in case of error. * Release with standard closedir(). */ DIR *vlc_opendir (const char *dirname) { const char *local_name = ToLocale (dirname); if (unlikely(local_name == NULL)) { errno = ENOENT; return NULL; } DIR *dir = opendir (local_name); LocaleFree (local_name); return dir; }
/** * Creates a directory using UTF-8 paths. * * @param dirname a UTF-8 string with the name of the directory that you * want to create. * @param mode directory permissions * @return 0 on success, -1 on error (see errno). */ int vlc_mkdir (const char *dirname, mode_t mode) { char *locname = ToLocale (dirname); if (unlikely(locname == NULL)) { errno = ENOENT; return -1; } int res = mkdir (locname, mode); LocaleFree (locname); return res; }
static int vlc_statEx (const char *filename, struct stat *buf, bool deref) { const char *local_name = ToLocale (filename); if (unlikely(local_name == NULL)) { errno = ENOENT; return -1; } int res = deref ? stat (local_name, buf) : lstat (local_name, buf); LocaleFree (local_name); return res; }
static char *config_GetAppDir (const char *xdg_name, const char *xdg_default) { char *psz_dir; char var[sizeof ("XDG__HOME") + strlen (xdg_name)]; /* XDG Base Directory Specification - Version 0.6 */ snprintf (var, sizeof (var), "XDG_%s_HOME", xdg_name); char *psz_home = FromLocale (getenv (var)); if( psz_home ) { if( asprintf( &psz_dir, "%s/vlc", psz_home ) == -1 ) psz_dir = NULL; LocaleFree (psz_home); return psz_dir; } psz_home = config_GetHomeDir (); if( psz_home == NULL || asprintf( &psz_dir, "%s/%s/vlc", psz_home, xdg_default ) == -1 ) psz_dir = NULL; free (psz_home); return psz_dir; }
/***************************************************************************** * Open: *****************************************************************************/ static int Open( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; char *psz_file; ifo_handle_t *p_vmg_file; if( !p_demux->psz_path || !*p_demux->psz_path ) { /* Only when selected */ if( !p_demux->psz_access || !*p_demux->psz_access ) return VLC_EGENERIC; psz_file = var_InheritString( p_this, "dvd" ); } else psz_file = strdup( p_demux->psz_path ); #ifdef WIN32 if( psz_file != NULL ) { size_t flen = strlen( psz_file ); if( flen > 0 && psz_file[flen - 1] == '\\' ) psz_file[flen - 1] = '\0'; } else psz_file = strdup(""); #endif if( unlikely(psz_file == NULL) ) return VLC_EGENERIC; /* Open dvdread */ const char *psz_path = ToLocale( psz_file ); dvd_reader_t *p_dvdread = DVDOpen( psz_path ); LocaleFree( psz_path ); if( p_dvdread == NULL ) { msg_Err( p_demux, "DVDRead cannot open source: %s", psz_file ); dialog_Fatal( p_demux, _("Playback failure"), _("DVDRead could not open the disc \"%s\"."), psz_file ); free( psz_file ); return VLC_EGENERIC; } free( psz_file ); /* Ifo allocation & initialisation */ if( !( p_vmg_file = ifoOpen( p_dvdread, 0 ) ) ) { msg_Warn( p_demux, "cannot open VMG info" ); return VLC_EGENERIC; } msg_Dbg( p_demux, "VMG opened" ); /* Fill p_demux field */ DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys; ps_track_init( p_sys->tk ); p_sys->i_sar_num = 0; p_sys->i_sar_den = 0; p_sys->i_title_cur_time = (mtime_t) 0; p_sys->i_cell_cur_time = (mtime_t) 0; p_sys->i_cell_duration = (mtime_t) 0; p_sys->p_dvdread = p_dvdread; p_sys->p_vmg_file = p_vmg_file; p_sys->p_title = NULL; p_sys->p_vts_file = NULL; p_sys->i_title = p_sys->i_chapter = -1; p_sys->i_mux_rate = 0; p_sys->i_angle = var_CreateGetInteger( p_demux, "dvdread-angle" ); if( p_sys->i_angle <= 0 ) p_sys->i_angle = 1; DemuxTitles( p_demux, &p_sys->i_angle ); if( DvdReadSetArea( p_demux, 0, 0, p_sys->i_angle ) != VLC_SUCCESS ) { Close( p_this ); msg_Err( p_demux, "DvdReadSetArea(0,0,%i) failed (can't decrypt DVD?)", p_sys->i_angle ); return VLC_EGENERIC; } /* Update default_pts to a suitable value for dvdread access */ var_Create( p_demux, "dvdread-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); return VLC_SUCCESS; }
/***************************************************************************** * main: parse command line, start interface and spawn threads. *****************************************************************************/ int main( int i_argc, const char *ppsz_argv[] ) { #ifdef __APPLE__ /* The so-called POSIX-compliant MacOS X is not. * SIGPIPE fires even when it is blocked in all threads! */ signal (SIGPIPE, SIG_IGN); #endif #ifndef ALLOW_RUN_AS_ROOT if (geteuid () == 0) { fprintf (stderr, "VLC is not supposed to be run as root. Sorry.\n" "If you need to use real-time priorities and/or privileged TCP ports\n" "you can use %s-wrapper (make sure it is Set-UID root and\n" "cannot be run by non-trusted users first).\n", ppsz_argv[0]); return 1; } #endif setlocale (LC_ALL, ""); #ifndef __APPLE__ /* This clutters OSX GUI error logs */ fprintf( stderr, "VLC media player %s\n", libvlc_get_version() ); #endif #ifdef HAVE_PUTENV # ifndef NDEBUG /* Activate malloc checking routines to detect heap corruptions. */ putenv( (char*)"MALLOC_CHECK_=2" ); /* Disable the ugly Gnome crash dialog so that we properly segfault */ putenv( (char *)"GNOME_DISABLE_CRASH_DIALOG=1" ); # endif #endif /* Synchronously intercepted POSIX signals. * * In a threaded program such as VLC, the only sane way to handle signals * is to block them in all thread but one - this is the only way to * predict which thread will receive them. If any piece of code depends * on delivery of one of this signal it is intrinsically not thread-safe * and MUST NOT be used in VLC, whether we like it or not. * There is only one exception: if the signal is raised with * pthread_kill() - we do not use this in LibVLC but some pthread * implementations use them internally. You should really use conditions * for thread synchronization anyway. * * Signal that request a clean shutdown, and force an unclean shutdown * if they are triggered again 2+ seconds later. * We have to handle SIGTERM cleanly because of daemon mode. * Note that we set the signals after the vlc_create call. */ static const int sigs[] = { SIGINT, SIGHUP, SIGQUIT, SIGTERM, /* Signals that cause a no-op: * - SIGPIPE might happen with sockets and would crash VLC. It MUST be * blocked by any LibVLC-dependent application, not just VLC. * - SIGCHLD comes after exec*() (such as httpd CGI support) and must * be dequeued to cleanup zombie processes. */ SIGPIPE, SIGCHLD }; sigset_t set; sigemptyset (&set); for (unsigned i = 0; i < sizeof (sigs) / sizeof (sigs[0]); i++) sigaddset (&set, sigs[i]); /* Block all these signals */ pthread_sigmask (SIG_BLOCK, &set, NULL); sigdelset (&set, SIGPIPE); sigdelset (&set, SIGCHLD); /* Note that FromLocale() can be used before libvlc is initialized */ const char *argv[i_argc + 3]; int argc = 0; argv[argc++] = "--no-ignore-config"; #ifdef TOP_BUILDDIR argv[argc++] = FromLocale ("--plugin-path="TOP_BUILDDIR"/modules"); #endif #ifdef TOP_SRCDIR # ifdef ENABLE_HTTPD argv[argc++] = FromLocale ("--http-src="TOP_SRCDIR"/share/http"); # endif #endif for (int i = 1; i < i_argc; i++) if ((argv[argc++] = FromLocale (ppsz_argv[i])) == NULL) return 1; // BOOM! argv[argc] = NULL; libvlc_exception_t ex, dummy; libvlc_exception_init (&ex); libvlc_exception_init (&dummy); /* Initialize libvlc */ libvlc_instance_t *vlc = libvlc_new (argc, argv, &ex); if (vlc != NULL) { libvlc_add_intf (vlc, "signals", &ex); if (libvlc_exception_raised (&ex)) { libvlc_exception_clear (&ex); pthread_sigmask (SIG_UNBLOCK, &set, NULL); } #if !defined (HAVE_MAEMO) libvlc_add_intf (vlc, "globalhotkeys,none", &ex); #endif libvlc_exception_clear (&ex); libvlc_add_intf (vlc, NULL, &ex); libvlc_playlist_play (vlc, -1, 0, NULL, &dummy); libvlc_wait (vlc); if (libvlc_exception_raised (&ex)) fprintf( stderr, "%s\n", libvlc_errmsg() ); libvlc_release (vlc); } for (int i = 1; i < argc; i++) LocaleFree (argv[i]); return vlc == NULL || libvlc_exception_raised (&ex); }
/***************************************************************************** * main: parse command line, start interface and spawn threads. *****************************************************************************/ int main( int i_argc, const char *ppsz_argv[] ) { /* The so-called POSIX-compliant MacOS X reportedly processes SIGPIPE even * if it is blocked in all thread. Also some libraries want SIGPIPE blocked * as they have no clue about signal masks. * Note: this is NOT an excuse for not protecting against SIGPIPE. If * LibVLC runs outside of VLC, we cannot rely on this code snippet. */ signal (SIGPIPE, SIG_IGN); /* Restore default for SIGCHLD in case parent ignores it. */ signal (SIGCHLD, SIG_DFL); #ifdef HAVE_SETENV # ifndef NDEBUG /* Activate malloc checking routines to detect heap corruptions. */ setenv ("MALLOC_CHECK_", "2", 1); /* Disable the ugly Gnome crash dialog so that we properly segfault */ setenv ("GNOME_DISABLE_CRASH_DIALOG", "1", 1); # endif /* Clear the X.Org startup notification ID. Otherwise the UI might try to * change the environment while the process is multi-threaded. That could * crash. Screw you X.Org. Next time write a thread-safe specification. */ unsetenv ("DESKTOP_STARTUP_ID"); #endif #ifndef ALLOW_RUN_AS_ROOT if (geteuid () == 0) { fprintf (stderr, "VLC is not supposed to be run as root. Sorry.\n" "If you need to use real-time priorities and/or privileged TCP ports\n" "you can use %s-wrapper (make sure it is Set-UID root and\n" "cannot be run by non-trusted users first).\n", ppsz_argv[0]); return 1; } #endif setlocale (LC_ALL, ""); #ifndef __APPLE__ /* This clutters OSX GUI error logs */ fprintf( stderr, "VLC media player %s (revision %s)\n", libvlc_get_version(), libvlc_get_changeset() ); #endif /* Synchronously intercepted POSIX signals. * * In a threaded program such as VLC, the only sane way to handle signals * is to block them in all threads but one - this is the only way to * predict which thread will receive them. If any piece of code depends * on delivery of one of this signal it is intrinsically not thread-safe * and MUST NOT be used in VLC, whether we like it or not. * There is only one exception: if the signal is raised with * pthread_kill() - we do not use this in LibVLC but some pthread * implementations use them internally. You should really use conditions * for thread synchronization anyway. * * Signal that request a clean shutdown, and force an unclean shutdown * if they are triggered again 2+ seconds later. * We have to handle SIGTERM cleanly because of daemon mode. * Note that we set the signals after the vlc_create call. */ static const int sigs[] = { SIGINT, SIGHUP, SIGQUIT, SIGTERM, /* Signals that cause a no-op: * - SIGPIPE might happen with sockets and would crash VLC. It MUST be * blocked by any LibVLC-dependent application, not just VLC. * - SIGCHLD comes after exec*() (such as httpd CGI support) and must * be dequeued to cleanup zombie processes. */ SIGPIPE, SIGCHLD }; sigset_t set; sigemptyset (&set); for (unsigned i = 0; i < sizeof (sigs) / sizeof (sigs[0]); i++) sigaddset (&set, sigs[i]); #ifdef HAVE_MAEMO sigaddset (&set, SIGRTMIN); { struct sigaction act = { .sa_handler = dummy_handler, }; sigaction (SIGRTMIN, &act, NULL); } #endif /* Block all these signals */ pthread_sigmask (SIG_BLOCK, &set, NULL); sigdelset (&set, SIGPIPE); sigdelset (&set, SIGCHLD); /* Note that FromLocale() can be used before libvlc is initialized */ const char *argv[i_argc + 3]; int argc = 0; argv[argc++] = "--no-ignore-config"; #ifdef TOP_BUILDDIR argv[argc++] = FromLocale ("--plugin-path="TOP_BUILDDIR"/modules"); #endif #ifdef TOP_SRCDIR argv[argc++] = FromLocale ("--data-path="TOP_SRCDIR"/share"); #endif int i = 1; #ifdef __APPLE__ /* When VLC.app is run by double clicking in Mac OS X, the 2nd arg * is the PSN - process serial number (a unique PID-ish thingie) * still ok for real Darwin & when run from command line * for example -psn_0_9306113 */ if(i_argc >= 2 && !strncmp( ppsz_argv[1] , "-psn" , 4 )) i = 2; #endif for (; i < i_argc; i++) if ((argv[argc++] = FromLocale (ppsz_argv[i])) == NULL) return 1; // BOOM! argv[argc] = NULL; vlc_enable_override (); /* Initialize libvlc */ libvlc_instance_t *vlc = libvlc_new (argc, argv); if (vlc != NULL) { libvlc_set_user_agent (vlc, "VLC media player", NULL); if (libvlc_add_intf (vlc, "signals")) pthread_sigmask (SIG_UNBLOCK, &set, NULL); #if !defined (HAVE_MAEMO) && !defined __APPLE__ libvlc_add_intf (vlc, "globalhotkeys,none"); #endif if (libvlc_add_intf (vlc, NULL) == 0) { libvlc_playlist_play (vlc, -1, 0, NULL); libvlc_wait (vlc); } libvlc_release (vlc); } for (int i = 1; i < argc; i++) LocaleFree (argv[i]); return 0; }
/** * Load a dynamically linked library using a system dependent method. * * \param p_this vlc object * \param psz_file library file * \param p_handle the module handle returned * \return 0 on success as well as the module handle. */ int module_Load( vlc_object_t *p_this, const char *psz_file, module_handle_t *p_handle ) { module_handle_t handle; #if defined(HAVE_DL_BEOS) handle = load_add_on( psz_file ); if( handle < 0 ) { msg_Warn( p_this, "cannot load module `%s'", psz_file ); return -1; } #elif defined(HAVE_DL_WINDOWS) wchar_t psz_wfile[MAX_PATH]; MultiByteToWideChar( CP_UTF8, 0, psz_file, -1, psz_wfile, MAX_PATH ); #ifndef UNDER_CE /* FIXME: this is not thread-safe -- Courmisch */ UINT mode = SetErrorMode (SEM_FAILCRITICALERRORS); SetErrorMode (mode|SEM_FAILCRITICALERRORS); #endif handle = LoadLibraryW( psz_wfile ); #ifndef UNDER_CE SetErrorMode (mode); #endif if( handle == NULL ) { char *psz_err = GetWindowsError(); msg_Warn( p_this, "cannot load module `%s' (%s)", psz_file, psz_err ); free( psz_err ); return -1; } #elif defined(HAVE_DL_DLOPEN) # if defined (RTLD_NOW) const int flags = RTLD_NOW; # elif defined (DL_LAZY) const int flags = DL_LAZY; # else const int flags = 0; # endif char *path = ToLocale( psz_file ); handle = dlopen( path, flags ); if( handle == NULL ) { msg_Warn( p_this, "cannot load module `%s' (%s)", path, dlerror() ); LocaleFree( path ); return -1; } LocaleFree( path ); #elif defined(HAVE_DL_SHL_LOAD) handle = shl_load( psz_file, BIND_IMMEDIATE | BIND_NONFATAL, NULL ); if( handle == NULL ) { msg_Warn( p_this, "cannot load module `%s' (%m)", psz_file ); return -1; } #else # error "Something is wrong in modules.c" #endif *p_handle = handle; return 0; }
static int Open (vlc_object_t *p_this) { decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys; if (p_dec->fmt_in.i_codec != VLC_CODEC_MIDI) return VLC_EGENERIC; char *font_path = var_InheritString (p_this, "soundfont"); if (font_path == NULL) { msg_Err (p_this, "sound font file required for synthesis"); dialog_Fatal (p_this, _("MIDI synthesis not set up"), _("A sound font file (.SF2) is required for MIDI synthesis.\n" "Please install a sound font and configure it " "from the VLC preferences " "(Input / Codecs > Audio codecs > FluidSynth).\n")); return VLC_EGENERIC; } p_dec->pf_decode_audio = DecodeBlock; p_sys = p_dec->p_sys = malloc (sizeof (*p_sys)); if (p_sys == NULL) { free (font_path); return VLC_ENOMEM; } p_sys->settings = new_fluid_settings (); p_sys->synth = new_fluid_synth (p_sys->settings); /* FIXME: I bet this is not thread-safe */ const char *lpath = ToLocale (font_path); p_sys->soundfont = fluid_synth_sfload (p_sys->synth, font_path, 1); LocaleFree (lpath); if (p_sys->soundfont == -1) { msg_Err (p_this, "cannot load sound fonts file %s", font_path); Close (p_this); dialog_Fatal (p_this, _("MIDI synthesis not set up"), _("The specified sound font file (%s) is incorrect.\n" "Please install a valid sound font and reconfigure it " "from the VLC preferences (Codecs / Audio / FluidSynth).\n"), font_path); free (font_path); return VLC_EGENERIC; } free (font_path); p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.audio.i_rate = 44100; p_dec->fmt_out.audio.i_channels = 2; p_dec->fmt_out.audio.i_original_channels = p_dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; if (HAVE_FPU) { p_dec->fmt_out.i_codec = VLC_CODEC_FL32; p_dec->fmt_out.audio.i_bitspersample = 32; p_sys->fixed = false; } else { p_dec->fmt_out.i_codec = VLC_CODEC_S16N; p_dec->fmt_out.audio.i_bitspersample = 16; p_sys->fixed = true; } date_Init (&p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1); date_Set (&p_sys->end_date, 0); return VLC_SUCCESS; }
static int Demux( demux_t *p_demux ) { char *psz_line; char *psz_name = NULL; char *psz_artist = NULL; int i_parsed_duration = 0; mtime_t i_duration = -1; const char**ppsz_options = NULL; char * (*pf_dup) (const char *) = p_demux->p_sys->pf_dup; int i_options = 0; bool b_cleanup = false; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); psz_line = stream_ReadLine( p_demux->s ); while( psz_line ) { char *psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; if( *psz_parse == '#' ) { /* Parse extra info */ /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' || *psz_parse == '#' ) psz_parse++; if( !*psz_parse ) goto error; if( !strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") -1 ) ) { /* Extended info */ psz_parse += sizeof("EXTINF:") - 1; parseEXTINF( psz_parse, &psz_artist, &psz_name, &i_parsed_duration ); if( i_parsed_duration >= 0 ) i_duration = i_parsed_duration * INT64_C(1000000); if( psz_name ) psz_name = pf_dup( psz_name ); if( psz_artist ) psz_artist = pf_dup( psz_artist ); } else if( !strncasecmp( psz_parse, "EXTVLCOPT:", sizeof("EXTVLCOPT:") -1 ) ) { /* VLC Option */ char *psz_option; psz_parse += sizeof("EXTVLCOPT:") -1; if( !*psz_parse ) goto error; psz_option = pf_dup( psz_parse ); if( psz_option ) INSERT_ELEM( ppsz_options, i_options, i_options, psz_option ); } } else if( !strncasecmp( psz_parse, "RTSPtext", sizeof("RTSPtext") -1 ) ) { ;/* special case to handle QuickTime RTSPtext redirect files */ } else if( *psz_parse ) { char *psz_mrl; psz_parse = pf_dup( psz_parse ); if( !psz_name && psz_parse ) /* Use filename as name for relative entries */ psz_name = strdup( psz_parse ); psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix ); b_cleanup = true; if( !psz_mrl ) goto error; p_input = input_item_NewExt( p_demux, psz_mrl, psz_name, i_options, ppsz_options, 0, i_duration ); LocaleFree( psz_parse ); free( psz_mrl ); if ( psz_artist && *psz_artist ) input_item_SetArtist( p_input, psz_artist ); if( psz_name ) input_item_SetTitle( p_input, psz_name ); input_item_AddSubItem( p_current_input, p_input ); vlc_gc_decref( p_input ); } error: /* Fetch another line */ free( psz_line ); psz_line = stream_ReadLine( p_demux->s ); if( !psz_line ) b_cleanup = true; if( b_cleanup ) { /* Cleanup state */ while( i_options-- ) free( (char*)ppsz_options[i_options] ); free( ppsz_options ); ppsz_options = NULL; i_options = 0; free( psz_name ); psz_name = NULL; free( psz_artist ); psz_artist = NULL; i_parsed_duration = 0; i_duration = -1; b_cleanup = false; } } vlc_gc_decref(p_current_input); var_Destroy( p_demux, "m3u-extvlcopt" ); return 0; /* Needed for correct operation of go back */ }