intf_eject.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:8k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * intf_eject.c: CD/DVD-ROM ejection handling functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2004 VideoLAN
  5.  * $Id: intf_eject.c 8905 2004-10-04 13:34:42Z gbazin $
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  25.  *****************************************************************************/
  26. /**
  27.  *  file
  28.  *  This file contain functions to eject CD and DVD drives
  29.  */
  30. #include <vlc/vlc.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #ifdef HAVE_UNISTD_H
  34. #    include <unistd.h>
  35. #endif
  36. #include <string.h>
  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(SYS_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. /*****************************************************************************
  66.  * Local prototypes
  67.  *****************************************************************************/
  68. #if defined(SYS_LINUX) && defined(HAVE_LINUX_VERSION_H)
  69. static int EjectSCSI ( int i_fd );
  70. #endif
  71. /*****************************************************************************
  72.  * intf_Eject: eject the CDRom
  73.  *****************************************************************************
  74.  * returns 0 on success
  75.  * returns 1 on failure
  76.  * returns -1 if not implemented
  77.  *****************************************************************************/
  78. /**
  79.  * brief Ejects the CD /DVD
  80.  * ingroup vlc_interface
  81.  * param p_this the calling vlc_object_t
  82.  * param psz_device the CD/DVD to eject
  83.  * return 0 on success, 1 on failure, -1 if not implemented
  84.  */
  85. int __intf_Eject( vlc_object_t *p_this, const char *psz_device )
  86. {
  87.     int i_ret = VLC_SUCCESS;
  88. #ifdef SYS_DARWIN
  89.     FILE *p_eject;
  90.     char *psz_disk;
  91.     char sz_cmd[32];
  92.     /*
  93.      * The only way to cleanly unmount the disc under MacOS X
  94.      * is to use the 'disktool' command line utility. It uses
  95.      * the non-public Disk Arbitration API, which can not be
  96.      * used by Cocoa or Carbon applications.
  97.      */
  98.     if( ( psz_disk = (char *)strstr( psz_device, "disk" ) ) != NULL &&
  99.         strlen( psz_disk ) > 4 )
  100.     {
  101. #define EJECT_CMD "/usr/sbin/disktool -e %s 0"
  102.         snprintf( sz_cmd, sizeof(sz_cmd), EJECT_CMD, psz_disk );
  103. #undef EJECT_CMD
  104.         if( ( p_eject = popen( sz_cmd, "r" ) ) != NULL )
  105.         {
  106.             char psz_result[0x200];
  107.             i_ret = fread( psz_result, 1, sizeof(psz_result) - 1, p_eject );
  108.             if( i_ret == 0 && ferror( p_eject ) != 0 )
  109.             {
  110.                 pclose( p_eject );
  111.                 return VLC_EGENERIC;
  112.             }
  113.             pclose( p_eject );
  114.             psz_result[ i_ret ] = 0;
  115.             if( strstr( psz_result, "Disk Ejected" ) != NULL )
  116.             {
  117.                 return VLC_SUCCESS;
  118.             }
  119.         }
  120.     }
  121.     return VLC_EGENERIC;
  122. #elif defined(UNDER_CE)
  123.     msg_Warn( p_this, "CD-Rom ejection unsupported on this platform" );
  124.     return i_ret;
  125. #elif defined(WIN32)
  126.     MCI_OPEN_PARMS op;
  127.     MCI_STATUS_PARMS st;
  128.     DWORD i_flags;
  129.     char psz_drive[4];
  130.     memset( &op, 0, sizeof(MCI_OPEN_PARMS) );
  131.     op.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_CD_AUDIO;
  132.     strcpy( psz_drive, "X:" );
  133.     psz_drive[0] = psz_device[0];
  134.     op.lpstrElementName = psz_drive;
  135.     /* Set the flags for the device type */
  136.     i_flags = MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID |
  137.               MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE;
  138.     if( !mciSendCommand( 0, MCI_OPEN, i_flags, (unsigned long)&op ) )
  139.     {
  140.         st.dwItem = MCI_STATUS_READY;
  141.         /* Eject disc */
  142.         i_ret = mciSendCommand( op.wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, 0 );
  143.         /* Release access to the device */
  144.         mciSendCommand( op.wDeviceID, MCI_CLOSE, MCI_WAIT, 0 );
  145.     }
  146.     else i_ret = VLC_EGENERIC;
  147.     return i_ret;
  148. #else   /* WIN32 */
  149.     int i_fd;
  150.     /* This code could be extended to support CD/DVD-ROM chargers */
  151.     i_fd = open( psz_device, O_RDONLY | O_NONBLOCK );
  152.     if( i_fd == -1 )
  153.     {
  154.         msg_Err( p_this, "could not open device %s", psz_device );
  155.         return VLC_EGENERIC;
  156.     }
  157. #if defined(SYS_LINUX) && defined(HAVE_LINUX_VERSION_H)
  158.     /* Try a simple ATAPI eject */
  159.     i_ret = ioctl( i_fd, CDROMEJECT, 0 );
  160.     if( i_ret != 0 )
  161.     {
  162.         i_ret = EjectSCSI( i_fd );
  163.     }
  164.     if( i_ret != 0 )
  165.     {
  166.         msg_Err( p_this, "could not eject %s", psz_device );
  167.     }
  168. #elif defined (HAVE_DVD_H)
  169.     i_ret = ioctl( i_fd, CDROMEJECT, 0 );
  170. #else
  171.     msg_Warn( p_this, "CD-Rom ejection unsupported on this platform" );
  172.     i_ret = -1;
  173. #endif
  174.     close( i_fd );
  175.     return i_ret;
  176. #endif
  177. }
  178. /* The following functions are local */
  179. #if defined(SYS_LINUX) && defined(HAVE_LINUX_VERSION_H)
  180. /*****************************************************************************
  181.  * Eject using SCSI commands. Return 0 if successful
  182.  *****************************************************************************/
  183. /**
  184.  * brief Ejects the CD /DVD using SCSI commands
  185.  * ingroup vlc_interface
  186.  * This function is local
  187.  * param i_fd a device nummber
  188.  * return 0 on success, VLC_EGENERIC on failure
  189.  */
  190. static int EjectSCSI( int i_fd )
  191. {
  192.     int i_status;
  193.     struct sdata
  194.     {
  195.         int  inlen;
  196.         int  outlen;
  197.         char cmd[256];
  198.     } scsi_cmd;
  199.     scsi_cmd.inlen  = 0;
  200.     scsi_cmd.outlen = 0;
  201.     scsi_cmd.cmd[0] = ALLOW_MEDIUM_REMOVAL;
  202.     scsi_cmd.cmd[1] = 0;
  203.     scsi_cmd.cmd[2] = 0;
  204.     scsi_cmd.cmd[3] = 0;
  205.     scsi_cmd.cmd[4] = 0;
  206.     scsi_cmd.cmd[5] = 0;
  207.     i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
  208.     if( i_status != 0 )
  209.     {
  210.         return VLC_EGENERIC;
  211.     }
  212.     scsi_cmd.inlen  = 0;
  213.     scsi_cmd.outlen = 0;
  214.     scsi_cmd.cmd[0] = START_STOP;
  215.     scsi_cmd.cmd[1] = 0;
  216.     scsi_cmd.cmd[2] = 0;
  217.     scsi_cmd.cmd[3] = 0;
  218.     scsi_cmd.cmd[4] = 1;
  219.     scsi_cmd.cmd[5] = 0;
  220.     i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
  221.     if( i_status != 0 )
  222.     {
  223.         return VLC_EGENERIC;
  224.     }
  225.     scsi_cmd.inlen  = 0;
  226.     scsi_cmd.outlen = 0;
  227.     scsi_cmd.cmd[0] = START_STOP;
  228.     scsi_cmd.cmd[1] = 0;
  229.     scsi_cmd.cmd[2] = 0;
  230.     scsi_cmd.cmd[3] = 0;
  231.     scsi_cmd.cmd[4] = 2;
  232.     scsi_cmd.cmd[5] = 0;
  233.     i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
  234.     if( i_status != 0 )
  235.     {
  236.         return VLC_EGENERIC;
  237.     }
  238.     /* Force kernel to reread partition table when new disc inserted */
  239.     i_status = ioctl( i_fd, BLKRRPART );
  240.     return i_status;
  241. }
  242. #endif