MCI: MCI_CLOSE needed if the CD has been ejected?

David L 161 Reputation points
2021-02-17T09:47:11.747+00:00

Hello

I have read that sending MCI_CLOSE command is important to get access again to the device later on.

If I handle the CD player opening message DBT_DEVICEREMOVECOMPLETE, check that this is the right player (in case there are several ones) and then try to send the "mciSendCommandW(deviceID, MCI_CLOSE, MCI_WAIT, (DWORD_PTR)&mgp);" (deviceID is the same than the one I used successfully for MCI_PLAY), I get a "0xC0000008: An invalid handle was specified" exception.

Does the ejection close the device on its own before sending DBT_DEVICEREMOVECOMPLETE ?

Thanks
David

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,422 questions
0 comments No comments
{count} votes

6 answers

Sort by: Most helpful
  1. David L 161 Reputation points
    2021-02-19T15:22:07.673+00:00

    Finally, I cheated:

    As the access to the CD player using MCI is reset once I've closed my program, I've created a console application:

    • that remains hidden (with "#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")")
    • that creates a dummy window to communicate with the calling app (with "hWnd=CreateWindowExA(0, class_name, "register_name", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);")
    • that accepts 4 arguments in the command line: the letter of the CD player, the number of the first track to be played, the number of the last track and the HWND of the calling program

    And then I launch it via CreateProcess from my main program. As it has the parent HWND, I "SendMessage" from it and as soon as the dummy window is created, to pass its HWND to the parent so the latter can SendMessage to the child too:

    • for the parent to get the current position in the playing
    • for the parent to get the length of the track
    • for the parent to tell its child to Kill itself if the playing has been cancelled
    • for the child to tell its parent that the song is over before lilling itself.

    And it works, I can open the CD tray while it's playing, insert a new one and start with a new track with the right TOC... And it is transparent as the way I create my console app makes no window and nothing in the taskbar.
    Perhaps it creates a little more delay between 2 different plays as the child app needs to be launched and the CD to be re-opened, but this is a 68kB prog so nothing unacceptable.

    Thanks for your help
    David

    1 person found this answer helpful.
    0 comments No comments

  2. David L 161 Reputation points
    2021-02-17T10:16:50.75+00:00

    I just realize that if an audio CD is playing when ejecting, the last sample (in the buffer I suppose) continues to play in a loop. I can then send a MCI_STOP command (with the same deviceID) with no error and the sound stops.
    If I insert another audio CD, the MCI_OPEN command returns an error, so it seems that the device has not been released... but I can't as it throws an exception even if I MCI_CLOSE just after the MCI_STOP.

    If I MCI_CLOSE while the CD is still in, I have no exception, it works.

    0 comments No comments

  3. Castorix31 81,726 Reputation points
    2021-02-17T11:43:24.553+00:00

    I also met this problem (Windows 10)
    A workaround is to Lock/Unlock the CD drive with IOCTL_STORAGE_MEDIA_REMOVAL (lock when a track is playing)

    0 comments No comments

  4. David L 161 Reputation points
    2021-02-17T13:00:31.697+00:00

    Thanks a lot for your answer, it's a shame it can't be done the right way.
    And if a track is not playing, if the CD is manually removed, there is no problem with WM_CLOSE?


  5. David L 161 Reputation points
    2021-02-17T14:27:52.757+00:00

    I have checked and if the CD never played or if the playing has been stopped with a MCI_STOP, there's no problem, but if the CD is removed while playing or even after a track has stopped on its own because it was over (and even if I send a MCI_STOP afterwards), then the MCI_CLOSE crashes.

    So the case of the track stopping on its own remains, even if I use your method. The only solution is to MCI_STOP just before the track is over (comparing actual play time against length) ?

    EDIT: in fact if the CD has ever been played, MCI_CLOSE crashes, even if it is MCI_STOP-ped before the end...