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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * mtp.c: mtp input (mtp: access plug-in)
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2006 the VideoLAN team
  5.  * Copyright © 2006-2008 Rémi Denis-Courmont
  6.  *
  7.  * Authors: Fabio Ritrovato <exsephiroth87@gmail.com>
  8.  * Original file.c: 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. #include <unistd.h>
  48. #include <poll.h>
  49. #include <vlc_charset.h>
  50. #include "libmtp.h"
  51. /*****************************************************************************
  52.  * Module descriptor
  53.  *****************************************************************************/
  54. static int  Open ( vlc_object_t * );
  55. static void Close( vlc_object_t * );
  56. #define CACHING_TEXT N_("Caching value in ms")
  57. #define CACHING_LONGTEXT N_( 
  58.     "Caching value for files. This " 
  59.     "value should be set in milliseconds." )
  60. vlc_module_begin()
  61.     set_description( N_("MTP input") )
  62.     set_shortname( N_("MTP") )
  63.     set_category( CAT_INPUT )
  64.     set_subcategory( SUBCAT_INPUT_ACCESS )
  65.     set_capability( "access", 0 )
  66.     add_shortcut( "mtp" )
  67.     set_callbacks( Open, Close )
  68. vlc_module_end()
  69. /*****************************************************************************
  70.  * Exported prototypes
  71.  *****************************************************************************/
  72. static int  Seek( access_t *, int64_t );
  73. static ssize_t Read( access_t *, uint8_t *, size_t );
  74. static int  Control( access_t *, int, va_list );
  75. static int  open_file( access_t *, const char * );
  76. struct access_sys_t
  77. {
  78.     unsigned int i_nb_reads;
  79.     int fd;
  80. };
  81. /*****************************************************************************
  82.  * Open: open the file
  83.  *****************************************************************************/
  84. static int Open( vlc_object_t *p_this )
  85. {
  86.     access_t     *p_access = ( access_t* )p_this;
  87.     access_sys_t *p_sys;
  88.     uint32_t i_bus;
  89.     uint8_t i_dev;
  90.     uint16_t i_product_id;
  91.     int i_track_id;
  92.     LIBMTP_raw_device_t *p_rawdevices;
  93.     LIBMTP_mtpdevice_t *p_device;
  94.     int i_numrawdevices;
  95.     int i_ret;
  96.     /* Update default_pts to a suitable value for file access */
  97.     var_Create( p_access, "file-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
  98.     if( sscanf( p_access->psz_path, "%"SCNu32":%"SCNu8":%"SCNu16":%d", &i_bus,
  99.                 &i_dev, &i_product_id, &i_track_id ) != 4 )
  100.         return VLC_EGENERIC;
  101.     i_ret = LIBMTP_Detect_Raw_Devices( &p_rawdevices, &i_numrawdevices );
  102.     if( i_ret != 0 || i_numrawdevices <= 0 || !p_rawdevices )
  103.         return VLC_EGENERIC;
  104.     for( int i = 0; i < i_numrawdevices; i++ )
  105.     {
  106.         if( i_bus == p_rawdevices[i].bus_location &&
  107.             i_dev == p_rawdevices[i].devnum &&
  108.             i_product_id == p_rawdevices[i].device_entry.product_id )
  109.         {
  110.             if( ( p_device = LIBMTP_Open_Raw_Device( &p_rawdevices[i] )
  111.                 ) != NULL )
  112.             {
  113.                 free( p_access->psz_path );
  114.                 if( ( p_access->psz_path = tempnam( NULL, "vlc" ) ) == NULL )
  115.                 {
  116.                     LIBMTP_Release_Device( p_device );
  117.                     free( p_rawdevices );
  118.                     return VLC_ENOMEM;
  119.                 }
  120.                 else
  121.                 {
  122.                     msg_Dbg( p_access, "About to write %s", p_access->psz_path );
  123.                     LIBMTP_Get_File_To_File( p_device, i_track_id,
  124.                                              p_access->psz_path, NULL, NULL );
  125.                     LIBMTP_Release_Device( p_device );
  126.                     i = i_numrawdevices;
  127.                 }
  128.             }
  129.             else
  130.             {
  131.                 free( p_rawdevices );
  132.                 return VLC_EGENERIC;
  133.             }
  134.         }
  135.     }
  136.     free( p_rawdevices );
  137.     STANDARD_READ_ACCESS_INIT;
  138.     p_sys->i_nb_reads = 0;
  139.     int fd = p_sys->fd = -1;
  140.     /* Open file */
  141.     msg_Dbg( p_access, "opening file `%s'", p_access->psz_path );
  142.     fd = open_file( p_access, p_access->psz_path );
  143.     if( fd == -1 )
  144.     {
  145.         free( p_sys );
  146.         return VLC_EGENERIC;
  147.     }
  148.     p_sys->fd = fd;
  149. #ifdef HAVE_SYS_STAT_H
  150.     struct stat st;
  151.     if( fstat( fd, &st ) )
  152.         msg_Err( p_access, "fstat(%d): %m", fd );
  153.     p_access->info.i_size = st.st_size;
  154. #else
  155. # warning File size not known!
  156. #endif
  157.     return VLC_SUCCESS;
  158. }
  159. /*****************************************************************************
  160.  * Close: close the target
  161.  *****************************************************************************/
  162. static void Close( vlc_object_t * p_this )
  163. {
  164.     access_t     *p_access = ( access_t* )p_this;
  165.     access_sys_t *p_sys = p_access->p_sys;
  166.     close ( p_sys->fd );
  167.     if( utf8_unlink( p_access->psz_path ) != 0 )
  168.         msg_Err( p_access, "Error deleting file %s, %m", p_access->psz_path );
  169.     free( p_sys );
  170. }
  171. /*****************************************************************************
  172.  * Read: standard read on a file descriptor.
  173.  *****************************************************************************/
  174. static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
  175. {
  176.     access_sys_t *p_sys = p_access->p_sys;
  177.     ssize_t i_ret;
  178.     int fd = p_sys->fd;
  179.     i_ret = read( fd, p_buffer, i_len );
  180.     if( i_ret < 0 )
  181.     {
  182.         switch( errno )
  183.         {
  184.             case EINTR:
  185.             case EAGAIN:
  186.                 break;
  187.             default:
  188.                 msg_Err( p_access, "read failed (%m)" );
  189.                 dialog_Fatal( p_access, _( "File reading failed" ), "%s",
  190.                                 _( "VLC could not read the file." ) );
  191.                 p_access->info.b_eof = true;
  192.                 return 0;
  193.         }
  194.     }
  195.     else if( i_ret > 0 )
  196.         p_access->info.i_pos += i_ret;
  197.     else
  198.         p_access->info.b_eof = true;
  199.     p_sys->i_nb_reads++;
  200.     return i_ret;
  201. }
  202. /*****************************************************************************
  203.  * Seek: seek to a specific location in a file
  204.  *****************************************************************************/
  205. static int Seek( access_t *p_access, int64_t i_pos )
  206. {
  207.     p_access->info.i_pos = i_pos;
  208.     p_access->info.b_eof = false;
  209.     lseek( p_access->p_sys->fd, i_pos, SEEK_SET );
  210.     return VLC_SUCCESS;
  211. }
  212. /*****************************************************************************
  213.  * Control:
  214.  *****************************************************************************/
  215. static int Control( access_t *p_access, int i_query, va_list args )
  216. {
  217.     bool   *pb_bool;
  218.     int64_t      *pi_64;
  219.     switch( i_query )
  220.     {
  221.         /* */
  222.         case ACCESS_CAN_SEEK:
  223.         case ACCESS_CAN_FASTSEEK:
  224.             pb_bool = ( bool* )va_arg( args, bool* );
  225.             *pb_bool = true;
  226.             break;
  227.         case ACCESS_CAN_PAUSE:
  228.         case ACCESS_CAN_CONTROL_PACE:
  229.             pb_bool = ( bool* )va_arg( args, bool* );
  230.             *pb_bool = true;
  231.             break;
  232.         case ACCESS_GET_PTS_DELAY:
  233.             pi_64 = ( int64_t* )va_arg( args, int64_t * );
  234.             *pi_64 = var_GetInteger( p_access, "file-caching" ) * INT64_C( 1000 );
  235.             break;
  236.         /* */
  237.         case ACCESS_SET_PAUSE_STATE:
  238.             /* Nothing to do */
  239.             break;
  240.         case ACCESS_GET_TITLE_INFO:
  241.         case ACCESS_SET_TITLE:
  242.         case ACCESS_SET_SEEKPOINT:
  243.         case ACCESS_SET_PRIVATE_ID_STATE:
  244.         case ACCESS_GET_META:
  245.         case ACCESS_GET_PRIVATE_ID_STATE:
  246.         case ACCESS_GET_CONTENT_TYPE:
  247.             return VLC_EGENERIC;
  248.         default:
  249.             msg_Warn( p_access, "unimplemented query %d in control", i_query );
  250.             return VLC_EGENERIC;
  251.     }
  252.     return VLC_SUCCESS;
  253. }
  254. /*****************************************************************************
  255.  * open_file: Opens a specific file
  256.  *****************************************************************************/
  257. static int open_file( access_t *p_access, const char *path )
  258. {
  259.     int fd = utf8_open( path, O_RDONLY | O_NONBLOCK /* O_LARGEFILE*/, 0666 );
  260.     if( fd == -1 )
  261.     {
  262.         msg_Err( p_access, "cannot open file %s (%m)", path );
  263.         dialog_Fatal( p_access, _( "File reading failed" ),
  264.                         _( "VLC could not open the file "%s"." ), path );
  265.         return -1;
  266.     }
  267. #if defined( HAVE_FCNTL )
  268.     fcntl( fd, F_SETFD, fcntl( fd, F_GETFD ) | FD_CLOEXEC );
  269.     /* We'd rather use any available memory for reading ahead
  270.      * than for caching what we've already seen/heard */
  271. # if defined( F_RDAHEAD )
  272.     fcntl( fd, F_RDAHEAD, 1 );
  273. # endif
  274. # if defined( F_NOCACHE )
  275.     fcntl( fd, F_NOCACHE, 1 );
  276. # endif
  277. #endif
  278.     return fd;
  279. }