How can I find out whether the CD tray is opened or closed?

The tray of a CD drive I can open via applescript with

do shell script "drutil tray eject"

and with

do shell script "drutil tray close"

I can close it. But I want to create a script which opens the tray when closed and closes it when opened. For this I would like to know the current status of the tray - whether it’s open or closed. Any idea how I can find out via applescript or shell commands?

Many thanks in advance, Olli

Model: iMac 20", OSX 10.8.3
Browser: Firefox 23.0
Operating System: Mac OS X (10.8)

Hello.

I can’t swear I saw something that detected the status of the CD-tray at MacOsX Hints, but I am fairly sure I did.
So if I were you, I’d search for it there.

I am sorry that I can’t do any better than that at the moment.

But one thing that slipped into my mind in this very moment: If the CD-tray is open, then the volume wouldn’t be mounted, or at least shouldn’t be mounted, so maybe you can check for the status of the tray implicitly, by checking if the CD drive can be found among the mounted volumes?

Why not pressing the eject button with AppleScript? This toggles the dvd tray for you.

How can I press the Eject button via applescript?

The real eject button is remapped via KeyRemap4Macbook

Which way are you clicking the eject button ?
Is there a numerical value defined to trigger the Eject key from the keyboard using keycode value ?

The Finder eject command can’t be used because it requires a volname which isn’t available if there is nothing in the tray.

KOENIG Yvan (VALLAURIS, France) vendredi 9 août 2013 16:25:30

Hello.

I found This thread

Now I wonder if the solution may be as simple as:

do shell script "drutil eject -drive internal"

Edit

And if that doesn’t work, then maybe the drutil command exits with an error code you can use to check for to determine if the drive was open , and then issue a following close command.

I have also seen that the key code for the Eject button, at least has been 161, I haven’t tested it.
I found the information here.

Hello McUsrII,

on my machine running 10.8.4 in french,


tell application "System Events"
	key code 161
end tell

has no visible effect.

KOENIG Yvan (VALLAURIS, France) vendredi 9 août 2013 16:50:13

If you have an tray that can open and close it means you have an MacPro. That also means you have an external keyboard connected to it. Which leads us that F12 is mapped to the eject key. At least key code 111 behaves on my MacPro as the eject button. The reason for F12 is that the eject button is missing on third party keyboards, so when Mac OS X detects an external keyboard it maps the eject key to the F12 button. It doesn’t work for internal keyboards like laptops.

When you have this software installed it’s even easier to press the eject button. Just press the key code that match with your remap of the eject button.

I apologize but on the external wired keyboard, eject and F12 are different keys.
Eject and F13 are different keys too.

I don’t have a macPro but an iMac.

KOENIG Yvan (VALLAURIS, France) vendredi 9 août 2013 17:21:47

PS : F12 is the key making the sound louder, nothing common with eject.

That is what I expected. I assumed that the TS doesn’t have an iMac because MacPro’s only have real trays, so for him a good solution. I didn’t say that F12 and the eject buttons are the same but the eject button is mapped to F12 (virtually). That is for support for external third party keyboards who doesn’t have an eject button. Press fn + F12 because probably you have turned off that Functions key doesn’t behave as normal keys in system preferences.

No luck !
With the checkbox checked or unchecked


tell application "System Events"
	key code 111
end tell

doesn’t eject the tray, and doesn’t change the sound level.

Just for info, the lull wired keyboard is exactly the same for macPro and iMac.

I found a valid list of codes for F13 thru F19 and for every keys of the numerical pad but was unable to find one for F1 thru F12 which may be different according to localization setting.

KOENIG Yvan (VALLAURIS, France) vendredi 9 août 2013 17:59:25

I use the following code: (on OS X 10.5!!)

property last_choice : "Open"

if last_choice = "Open" then
	do shell script "drutil tray open -drive 1"
	set last_choice to "Close"
else
	do shell script "drutil tray close -drive 1"
	set last_choice to "Open"
end if

Yep, I guess that’s the best we can come up with, because there doesn’t seem to be a wayto find out in what state the tray actually is…

Hello.

I actually found a way around this.
There are some assumptions here, and one is that the devicename for the CD-Rom player doesn’t change:

I mounted a CD, I saw that it turned up in Terminal by issuing ls -l /Volumes.

Ok, then I fired up disk-utility, and I noted the device number on my machine for the CD-Rom, that is /dev/disk1s2.

Ok, so when a CD is in the drive, then I can ls -l /dev/disk1s2 without error, that is, when I perform an echo $?, then it returns 0. When there isn’t any CD in the drive, then the ls -l command returns 1, and there is nothing to eject.

Personally, I prefer this scheme over the one with a script property, since there are so many ways to eject a drive.

Hopes this helps. :wink:

Hi,

the status of the tray can be read with DiscRecording.framework.

I wrote a tiny command line tool, which returns 0 (closed) or 1 (open).
If there are multiple devices, you can specify an index (zero-based)

Download: TrayOpenStatus

The code is very simple


#import <Foundation/Foundation.h>
#import <DiscRecording/DiscRecording.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        NSUInteger deviceIndex = 0;
        if (argc == 2) {
            if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0) {
                printf("Usage:\nTrayOpenStatus [index] \n\nTrayOpenStatus returns the tray status (0 = closed or 1) of the optical drive.\nIf no index number (zero-based) is specified, the status of the primary drive is returned.\n\n-help\tprint this list\n");
                return 1;
            }
            deviceIndex = [[NSString stringWithUTF8String:argv[1]] integerValue];
        }
        NSArray *devices = [DRDevice devices];
        NSUInteger numberOfDevices = [devices count];
        
        if (numberOfDevices) {
            if (deviceIndex > numberOfDevices - 1) {
                printf("Invalid device index\n");
                return 1;
            }
            DRDevice* device  = devices[deviceIndex];
            printf("%d\n", [device trayIsOpen]);
        } else {
            printf("No optical devices available\n");
            return 1;
        }
    }
    return 0;
}

PS:

Just for fun

Disc Events is a faceless scriptable application (like System Events) with a few rudimental features.
You can get the tray status and open/close the tray and eject media


tell application "Disc Events"
	tell device "SuperDrive"
		if tray is open then
			close tray
		else
			open tray
		end if
	end tell
end tell

Download (code signed) : Disc Events

Thanks Stefan. That’s exactly what I needed! I use it for my little script which alternates between opening and closing:


#!/bin/bash

function usage {
cat<<EOT
usage: ${0##*/}
Open CD tray (eject Media beforehand if needed) when closed and close CD tray when opened
EOT
}

if [ "$1" == "--help" ]; then
  usage
  exit 60
fi

if [ $# -gt 0 ]; then
  echo "error: to many arguments" >&2
  usage
  exit 65
fi


TRAYTESTCMD="TrayOpenStatus"
if which "$TRAYTESTCMD" >/dev/null; then 
  is_open=`"$TRAYTESTCMD"`
else
  is_open=0
fi

if [ "$is_open" -eq "1" ]; then
  drutil tray close
else
  drutil tray eject
fi

Many thanks again,
Olli