/** * @brief Add a directory to monitor * @param p_ml This media_library_t object * @param psz_dir the directory to add * @return VLC_SUCCESS or VLC_EGENERIC */ int AddDirToMonitor( media_library_t *p_ml, const char *psz_dir ) { assert( p_ml ); /* Verify if we can open the directory */ DIR *dir = vlc_opendir( psz_dir ); if( !dir ) { int err = errno; if( err != ENOTDIR ) msg_Err( p_ml, "%s: %m", psz_dir ); else msg_Dbg( p_ml, "`%s' is not a directory", psz_dir ); errno = err; return VLC_EGENERIC; } closedir( dir ); msg_Dbg( p_ml, "Adding directory `%s' to be monitored", psz_dir ); QuerySimple( p_ml, "INSERT INTO directories ( uri, timestamp, " "recursive ) VALUES( %Q, 0, 0 )", psz_dir ); vlc_cond_signal( &p_ml->p_sys->p_mon->wait ); return VLC_SUCCESS; }
/***************************************************************************** * DirOpen: Open the directory access *****************************************************************************/ int DirOpen (vlc_object_t *obj) { stream_t *access = (stream_t *)obj; if (access->psz_filepath == NULL) return VLC_EGENERIC; DIR *dir = vlc_opendir(access->psz_filepath); if (dir == NULL) return VLC_EGENERIC; return DirInit(access, dir); }
/***************************************************************************** * Open: open the directory *****************************************************************************/ int DirOpen( vlc_object_t *p_this ) { access_t *p_access = (access_t*)p_this; if( !p_access->psz_filepath ) return VLC_EGENERIC; DIR *handle = vlc_opendir (p_access->psz_filepath); if (handle == NULL) return VLC_EGENERIC; return DirInit (p_access, handle); }
/** * Selects file entries from a directory, as GNU C scandir(). * * @param dirname UTF-8 diretory path * @param pointer [OUT] pointer set, on successful completion, to the address * of a table of UTF-8 filenames. All filenames must be freed with free(). * The table itself must be freed with free() as well. * * @return How many file names were selected (possibly 0), * or -1 in case of error. */ int vlc_scandir( const char *dirname, char ***namelist, int (*select)( const char * ), int (*compar)( const char **, const char ** ) ) { DIR *dir = vlc_opendir (dirname); int val = -1; if (dir != NULL) { val = vlc_loaddir (dir, namelist, select, compar); closedir (dir); } return val; }
void ThemeRepository::parseDirectory( const string &rDir_locale ) { DIR *pDir; char *pszDirContent; // Path separator const string &sep = OSFactory::instance( getIntf() )->getDirSeparator(); // Open the dir // FIXME: parseDirectory should be invoked with UTF-8 input instead!! string rDir = sFromLocale( rDir_locale ); pDir = vlc_opendir( rDir.c_str() ); if( pDir == NULL ) { // An error occurred msg_Dbg( getIntf(), "cannot open directory %s", rDir.c_str() ); return; } // While we still have entries in the directory while( ( pszDirContent = vlc_readdir( pDir ) ) != NULL ) { string name = pszDirContent; string extension; if( name.size() > 4 ) { extension = name.substr( name.size() - 4, 4 ); } if( extension == ".vlt" || extension == ".wsz" ) { string path = rDir + sep + name; string shortname = name.substr( 0, name.size() - 4 ); for( string::size_type i = 0; i < shortname.size(); i++ ) shortname[i] = ( i == 0 ) ? toupper( shortname[i] ) : tolower( shortname[i] ); m_skinsMap[shortname] = path; msg_Dbg( getIntf(), "found skin %s", path.c_str() ); } free( pszDirContent ); } closedir( pDir ); }
int playlist_FindArtInCache( input_item_t *p_item ) { char *psz_path = ArtCachePath( p_item ); if( !psz_path ) return VLC_EGENERIC; /* Check if file exists */ DIR *p_dir = vlc_opendir( psz_path ); if( !p_dir ) { free( psz_path ); return VLC_EGENERIC; } bool b_found = false; char *psz_filename; while( !b_found && (psz_filename = vlc_readdir( p_dir )) ) { if( !strncmp( psz_filename, "art", 3 ) ) { char *psz_file; if( asprintf( &psz_file, "%s" DIR_SEP "%s", psz_path, psz_filename ) != -1 ) { char *psz_uri = make_URI( psz_file, "file" ); if( psz_uri ) { input_item_SetArtURL( p_item, psz_uri ); free( psz_uri ); } free( psz_file ); } b_found = true; } free( psz_filename ); } /* */ closedir( p_dir ); free( psz_path ); return b_found ? VLC_SUCCESS : VLC_EGENERIC; }
static int vlclua_opendir( lua_State *L ) { const char *psz_dir = luaL_checkstring( L, 1 ); DIR *p_dir; int i = 0; if( ( p_dir = vlc_opendir( psz_dir ) ) == NULL ) return luaL_error( L, "cannot open directory `%s'.", psz_dir ); lua_newtable( L ); for( ;; ) { const char *psz_filename = vlc_readdir( p_dir ); if( !psz_filename ) break; i++; lua_pushstring( L, psz_filename ); lua_rawseti( L, -2, i ); } closedir( p_dir ); return 1; }
bool ThemeLoader::findFile( const string &rootDir, const string &rFileName, string &themeFilePath ) { // Path separator const string &sep = OSFactory::instance( getIntf() )->getDirSeparator(); DIR *pCurrDir; char *pszDirContent; // Open the dir pCurrDir = vlc_opendir( rootDir.c_str() ); if( pCurrDir == NULL ) { // An error occurred msg_Dbg( getIntf(), "cannot open directory %s", rootDir.c_str() ); return false; } // While we still have entries in the directory while( ( pszDirContent = vlc_readdir( pCurrDir ) ) != NULL ) { string newURI = rootDir + sep + pszDirContent; // Skip . and .. if( string( pszDirContent ) != "." && string( pszDirContent ) != ".." ) { #if defined( S_ISDIR ) struct stat stat_data; if( ( vlc_stat( newURI.c_str(), &stat_data ) == 0 ) && S_ISDIR(stat_data.st_mode) ) #elif defined( DT_DIR ) if( pDirContent->d_type & DT_DIR ) #else if( 0 ) #endif { // Can we find the file in this subdirectory? if( findFile( newURI, rFileName, themeFilePath ) ) { free( pszDirContent ); closedir( pCurrDir ); return true; } } else { // Found the theme file? if( rFileName == string( pszDirContent ) ) { themeFilePath = newURI; free( pszDirContent ); closedir( pCurrDir ); return true; } } } free( pszDirContent ); } closedir( pCurrDir ); return false; }
/** * Recursively browses a directory to look for plug-ins. */ static void AllocatePluginDir (module_bank_t *bank, unsigned maxdepth, const char *absdir, const char *reldir) { if (maxdepth == 0) return; maxdepth--; DIR *dh = vlc_opendir (absdir); if (dh == NULL) return; /* Parse the directory and try to load all files it contains. */ for (;;) { char *relpath = NULL, *abspath = NULL; const char *file = vlc_readdir (dh); if (file == NULL) break; /* Skip ".", ".." */ if (!strcmp (file, ".") || !strcmp (file, "..")) continue; /* Compute path relative to plug-in base directory */ if (reldir != NULL) { if (asprintf (&relpath, "%s"DIR_SEP"%s", reldir, file) == -1) relpath = NULL; } else relpath = strdup (file); if (unlikely(relpath == NULL)) continue; /* Compute absolute path */ if (asprintf (&abspath, "%s"DIR_SEP"%s", bank->base, relpath) == -1) { abspath = NULL; goto skip; } struct stat st; if (vlc_stat (abspath, &st) == -1) goto skip; if (S_ISREG (st.st_mode)) { static const char prefix[] = "lib"; static const char suffix[] = "_plugin"LIBEXT; size_t len = strlen (file); #ifndef __OS2__ /* Check that file matches the "lib*_plugin"LIBEXT pattern */ if (len > strlen (suffix) && !strncmp (file, prefix, strlen (prefix)) && !strcmp (file + len - strlen (suffix), suffix)) #else /* We load all the files ending with LIBEXT on OS/2, * because OS/2 has a 8.3 length limitation for DLL name */ if (len > strlen (LIBEXT) && !strcasecmp (file + len - strlen (LIBEXT), LIBEXT)) #endif AllocatePluginFile (bank, abspath, relpath, &st); } else if (S_ISDIR (st.st_mode)) /* Recurse into another directory */ AllocatePluginDir (bank, maxdepth, abspath, relpath); skip: free (relpath); free (abspath); } closedir (dh); }
int vout_snapshot_SaveImage(char **name, int *sequential, const block_t *image, vout_thread_t *p_vout, const vout_snapshot_save_cfg_t *cfg) { /* */ char *filename; DIR *pathdir = vlc_opendir(cfg->path); input_thread_t *input = (input_thread_t*)p_vout->p->input; if (pathdir != NULL) { /* The use specified a directory path */ closedir(pathdir); /* */ char *prefix = NULL; if (cfg->prefix_fmt) prefix = str_format(input, cfg->prefix_fmt); if (prefix) filename_sanitize(prefix); else { prefix = strdup("vlcsnap-"); if (!prefix) goto error; } if (cfg->is_sequential) { for (int num = cfg->sequence; ; num++) { struct stat st; if (asprintf(&filename, "%s" DIR_SEP "%s%05d.%s", cfg->path, prefix, num, cfg->format) < 0) { free(prefix); goto error; } if (vlc_stat(filename, &st)) { *sequential = num; break; } free(filename); } } else { struct timespec ts; struct tm curtime; char buffer[128]; timespec_get(&ts, TIME_UTC); if (localtime_r(&ts.tv_sec, &curtime) == NULL) gmtime_r(&ts.tv_sec, &curtime); if (strftime(buffer, sizeof(buffer), "%Y-%m-%d-%Hh%Mm%Ss", &curtime) == 0) strcpy(buffer, "error"); if (asprintf(&filename, "%s" DIR_SEP "%s%s%03lu.%s", cfg->path, prefix, buffer, ts.tv_nsec / 1000000, cfg->format) < 0) filename = NULL; } free(prefix); } else { /* The user specified a full path name (including file name) */ filename = str_format(input, cfg->path); path_sanitize(filename); } if (!filename) goto error; /* Save the snapshot */ FILE *file = vlc_fopen(filename, "wb"); if (!file) { msg_Err(p_vout, "Failed to open '%s'", filename); free(filename); goto error; } if (fwrite(image->p_buffer, image->i_buffer, 1, file) != 1) { msg_Err(p_vout, "Failed to write to '%s'", filename); fclose(file); free(filename); goto error; } fclose(file); /* */ if (name) *name = filename; else free(filename); return VLC_SUCCESS; error: msg_Err(p_vout, "could not save snapshot"); return VLC_EGENERIC; }
block_t *DirBlock (access_t *p_access) { access_sys_t *p_sys = p_access->p_sys; directory_t *current = p_sys->current; if (p_access->info.b_eof) return NULL; if (current == NULL) { /* Startup: send the XSPF header */ static const char header[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\" xmlns:vlc=\"http://www.videolan.org/vlc/playlist/ns/0/\">\n" " <trackList>\n"; block_t *block = block_Alloc (sizeof (header) - 1); if (!block) goto fatal; memcpy (block->p_buffer, header, sizeof (header) - 1); /* "Open" the base directory */ current = malloc (sizeof (*current)); if (current == NULL) { block_Release (block); goto fatal; } current->parent = NULL; current->handle = p_sys->handle; #ifndef HAVE_OPENAT current->path = strdup (p_access->psz_filepath); #endif current->uri = p_sys->uri; if (fstat (dirfd (current->handle), ¤t->st)) { free (current); block_Release (block); goto fatal; } p_sys->handle = NULL; p_sys->uri = NULL; p_sys->current = current; return block; } char *entry = vlc_readdir (current->handle); if (entry == NULL) { /* End of directory, go back to parent */ closedir (current->handle); p_sys->current = current->parent; free (current->uri); #ifndef HAVE_OPENAT free (current->path); #endif free (current); if (p_sys->current == NULL) { /* End of XSPF playlist */ char *footer; int len = asprintf( &footer, " </trackList>\n" \ " <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n" \ "%s" \ " </extension>\n" \ "</playlist>\n", p_sys->psz_xspf_extension ); if (unlikely(len == -1)) goto fatal; block_t *block = block_heap_Alloc (footer, footer, len); if (unlikely(block == NULL)) free (footer); p_access->info.b_eof = true; return block; } else { /* This was the end of a "subnode" */ /* Write the ID to the extension */ char *old_xspf_extension = p_sys->psz_xspf_extension; if (old_xspf_extension == NULL) goto fatal; int len2 = asprintf( &p_sys->psz_xspf_extension, "%s </vlc:node>\n", old_xspf_extension ); if (len2 == -1) goto fatal; free( old_xspf_extension ); } return NULL; } /* Skip current, parent and hidden directories */ if (entry[0] == '.') { free (entry); return NULL; } /* Handle recursion */ if (p_sys->mode != MODE_COLLAPSE) { directory_t *sub = malloc (sizeof (*sub)); if (sub == NULL) { free (entry); return NULL; } DIR *handle; #ifdef HAVE_OPENAT int fd = vlc_openat (dirfd (current->handle), entry, O_RDONLY); if (fd != -1) { handle = fdopendir (fd); if (handle == NULL) close (fd); } else handle = NULL; #else if (asprintf (&sub->path, "%s/%s", current->path, entry) != -1) handle = vlc_opendir (sub->path); else handle = NULL; #endif if (handle != NULL) { sub->parent = current; sub->handle = handle; char *encoded = encode_URI_component (entry); if ((encoded == NULL) || (asprintf (&sub->uri, "%s/%s", current->uri, encoded) == -1)) sub->uri = NULL; free (encoded); if ((p_sys->mode == MODE_NONE) || fstat (dirfd (handle), &sub->st) || has_inode_loop (sub) || (sub->uri == NULL)) { free (entry); closedir (handle); free (sub->uri); free (sub); return NULL; } p_sys->current = sub; /* Add node to xspf extension */ char *old_xspf_extension = p_sys->psz_xspf_extension; if (old_xspf_extension == NULL) { free (entry); goto fatal; } char *title = convert_xml_special_chars (entry); free (entry); if (title == NULL || asprintf (&p_sys->psz_xspf_extension, "%s" " <vlc:node title=\"%s\">\n", old_xspf_extension, title) == -1) { free (title); goto fatal; } free (title); free (old_xspf_extension); return NULL; } else free (sub); } /* Skip files with ignored extensions */ if (p_sys->ignored_exts != NULL) { const char *ext = strrchr (entry, '.'); if (ext != NULL) { size_t extlen = strlen (++ext); for (const char *type = p_sys->ignored_exts, *end; type[0]; type = end + 1) { end = strchr (type, ','); if (end == NULL) end = type + strlen (type); if (type + extlen == end && !strncasecmp (ext, type, extlen)) { free (entry); return NULL; } if (*end == '\0') break; } } } char *encoded = encode_URI_component (entry); free (entry); if (encoded == NULL) goto fatal; int len = asprintf (&entry, " <track><location>%s/%s</location>\n" \ " <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n" \ " <vlc:id>%d</vlc:id>\n" \ " </extension>\n" \ " </track>\n", current->uri, encoded, p_sys->i_item_count++); free (encoded); if (len == -1) goto fatal; /* Write the ID to the extension */ char *old_xspf_extension = p_sys->psz_xspf_extension; if (old_xspf_extension == NULL) goto fatal; int len2 = asprintf( &p_sys->psz_xspf_extension, "%s <vlc:item tid=\"%i\" />\n", old_xspf_extension, p_sys->i_item_count-1 ); if (len2 == -1) goto fatal; free( old_xspf_extension ); block_t *block = block_heap_Alloc (entry, entry, len); if (unlikely(block == NULL)) { free (entry); goto fatal; } return block; fatal: p_access->info.b_eof = true; return NULL; }
/***************************************************************************** * Open: initializes matroska demux structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; matroska_stream_c *p_stream; matroska_segment_c *p_segment; const uint8_t *p_peek; std::string s_path, s_filename; vlc_stream_io_callback *p_io_callback; EbmlStream *p_io_stream; bool b_need_preload = false; /* peek the begining */ if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC; /* is a valid file */ if( p_peek[0] != 0x1a || p_peek[1] != 0x45 || p_peek[2] != 0xdf || p_peek[3] != 0xa3 ) return VLC_EGENERIC; /* Set the demux function */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = new demux_sys_t( *p_demux ); p_io_callback = new vlc_stream_io_callback( p_demux->s, false ); p_io_stream = new (std::nothrow) EbmlStream( *p_io_callback ); if( p_io_stream == NULL ) { msg_Err( p_demux, "failed to create EbmlStream" ); delete p_io_callback; delete p_sys; return VLC_EGENERIC; } p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_io_stream, true ); if( p_stream == NULL ) { msg_Err( p_demux, "cannot find KaxSegment or missing mandatory KaxInfo" ); goto error; } p_sys->streams.push_back( p_stream ); p_stream->p_io_callback = p_io_callback; p_stream->p_estream = p_io_stream; for (size_t i=0; i<p_stream->segments.size(); i++) { p_stream->segments[i]->Preload(); b_need_preload |= p_stream->segments[i]->b_ref_external_segments; if ( p_stream->segments[i]->translations.size() && p_stream->segments[i]->translations[0]->codec_id == MATROSKA_CHAPTER_CODEC_DVD && p_stream->segments[i]->families.size() ) b_need_preload = true; } p_segment = p_stream->segments[0]; if( p_segment->cluster == NULL && p_segment->stored_editions.size() == 0 ) { msg_Err( p_demux, "cannot find any cluster or chapter, damaged file ?" ); goto error; } if (b_need_preload && var_InheritBool( p_demux, "mkv-preload-local-dir" )) { msg_Dbg( p_demux, "Preloading local dir" ); /* get the files from the same dir from the same family (based on p_demux->psz_path) */ if ( p_demux->psz_file && !strcmp( p_demux->psz_access, "file" ) ) { // assume it's a regular file // get the directory path s_path = p_demux->psz_file; if (s_path.at(s_path.length() - 1) == DIR_SEP_CHAR) { s_path = s_path.substr(0,s_path.length()-1); } else { if (s_path.find_last_of(DIR_SEP_CHAR) > 0) { s_path = s_path.substr(0,s_path.find_last_of(DIR_SEP_CHAR)); } } DIR *p_src_dir = vlc_opendir(s_path.c_str()); if (p_src_dir != NULL) { const char *psz_file; while ((psz_file = vlc_readdir(p_src_dir)) != NULL) { if (strlen(psz_file) > 4) { s_filename = s_path + DIR_SEP_CHAR + psz_file; #if defined(_WIN32) || defined(__OS2__) if (!strcasecmp(s_filename.c_str(), p_demux->psz_file)) #else if (!s_filename.compare(p_demux->psz_file)) #endif { continue; // don't reuse the original opened file } if (!s_filename.compare(s_filename.length() - 3, 3, "mkv") || !s_filename.compare(s_filename.length() - 3, 3, "mka")) { // test whether this file belongs to our family const uint8_t *p_peek; bool file_ok = false; char *psz_url = vlc_path2uri( s_filename.c_str(), "file" ); stream_t *p_file_stream = vlc_stream_NewURL( p_demux, psz_url ); /* peek the begining */ if( p_file_stream && vlc_stream_Peek( p_file_stream, &p_peek, 4 ) >= 4 && p_peek[0] == 0x1a && p_peek[1] == 0x45 && p_peek[2] == 0xdf && p_peek[3] == 0xa3 ) file_ok = true; if ( file_ok ) { vlc_stream_io_callback *p_file_io = new vlc_stream_io_callback( p_file_stream, true ); EbmlStream *p_estream = new EbmlStream(*p_file_io); p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_estream ); if ( p_stream == NULL ) { msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() ); delete p_estream; delete p_file_io; } else { p_stream->p_io_callback = p_file_io; p_stream->p_estream = p_estream; p_sys->streams.push_back( p_stream ); } } else { if( p_file_stream ) { vlc_stream_Delete( p_file_stream ); } msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() ); } free( psz_url ); } } } closedir( p_src_dir ); } } p_sys->PreloadFamily( *p_segment ); } else if (b_need_preload) msg_Warn( p_demux, "This file references other files, you may want to enable the preload of local directory"); if ( !p_sys->PreloadLinked() || !p_sys->PreparePlayback( *p_sys->p_current_vsegment, 0 ) ) { msg_Err( p_demux, "cannot use the segment" ); goto error; } p_sys->FreeUnused(); p_sys->InitUi(); return VLC_SUCCESS; error: delete p_sys; return VLC_EGENERIC; }
block_t *DirBlock (access_t *p_access) { access_sys_t *p_sys = p_access->p_sys; directory_t *current = p_sys->current; if (p_access->info.b_eof) return NULL; if (p_sys->header) { /* Startup: send the XSPF header */ static const char header[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\" xmlns:vlc=\"http://www.videolan.org/vlc/playlist/ns/0/\">\n" " <trackList>\n"; block_t *block = block_Alloc (sizeof (header) - 1); if (!block) goto fatal; memcpy (block->p_buffer, header, sizeof (header) - 1); p_sys->header = false; return block; } if (current->i >= current->filec) { /* End of directory, go back to parent */ closedir (current->handle); p_sys->current = current->parent; free (current->uri); free (current->filev); #ifndef HAVE_OPENAT free (current->path); #endif free (current); if (p_sys->current == NULL) { /* End of XSPF playlist */ char *footer; int len = asprintf (&footer, " </trackList>\n" " <extension application=\"http://www.videolan.org/" "vlc/playlist/0\">\n" "%s" " </extension>\n" "</playlist>\n", p_sys->xspf_ext ? p_sys->xspf_ext : ""); if (unlikely(len == -1)) goto fatal; block_t *block = block_heap_Alloc (footer, len); p_access->info.b_eof = true; return block; } else { /* This was the end of a "subnode" */ /* Write the ID to the extension */ char *old_xspf_ext = p_sys->xspf_ext; if (old_xspf_ext != NULL && asprintf (&p_sys->xspf_ext, "%s </vlc:node>\n", old_xspf_ext ? old_xspf_ext : "") == -1) p_sys->xspf_ext = NULL; free (old_xspf_ext); } return NULL; } char *entry = current->filev[current->i++]; /* Handle recursion */ if (p_sys->mode != MODE_COLLAPSE) { DIR *handle; #ifdef HAVE_OPENAT int fd = vlc_openat (dirfd (current->handle), entry, O_RDONLY | O_DIRECTORY); if (fd == -1) { if (errno == ENOTDIR) goto notdir; goto skip; /* File cannot be opened... forget it */ } struct stat st; if (fstat (fd, &st) || p_sys->mode == MODE_NONE || has_inode_loop (current, st.st_dev, st.st_ino) || (handle = fdopendir (fd)) == NULL) { close (fd); goto skip; } #else char *path; if (asprintf (&path, "%s/%s", current->path, entry) == -1) goto skip; if ((handle = vlc_opendir (path)) == NULL) goto notdir; if (p_sys->mode == MODE_NONE) goto skip; #endif directory_t *sub = malloc (sizeof (*sub)); if (unlikely(sub == NULL)) { closedir (handle); #ifndef HAVE_OPENAT free (path); #endif goto skip; } sub->parent = current; sub->handle = handle; sub->filec = vlc_loaddir (handle, &sub->filev, visible, p_sys->compar); if (sub->filec < 0) sub->filev = NULL; sub->i = 0; #ifdef HAVE_OPENAT sub->device = st.st_dev; sub->inode = st.st_ino; #else sub->path = path; #endif p_sys->current = sub; char *encoded = encode_URI_component (entry); if (encoded == NULL || (asprintf (&sub->uri, "%s/%s", current->uri, encoded) == -1)) sub->uri = NULL; free (encoded); if (unlikely(sub->uri == NULL)) { free (entry); goto fatal; } /* Add node to XSPF extension */ char *old_xspf_ext = p_sys->xspf_ext; EnsureUTF8 (entry); char *title = convert_xml_special_chars (entry); if (old_xspf_ext != NULL && asprintf (&p_sys->xspf_ext, "%s <vlc:node title=\"%s\">\n", old_xspf_ext, title ? title : "?") == -1) p_sys->xspf_ext = NULL; free (old_xspf_ext); free (title); goto skip; } notdir: /* Skip files with ignored extensions */ if (p_sys->ignored_exts != NULL) { const char *ext = strrchr (entry, '.'); if (ext != NULL) { size_t extlen = strlen (++ext); for (const char *type = p_sys->ignored_exts, *end; type[0]; type = end + 1) { end = strchr (type, ','); if (end == NULL) end = type + strlen (type); if (type + extlen == end && !strncasecmp (ext, type, extlen)) { free (entry); return NULL; } if (*end == '\0') break; } } } char *encoded = encode_URI_component (entry); free (entry); if (encoded == NULL) goto fatal; int len = asprintf (&entry, " <track><location>%s/%s</location>\n" \ " <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n" \ " <vlc:id>%d</vlc:id>\n" \ " </extension>\n" \ " </track>\n", current->uri, encoded, p_sys->i_item_count++); free (encoded); if (len == -1) goto fatal; /* Write the ID to the extension */ char *old_xspf_ext = p_sys->xspf_ext; if (old_xspf_ext != NULL && asprintf (&p_sys->xspf_ext, "%s <vlc:item tid=\"%i\" />\n", old_xspf_ext, p_sys->i_item_count - 1) == -1) p_sys->xspf_ext = NULL; free (old_xspf_ext); block_t *block = block_heap_Alloc (entry, len); if (unlikely(block == NULL)) goto fatal; return block; fatal: p_access->info.b_eof = true; return NULL; skip: free (entry); return NULL; }
int vout_snapshot_SaveImage(char **name, int *sequential, const block_t *image, vlc_object_t *object, const vout_snapshot_save_cfg_t *cfg) { /* */ char *filename; DIR *pathdir = vlc_opendir(cfg->path); if (pathdir != NULL) { /* The use specified a directory path */ closedir(pathdir); /* */ char *prefix = NULL; if (cfg->prefix_fmt) prefix = str_format(object, cfg->prefix_fmt); if (prefix) filename_sanitize(prefix); else { prefix = strdup("vlcsnap-"); if (!prefix) goto error; } if (cfg->is_sequential) { for (int num = cfg->sequence; ; num++) { struct stat st; if (asprintf(&filename, "%s" DIR_SEP "%s%05d.%s", cfg->path, prefix, num, cfg->format) < 0) { free(prefix); goto error; } if (vlc_stat(filename, &st)) { *sequential = num; break; } free(filename); } } else { struct tm curtime; time_t lcurtime = time(NULL) ; if (!localtime_r(&lcurtime, &curtime)) { const unsigned int id = (image->i_pts / 100000) & 0xFFFFFF; msg_Warn(object, "failed to get current time. Falling back to legacy snapshot naming"); if (asprintf(&filename, "%s" DIR_SEP "%s%u.%s", cfg->path, prefix, id, cfg->format) < 0) filename = NULL; } else { /* suffix with the last decimal digit in 10s of seconds resolution * FIXME gni ? */ const int id = (image->i_pts / (100*1000)) & 0xFF; char buffer[128]; if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d-%Hh%Mm%Ss", &curtime)) strcpy(buffer, "error"); if (asprintf(&filename, "%s" DIR_SEP "%s%s%1u.%s", cfg->path, prefix, buffer, id, cfg->format) < 0) filename = NULL; } } free(prefix); } else { /* The user specified a full path name (including file name) */ filename = str_format(object, cfg->path); path_sanitize(filename); } if (!filename) goto error; /* Save the snapshot */ FILE *file = vlc_fopen(filename, "wb"); if (!file) { msg_Err(object, "Failed to open '%s'", filename); free(filename); goto error; } if (fwrite(image->p_buffer, image->i_buffer, 1, file) != 1) { msg_Err(object, "Failed to write to '%s'", filename); fclose(file); free(filename); goto error; } fclose(file); /* */ if (name) *name = filename; else free(filename); return VLC_SUCCESS; error: msg_Err(object, "could not save snapshot"); return VLC_EGENERIC; }
/** * Detect subtitle files. * * When called this function will split up the psz_name string into a * directory, filename and extension. It then opens the directory * in which the file resides and tries to find possible matches of * subtitles files. * * \ingroup Demux * \param p_this the calling \ref input_thread_t * \param psz_path a list of subdirectories (separated by a ',') to look in. * \param psz_name_org the complete filename to base the search on. * \param pp_slaves an initialized input item slave list to append detected subtitles to * \param p_slaves pointer to the size of the slave list * \return VLC_SUCCESS if ok */ int subtitles_Detect( input_thread_t *p_this, char *psz_path, const char *psz_name_org, input_item_slave_t ***ppp_slaves, int *p_slaves ) { int i_fuzzy = var_GetInteger( p_this, "sub-autodetect-fuzzy" ); if ( i_fuzzy == 0 ) return VLC_EGENERIC; int j, i_fname_len; input_item_slave_t **pp_slaves = *ppp_slaves; int i_slaves = *p_slaves; char *f_fname_noext = NULL, *f_fname_trim = NULL; char **subdirs; /* list of subdirectories to look in */ if( !psz_name_org ) return VLC_EGENERIC; char *psz_fname = vlc_uri2path( psz_name_org ); if( !psz_fname ) return VLC_EGENERIC; /* extract filename & dirname from psz_fname */ char *f_dir = strdup( psz_fname ); if( f_dir == 0 ) { free( psz_fname ); return VLC_ENOMEM; } const char *f_fname = strrchr( psz_fname, DIR_SEP_CHAR ); if( !f_fname ) { free( f_dir ); free( psz_fname ); return VLC_EGENERIC; } f_fname++; /* Skip the '/' */ f_dir[f_fname - psz_fname] = 0; /* keep dir separator in f_dir */ i_fname_len = strlen( f_fname ); f_fname_noext = malloc(i_fname_len + 1); f_fname_trim = malloc(i_fname_len + 1 ); if( !f_fname_noext || !f_fname_trim ) { free( f_dir ); free( f_fname_noext ); free( f_fname_trim ); free( psz_fname ); return VLC_ENOMEM; } strcpy_strip_ext( f_fname_noext, f_fname ); strcpy_trim( f_fname_trim, f_fname_noext ); subdirs = paths_to_list( f_dir, psz_path ); for( j = -1; (j == -1) || ( j >= 0 && subdirs != NULL && subdirs[j] != NULL ); j++ ) { const char *psz_dir = (j < 0) ? f_dir : subdirs[j]; if( psz_dir == NULL || ( j >= 0 && !strcmp( psz_dir, f_dir ) ) ) continue; /* parse psz_src dir */ DIR *dir = vlc_opendir( psz_dir ); if( dir == NULL ) continue; msg_Dbg( p_this, "looking for a subtitle file in %s", psz_dir ); const char *psz_name; while( (psz_name = vlc_readdir( dir )) ) { if( psz_name[0] == '.' || !subtitles_Filter( psz_name ) ) continue; char tmp_fname_noext[strlen( psz_name ) + 1]; char tmp_fname_trim[strlen( psz_name ) + 1]; char tmp_fname_ext[strlen( psz_name ) + 1]; const char *tmp; int i_prio = 0; /* retrieve various parts of the filename */ strcpy_strip_ext( tmp_fname_noext, psz_name ); strcpy_get_ext( tmp_fname_ext, psz_name ); strcpy_trim( tmp_fname_trim, tmp_fname_noext ); if( !strcmp( tmp_fname_trim, f_fname_trim ) ) { /* matches the movie name exactly */ i_prio = SLAVE_PRIORITY_MATCH_ALL; } else if( (tmp = strstr( tmp_fname_trim, f_fname_trim )) ) { /* contains the movie name */ tmp += strlen( f_fname_trim ); if( whiteonly( tmp ) ) { /* chars in front of the movie name */ i_prio = SLAVE_PRIORITY_MATCH_RIGHT; } else { /* chars after (and possibly in front of) * the movie name */ i_prio = SLAVE_PRIORITY_MATCH_LEFT; } } else if( j == -1 ) { /* doesn't contain the movie name, prefer files in f_dir over subdirs */ i_prio = SLAVE_PRIORITY_MATCH_NONE; } if( i_prio >= i_fuzzy ) { struct stat st; char *path; size_t i_len = strlen( psz_dir ); const char *psz_format; if ( i_len == 0 ) continue; if( psz_dir[i_len - 1] == DIR_SEP_CHAR ) psz_format = "%s%s"; else psz_format = "%s"DIR_SEP"%s"; if( asprintf( &path, psz_format, psz_dir, psz_name ) < 0 ) continue; if( strcmp( path, psz_fname ) && vlc_stat( path, &st ) == 0 && S_ISREG( st.st_mode ) ) { msg_Dbg( p_this, "autodetected subtitle: %s with priority %d", path, i_prio ); char *psz_uri = vlc_path2uri( path, NULL ); input_item_slave_t *p_sub = psz_uri != NULL ? input_item_slave_New( psz_uri, SLAVE_TYPE_SPU, i_prio ) : NULL; if( p_sub ) { p_sub->b_forced = true; INSERT_ELEM( pp_slaves, i_slaves, i_slaves, p_sub ); } free( psz_uri ); } free( path ); } } closedir( dir ); } if( subdirs ) { for( j = 0; subdirs[j]; j++ ) free( subdirs[j] ); free( subdirs ); } free( f_dir ); free( f_fname_trim ); free( f_fname_noext ); free( psz_fname ); for( int i = 0; i < i_slaves; i++ ) { input_item_slave_t *p_sub = pp_slaves[i]; bool b_reject = false; char *psz_ext = strrchr( p_sub->psz_uri, '.' ); if( !psz_ext ) continue; psz_ext++; if( !strcasecmp( psz_ext, "sub" ) ) { for( int j = 0; j < i_slaves; j++ ) { input_item_slave_t *p_sub_inner = pp_slaves[j]; /* A slave can be null if it's already rejected */ if( p_sub_inner == NULL ) continue; /* check that the filenames without extension match */ if( strncasecmp( p_sub->psz_uri, p_sub_inner->psz_uri, strlen( p_sub->psz_uri ) - 3 ) ) continue; char *psz_ext_inner = strrchr( p_sub_inner->psz_uri, '.' ); if( !psz_ext_inner ) continue; psz_ext_inner++; /* check that we have an idx file */ if( !strcasecmp( psz_ext_inner, "idx" ) ) { b_reject = true; break; } } } else if( !strcasecmp( psz_ext, "cdg" ) ) { if( p_sub->i_priority < SLAVE_PRIORITY_MATCH_ALL ) b_reject = true; } if( b_reject ) { pp_slaves[i] = NULL; input_item_slave_Delete( p_sub ); } } /* Sort alphabetically */ if( i_slaves > 0 ) qsort( pp_slaves, i_slaves, sizeof (input_item_slave_t*), slave_strcmp ); *ppp_slaves = pp_slaves; /* in case of realloc */ *p_slaves = i_slaves; return VLC_SUCCESS; }