Welcome, guest | Sign In | My Account | Store | Cart

This module provides easy control of cd drives on Win32 machines. Using the Python Win32 Extensions, the module automatically detects all cd drives and defaults to the first drive found or to a programmer specified drive. Methods include eject() to open the drive door, close() to close the drive door, and load() which tries to close the drive door and then make the drive available to the file system.

To test either import the WinCDRom module and create an instance of the Cdrom class:

import WinCDRom cd = WinCDRom.Cdrom() cd.eject() cd.close() cd.load()

Or just run the script from a DOS prompt to use the test function:

C:\python WinCDRom.py

Listing drives: ['D:'] Default drive: D: Opening drive door... Closing cd drive door... (CD read attempt will time out at 5 seconds.) Loaded cd successfully in drive D: WinCDRom Tests completed.

Python, 107 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
'''
Python Module: WinCDROM
Purpose: Loads or unloads a cd-rom drive on Windows. Only
tested on Windows 2000 and XP.
'''

import os, time
try:
    import win32file, win32api
    from win32con import *
except ImportError:
    print "The WinCDROM module requires the Python Win32 extensions."
    raise

class Cdrom:
    '''Controls for loading,ejecting, and reading cds on Win32 platforms.'''

    def __init__(self, drive=None, timeout=20):
        '''Accepts a cd drive letter. For example 'E:' or 'e'.'''
        self.drives = []
        try:
            self.drive = drive[:1].upper()
        except TypeError:
            self.drive = ''
            self.getDrives()
        self.timeout = timeout

    def __getDeviceHandle(self, drive=''):
        '''Returns a properly formatted device handle for DeviceIOControl call.'''
        drive = drive[:1]
        return "\\\\.\\%s:" % drive.upper()

    def __is_cd_inserted(self, drive=''):
        try:
            x = win32api.GetVolumeInformation(drive)
            #print "CD is inserted in drive %s" % drive
            return 1
        except:
            #print "no CD inserted in drive %s" % drive
            return 0

    def getDrives(self):
        '''Assign all available cd drives to self.drives. If CdRom.drive
        is not already set the first drive returned becomes the default.
        '''
        letters = [l.upper() + ':' for l in 'abcdefghijklmnopqrstuvwxyz']
        for drive in letters:
            if win32file.GetDriveType(drive)==5:
                self.drives.append(drive)
        if not self.drive:
            self.drive = self.drives[0]

    def load(self, drive=''):
        '''Closes cd drive door and waits until cd is readable.'''
        drive = drive or self.drive
        device = self.__getDeviceHandle(drive)
        hdevice = win32file.CreateFile(device, GENERIC_READ,
                                        FILE_SHARE_READ, None, OPEN_EXISTING, 0, 0)
        win32file.DeviceIoControl(hdevice,2967564,"", 0, None)
        win32file.CloseHandle(hdevice)
        # Poll drive for loaded and give up after timeout period
        i=0
        while i < 20:
            if self.__is_cd_inserted(drive) == 1:
                return 1
            else:
                time.sleep(1)
            i = i+1
        return 0

    def eject(self, drive=''):
        '''Opens the cd drive door.'''
        drive = drive or self.drive
        device = self.__getDeviceHandle(drive)
        hdevice = win32file.CreateFile(device, GENERIC_READ,
                                        FILE_SHARE_READ, None, OPEN_EXISTING, 0, 0)
        win32file.DeviceIoControl(hdevice,2967560,"", 0, None)
        win32file.CloseHandle(hdevice)

    def close(self, drive=''):
        '''Closes the cd drive door.'''
        drive = drive or self.drive
        device = self.__getDeviceHandle(drive)
        hdevice = win32file.CreateFile(device, GENERIC_READ,
                                        FILE_SHARE_READ, None, OPEN_EXISTING, 0, 0)
        win32file.DeviceIoControl(hdevice,2967564,"", 0, None)
        win32file.CloseHandle(hdevice)
        
if __name__ == '__main__':
    cd = Cdrom(timeout=5)
    print "Running WinCDRom tests"; print
    print "Listing drives:"; print
    print cd.drives; print
    print "Default drive: %s" % cd.drive; print
    print "Opening drive door..."
    cd.eject(); print
    import time; time.sleep(2)
    print "Closing cd drive door... (CD read attempt will time out at %s seconds.)" % cd.timeout
    print
    if cd.load() == 1:
        print "Loaded cd successfully in drive %s" % cd.drive
        print
    else:
        print "Unable to load cd."
        print "If you have a slower drive try increasing the 'timeout' parameter."
        print
    print "WinCDRom Tests completed."

If you're writing an application which processes data on a set of cds then opening the drive door is an easy way for users to know the application has processed the cd or maybe found an error.

My company uses this module in an application to extract thumbnails and metadata from regularly-received satellite image cds for automatic inclusion in a Web searchable database. We have the application running on several peripheral computers and everyone in the office knows to swap in another cd for processing if they walk by and the drive door is open.

1 comment

sasa sasa 18 years, 4 months ago  # | flag

Any idea how to detect blank CDs or DVDs? I tried your module but I think it didn't detect a blank DVD. That's what I need. Do you have any advice?