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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * intf_eject.c: CD/DVD-ROM ejection handling functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2004 the VideoLAN team
  5.  * $Id: 87b9f7c5089fff2bb5625d947c7032e99216c6ff $
  6.  *
  7.  * Authors: Julien Blache <jb@technologeek.org> for the Linux part
  8.  *                with code taken from the Linux "eject" command
  9.  *          Jon Lech Johansen <jon-vl@nanocrew.net> for Darwin
  10.  *          Gildas Bazin <gbazin@netcourrier.com> for Win32
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  25.  *****************************************************************************/
  26. /**
  27.  *  file
  28.  *  This file contain functions to eject CD and DVD drives
  29.  */
  30. #ifdef HAVE_CONFIG_H
  31. # include "config.h"
  32. #endif
  33. #include <vlc_common.h>
  34. #ifdef HAVE_UNISTD_H
  35. #    include <unistd.h>
  36. #endif
  37. #ifdef HAVE_FCNTL_H
  38. #   include <fcntl.h>
  39. #endif
  40. #ifdef HAVE_DVD_H
  41. #   include <dvd.h>
  42. #endif
  43. #if defined(__linux__) && defined(HAVE_LINUX_VERSION_H)
  44. #   include <linux/version.h>
  45.     /* handy macro found in 2.1 kernels, but not in older ones */
  46. #   ifndef KERNEL_VERSION
  47. #       define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
  48. #   endif
  49. #   include <sys/types.h>
  50. #   include <sys/stat.h>
  51. #   include <sys/ioctl.h>
  52. #   include <sys/ioctl.h>
  53. #   include <sys/mount.h>
  54. #   include <linux/cdrom.h>
  55. #   if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
  56. #       include <linux/ucdrom.h>
  57. #   endif
  58. #   include <scsi/scsi.h>
  59. #   include <scsi/sg.h>
  60. #   include <scsi/scsi_ioctl.h>
  61. #endif
  62. #if defined( WIN32 ) && !defined( UNDER_CE )
  63. #   include <mmsystem.h>
  64. #endif
  65. #include <vlc_interface.h>
  66. /*****************************************************************************
  67.  * Local prototypes
  68.  *****************************************************************************/
  69. #if defined(__linux__) && defined(HAVE_LINUX_VERSION_H)
  70. static int EjectSCSI ( int i_fd );
  71. #endif
  72. /*****************************************************************************
  73.  * intf_Eject: eject the CDRom
  74.  *****************************************************************************
  75.  * returns 0 on success
  76.  * returns 1 on failure
  77.  * returns -1 if not implemented
  78.  *****************************************************************************/
  79. /**
  80.  * brief Ejects the CD /DVD
  81.  * ingroup vlc_interface
  82.  * param p_this the calling vlc_object_t
  83.  * param psz_device the CD/DVD to eject
  84.  * return 0 on success, 1 on failure, -1 if not implemented
  85.  */
  86. int __intf_Eject( vlc_object_t *p_this, const char *psz_device )
  87. {
  88.     VLC_UNUSED(p_this);
  89.     int i_ret = VLC_SUCCESS;
  90. #ifdef __APPLE__
  91.     FILE *p_eject;
  92.     char *psz_disk;
  93.     char sz_cmd[32];
  94.     /*
  95.      * The only way to cleanly unmount the disc under MacOS X
  96.      * is to use the 'disktool' command line utility. It uses
  97.      * the non-public Disk Arbitration API, which can not be
  98.      * used by Cocoa or Carbon applications.
  99.      */
  100.     if( ( psz_disk = (char *)strstr( psz_device, "disk" ) ) != NULL &&
  101.         strlen( psz_disk ) > 4 )
  102.     {
  103. #define EJECT_CMD "/usr/sbin/disktool -e %s 0"
  104.         snprintf( sz_cmd, sizeof(sz_cmd), EJECT_CMD, psz_disk );
  105. #undef EJECT_CMD
  106.         if( ( p_eject = popen( sz_cmd, "r" ) ) != NULL )
  107.         {
  108.             char psz_result[0x200];
  109.             i_ret = fread( psz_result, 1, sizeof(psz_result) - 1, p_eject );
  110.             if( i_ret == 0 && ferror( p_eject ) != 0 )
  111.             {
  112.                 pclose( p_eject );
  113.                 return VLC_EGENERIC;
  114.             }
  115.             pclose( p_eject );
  116.             psz_result[ i_ret ] = 0;
  117.             if( strstr( psz_result, "Disk Ejected" ) != NULL )
  118.             {
  119.                 return VLC_SUCCESS;
  120.             }
  121.         }
  122.     }
  123.     return VLC_EGENERIC;
  124. #elif defined(UNDER_CE)
  125.     msg_Warn( p_this, "CD-Rom ejection unsupported on this platform" );
  126.     return i_ret;
  127. #elif defined(WIN32)
  128.     MCI_OPEN_PARMS op;
  129.     MCI_STATUS_PARMS st;
  130.     DWORD i_flags;
  131.     char psz_drive[4];
  132.     memset( &op, 0, sizeof(MCI_OPEN_PARMS) );
  133.     op.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_CD_AUDIO;
  134.     strcpy( psz_drive, "X:" );
  135.     psz_drive[0] = psz_device[0];
  136.     op.lpstrElementName = psz_drive;
  137.     /* Set the flags for the device type */
  138.     i_flags = MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID |
  139.               MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE;
  140.     if( !mciSendCommand( 0, MCI_OPEN, i_flags, (unsigned long)&op ) )
  141.     {
  142.         st.dwItem = MCI_STATUS_READY;
  143.         /* Eject disc */
  144.         i_ret = mciSendCommand( op.wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, 0 );
  145.         /* Release access to the device */
  146.         mciSendCommand( op.wDeviceID, MCI_CLOSE, MCI_WAIT, 0 );
  147.     }
  148.     else i_ret = VLC_EGENERIC;
  149.     return i_ret;
  150. #else   /* WIN32 */
  151.     int i_fd;
  152.     /* This code could be extended to support CD/DVD-ROM chargers */
  153.     i_fd = open( psz_device, O_RDONLY | O_NONBLOCK );
  154.     if( i_fd == -1 )
  155.     {
  156.         msg_Err( p_this, "could not open device %s", psz_device );
  157.         return VLC_EGENERIC;
  158.     }
  159. #if defined(__linux__) && defined(HAVE_LINUX_VERSION_H)
  160.     /* Try a simple ATAPI eject */
  161.     i_ret = ioctl( i_fd, CDROMEJECT, 0 );
  162.     if( i_ret != 0 )
  163.     {
  164.         i_ret = EjectSCSI( i_fd );
  165.     }
  166.     if( i_ret != 0 )
  167.     {
  168.         msg_Err( p_this, "could not eject %s", psz_device );
  169.     }
  170. #elif defined (HAVE_DVD_H)
  171.     i_ret = ioctl( i_fd, CDROMEJECT, 0 );
  172. #else
  173.     msg_Warn( p_this, "CD-ROM ejection unsupported on this platform" );
  174.     i_ret = -1;
  175. #endif
  176.     close( i_fd );
  177.     return i_ret;
  178. #endif
  179. }
  180. /* The following functions are local */
  181. #if defined(__linux__) && defined(HAVE_LINUX_VERSION_H)
  182. /*****************************************************************************
  183.  * Eject using SCSI commands. Return 0 if successful
  184.  *****************************************************************************/
  185. /**
  186.  * brief Ejects the CD /DVD using SCSI commands
  187.  * ingroup vlc_interface
  188.  * This function is local
  189.  * param i_fd a device nummber
  190.  * return 0 on success, VLC_EGENERIC on failure
  191.  */
  192. static int EjectSCSI( int i_fd )
  193. {
  194.     int i_status;
  195.     struct sdata
  196.     {
  197.         int  inlen;
  198.         int  outlen;
  199.         char cmd[256];
  200.     } scsi_cmd;
  201.     scsi_cmd.inlen  = 0;
  202.     scsi_cmd.outlen = 0;
  203.     scsi_cmd.cmd[0] = ALLOW_MEDIUM_REMOVAL;
  204.     scsi_cmd.cmd[1] = 0;
  205.     scsi_cmd.cmd[2] = 0;
  206.     scsi_cmd.cmd[3] = 0;
  207.     scsi_cmd.cmd[4] = 0;
  208.     scsi_cmd.cmd[5] = 0;
  209.     i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
  210.     if( i_status != 0 )
  211.     {
  212.         return VLC_EGENERIC;
  213.     }
  214.     scsi_cmd.inlen  = 0;
  215.     scsi_cmd.outlen = 0;
  216.     scsi_cmd.cmd[0] = START_STOP;
  217.     scsi_cmd.cmd[1] = 0;
  218.     scsi_cmd.cmd[2] = 0;
  219.     scsi_cmd.cmd[3] = 0;
  220.     scsi_cmd.cmd[4] = 1;
  221.     scsi_cmd.cmd[5] = 0;
  222.     i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
  223.     if( i_status != 0 )
  224.     {
  225.         return VLC_EGENERIC;
  226.     }
  227.     scsi_cmd.inlen  = 0;
  228.     scsi_cmd.outlen = 0;
  229.     scsi_cmd.cmd[0] = START_STOP;
  230.     scsi_cmd.cmd[1] = 0;
  231.     scsi_cmd.cmd[2] = 0;
  232.     scsi_cmd.cmd[3] = 0;
  233.     scsi_cmd.cmd[4] = 2;
  234.     scsi_cmd.cmd[5] = 0;
  235.     i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
  236.     if( i_status != 0 )
  237.     {
  238.         return VLC_EGENERIC;
  239.     }
  240.     /* Force kernel to reread partition table when new disc inserted */
  241.     i_status = ioctl( i_fd, BLKRRPART );
  242.     return i_status;
  243. }
  244. #endif