file.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:12k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * file.c: file input (file: access plug-in)
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2006 the VideoLAN team
  5.  * Copyright © 2006-2007 Rémi Denis-Courmont
  6.  * $Id: ad111cb458c35af33a8accb6c172dc4ae7ffad13 $
  7.  *
  8.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  9.  *          Rémi Denis-Courmont <rem # videolan # org>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  24.  *****************************************************************************/
  25. /*****************************************************************************
  26.  * Preamble
  27.  *****************************************************************************/
  28. #ifdef HAVE_CONFIG_H
  29. # include "config.h"
  30. #endif
  31. #include <vlc_common.h>
  32. #include <vlc_plugin.h>
  33. #include <vlc_input.h>
  34. #include <vlc_access.h>
  35. #include <vlc_dialog.h>
  36. #include <assert.h>
  37. #include <errno.h>
  38. #ifdef HAVE_SYS_TYPES_H
  39. #   include <sys/types.h>
  40. #endif
  41. #ifdef HAVE_SYS_STAT_H
  42. #   include <sys/stat.h>
  43. #endif
  44. #ifdef HAVE_FCNTL_H
  45. #   include <fcntl.h>
  46. #endif
  47. #if defined (__linux__)
  48. #   include <sys/vfs.h>
  49. #   include <linux/magic.h>
  50. #elif defined (HAVE_SYS_MOUNT_H)
  51. #   include <sys/param.h>
  52. #   include <sys/mount.h>
  53. #endif
  54. #if defined( WIN32 )
  55. #   include <io.h>
  56. #   include <ctype.h>
  57. #   include <shlwapi.h>
  58. #else
  59. #   include <unistd.h>
  60. #   include <poll.h>
  61. #endif
  62. #if defined( WIN32 ) && !defined( UNDER_CE )
  63. #   ifdef lseek
  64. #      undef lseek
  65. #   endif
  66. #   define lseek _lseeki64
  67. #elif defined( UNDER_CE )
  68. /* FIXME the commandline on wince is a mess */
  69. # define dup(a) -1
  70. # define PathIsNetworkPathW(wpath) (! wcsncmp(wpath, L"\\", 2))
  71. #endif
  72. #include <vlc_charset.h>
  73. /*****************************************************************************
  74.  * Module descriptor
  75.  *****************************************************************************/
  76. static int  Open ( vlc_object_t * );
  77. static void Close( vlc_object_t * );
  78. #define CACHING_TEXT N_("Caching value in ms")
  79. #define CACHING_LONGTEXT N_( 
  80.     "Caching value for files. This " 
  81.     "value should be set in milliseconds." )
  82. vlc_module_begin ()
  83.     set_description( N_("File input") )
  84.     set_shortname( N_("File") )
  85.     set_category( CAT_INPUT )
  86.     set_subcategory( SUBCAT_INPUT_ACCESS )
  87.     add_integer( "file-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, true )
  88.         change_safe()
  89.     add_obsolete_string( "file-cat" )
  90.     set_capability( "access", 50 )
  91.     add_shortcut( "file" )
  92.     add_shortcut( "fd" )
  93.     add_shortcut( "stream" )
  94.     set_callbacks( Open, Close )
  95. vlc_module_end ()
  96. /*****************************************************************************
  97.  * Exported prototypes
  98.  *****************************************************************************/
  99. static int  Seek( access_t *, int64_t );
  100. static int  NoSeek( access_t *, int64_t );
  101. static ssize_t Read( access_t *, uint8_t *, size_t );
  102. static int  Control( access_t *, int, va_list );
  103. static int  open_file( access_t *, const char * );
  104. struct access_sys_t
  105. {
  106.     unsigned int i_nb_reads;
  107.     int fd;
  108.     /* */
  109.     bool b_pace_control;
  110. };
  111. static bool IsRemote (int fd)
  112. {
  113. #ifdef HAVE_FSTATFS
  114.     struct statfs stf;
  115.     if (fstatfs (fd, &stf))
  116.         return false;
  117. #if defined(MNT_LOCAL)
  118.     return !(stf.f_flags & MNT_LOCAL);
  119. #elif defined (__linux__)
  120.     switch (stf.f_type)
  121.     {
  122.         case AFS_SUPER_MAGIC:
  123.         case CODA_SUPER_MAGIC:
  124.         case NCP_SUPER_MAGIC:
  125.         case NFS_SUPER_MAGIC:
  126.         case SMB_SUPER_MAGIC:
  127.         case 0xFF534D42 /*CIFS_MAGIC_NUMBER*/:
  128.             return true;
  129.     }
  130.     return false;
  131. #endif
  132. #else /* !HAVE_FSTATFS */
  133.     return false;
  134. #endif
  135. }
  136. /*****************************************************************************
  137.  * Open: open the file
  138.  *****************************************************************************/
  139. static int Open( vlc_object_t *p_this )
  140. {
  141.     access_t     *p_access = (access_t*)p_this;
  142.     access_sys_t *p_sys;
  143. #ifdef WIN32
  144.     wchar_t wpath[MAX_PATH+1];
  145.     bool is_remote = false;
  146. #endif
  147.     /* Update default_pts to a suitable value for file access */
  148.     var_Create( p_access, "file-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  149.     STANDARD_READ_ACCESS_INIT;
  150.     p_sys->i_nb_reads = 0;
  151.     p_sys->b_pace_control = true;
  152.     /* Open file */
  153.     int fd = -1;
  154.     if (!strcasecmp (p_access->psz_access, "fd"))
  155.         fd = dup (atoi (p_access->psz_path));
  156.     else if (!strcmp (p_access->psz_path, "-"))
  157.         fd = dup (0);
  158.     else
  159.     {
  160.         msg_Dbg (p_access, "opening file `%s'", p_access->psz_path);
  161.         fd = open_file (p_access, p_access->psz_path);
  162. #ifdef WIN32
  163.         if (MultiByteToWideChar (CP_UTF8, 0, p_access->psz_path, -1,
  164.                                  wpath, MAX_PATH)
  165.          && PathIsNetworkPathW (wpath))
  166.             is_remote = true;
  167. # define IsRemote( fd ) ((void)fd, is_remote)
  168. #endif
  169.     }
  170.     if (fd == -1)
  171.         goto error;
  172. #ifdef HAVE_SYS_STAT_H
  173.     struct stat st;
  174.     if (fstat (fd, &st))
  175.     {
  176.         msg_Err (p_access, "failed to read (%m)");
  177.         goto error;
  178.     }
  179.     /* Directories can be opened and read from, but only readdir() knows
  180.      * how to parse the data. The directory plugin will do it. */
  181.     if (S_ISDIR (st.st_mode))
  182.     {
  183.         msg_Dbg (p_access, "ignoring directory");
  184.         goto error;
  185.     }
  186.     if (S_ISREG (st.st_mode))
  187.         p_access->info.i_size = st.st_size;
  188.     else if (!S_ISBLK (st.st_mode))
  189.     {
  190.         p_access->pf_seek = NoSeek;
  191.         p_sys->b_pace_control = strcasecmp (p_access->psz_access, "stream");
  192.     }
  193. #else
  194. # warning File size not known!
  195. #endif
  196.     if (IsRemote(fd))
  197.     {
  198.         int i_cache = var_GetInteger (p_access, "file-caching") + 700;
  199.         var_SetInteger (p_access, "file-caching", i_cache);
  200.         msg_Warn (p_access, "Opening remote file, increasing cache: %d",
  201.                   i_cache);
  202.     }
  203.     p_sys->fd = fd;
  204.     return VLC_SUCCESS;
  205. error:
  206.     if (fd != -1)
  207.         close (fd);
  208.     free (p_sys);
  209.     return VLC_EGENERIC;
  210. }
  211. /*****************************************************************************
  212.  * Close: close the target
  213.  *****************************************************************************/
  214. static void Close (vlc_object_t * p_this)
  215. {
  216.     access_t     *p_access = (access_t*)p_this;
  217.     access_sys_t *p_sys = p_access->p_sys;
  218.     close (p_sys->fd);
  219.     free (p_sys);
  220. }
  221. #include <vlc_network.h>
  222. /*****************************************************************************
  223.  * Read: standard read on a file descriptor.
  224.  *****************************************************************************/
  225. static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
  226. {
  227.     access_sys_t *p_sys = p_access->p_sys;
  228.     int fd = p_sys->fd;
  229.     ssize_t i_ret;
  230. #ifndef WIN32
  231.     if (p_access->pf_seek == NoSeek)
  232.         i_ret = net_Read (p_access, fd, NULL, p_buffer, i_len, false);
  233.     else
  234. #endif
  235.         i_ret = read (fd, p_buffer, i_len);
  236.     if( i_ret < 0 )
  237.     {
  238.         switch (errno)
  239.         {
  240.             case EINTR:
  241.             case EAGAIN:
  242.                 break;
  243.             default:
  244.                 msg_Err (p_access, "failed to read (%m)");
  245.                 dialog_Fatal (p_access, _("File reading failed"), "%s",
  246.                               _("VLC could not read the file."));
  247.                 p_access->info.b_eof = true;
  248.                 return 0;
  249.         }
  250.     }
  251.     else if( i_ret > 0 )
  252.         p_access->info.i_pos += i_ret;
  253.     else
  254.         p_access->info.b_eof = true;
  255.     p_sys->i_nb_reads++;
  256. #ifdef HAVE_SYS_STAT_H
  257.     if ((p_access->info.i_size && !(p_sys->i_nb_reads % INPUT_FSTAT_NB_READS))
  258.      || (p_access->info.i_pos > p_access->info.i_size))
  259.     {
  260.         struct stat st;
  261.         if ((fstat (fd, &st) == 0)
  262.          && (p_access->info.i_size != st.st_size))
  263.         {
  264.             p_access->info.i_size = st.st_size;
  265.             p_access->info.i_update |= INPUT_UPDATE_SIZE;
  266.         }
  267.     }
  268. #endif
  269.     return i_ret;
  270. }
  271. /*****************************************************************************
  272.  * Seek: seek to a specific location in a file
  273.  *****************************************************************************/
  274. static int Seek (access_t *p_access, int64_t i_pos)
  275. {
  276.     p_access->info.i_pos = i_pos;
  277.     p_access->info.b_eof = false;
  278.     lseek (p_access->p_sys->fd, i_pos, SEEK_SET);
  279.     return VLC_SUCCESS;
  280. }
  281. static int NoSeek (access_t *p_access, int64_t i_pos)
  282. {
  283.     /* assert(0); ?? */
  284.     (void) p_access; (void) i_pos;
  285.     return VLC_EGENERIC;
  286. }
  287. /*****************************************************************************
  288.  * Control:
  289.  *****************************************************************************/
  290. static int Control( access_t *p_access, int i_query, va_list args )
  291. {
  292.     access_sys_t *p_sys = p_access->p_sys;
  293.     bool    *pb_bool;
  294.     int64_t *pi_64;
  295.     switch( i_query )
  296.     {
  297.         /* */
  298.         case ACCESS_CAN_SEEK:
  299.         case ACCESS_CAN_FASTSEEK:
  300.             pb_bool = (bool*)va_arg( args, bool* );
  301.             *pb_bool = (p_access->pf_seek != NoSeek);
  302.             break;
  303.         case ACCESS_CAN_PAUSE:
  304.         case ACCESS_CAN_CONTROL_PACE:
  305.             pb_bool = (bool*)va_arg( args, bool* );
  306.             *pb_bool = p_sys->b_pace_control;
  307.             break;
  308.         /* */
  309.         case ACCESS_GET_PTS_DELAY:
  310.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  311.             *pi_64 = var_GetInteger( p_access, "file-caching" ) * INT64_C(1000);
  312.             break;
  313.         /* */
  314.         case ACCESS_SET_PAUSE_STATE:
  315.             /* Nothing to do */
  316.             break;
  317.         case ACCESS_GET_TITLE_INFO:
  318.         case ACCESS_SET_TITLE:
  319.         case ACCESS_SET_SEEKPOINT:
  320.         case ACCESS_SET_PRIVATE_ID_STATE:
  321.         case ACCESS_GET_META:
  322.         case ACCESS_GET_PRIVATE_ID_STATE:
  323.         case ACCESS_GET_CONTENT_TYPE:
  324.             return VLC_EGENERIC;
  325.         default:
  326.             msg_Warn( p_access, "unimplemented query %d in control", i_query );
  327.             return VLC_EGENERIC;
  328.     }
  329.     return VLC_SUCCESS;
  330. }
  331. /*****************************************************************************
  332.  * open_file: Opens a specific file
  333.  *****************************************************************************/
  334. static int open_file (access_t *p_access, const char *path)
  335. {
  336. #if defined(WIN32)
  337.     if (!strcasecmp (p_access->psz_access, "file")
  338.       && ('/' == path[0]) && isalpha (path[1])
  339.       && (':' == path[2]) && ('/' == path[3]))
  340.         /* Explorer can open path such as file:/C:/ or file:///C:/
  341.          * hence remove leading / if found */
  342.         path++;
  343. #endif
  344.     int fd = utf8_open (path, O_RDONLY | O_NONBLOCK /* O_LARGEFILE*/, 0666);
  345.     if (fd == -1)
  346.     {
  347.         msg_Err (p_access, "cannot open file %s (%m)", path);
  348.         dialog_Fatal (p_access, _("File reading failed"),
  349.                       _("VLC could not open the file "%s"."), path);
  350.         return -1;
  351.     }
  352. #if defined(HAVE_FCNTL)
  353.     /* We'd rather use any available memory for reading ahead
  354.      * than for caching what we've already seen/heard */
  355. # if defined(F_RDAHEAD)
  356.     fcntl (fd, F_RDAHEAD, 1);
  357. # endif
  358. # if defined(F_NOCACHE)
  359.     fcntl (fd, F_NOCACHE, 1);
  360. # endif
  361. #endif
  362.     return fd;
  363. }