Solved

CD door state

Posted on 1997-12-20
29
511 Views
Last Modified: 2010-04-04
I need a simple examle of a procedure that will be attached  to a win32 event that is triggered when the CD-ROM door OPENS or CLOSES (of course I need to know the state of the door).
And I also need a procedure that wil OPEN or CLOSE the door according to it's state.

Thanks in advance!
0
Comment
Question by:Matvey
  • 15
  • 13
29 Comments
 
LVL 2

Expert Comment

by:Felixin
Comment Utility
Why don't you use a TMediaPlayer object?. (Delphi 3)

You have an Eject method to Open/Close the door of the CD, and you have a OnNotify method that is fired whenever those actions are made, among many others.
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
You see, it's not that easy. The eject method only opens, but doesn't closes the CD door.
And about the notify event - it's not fired when the user opens the CD door manually (presses the button on the CD-ROM).
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
You have to include the MMSystem unit in your uses clause.

Open CD-ROM:

  mciSendString('Set cdaudio door open wait', nil, 0, handle);

Close CD-ROM:

 mciSendString('Set cdaudio door closed wait', nil, 0, handle);

Notify event, I don't know, sorry

Have fun,
c.u. ZifNab;
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
Thanks ZifNab.

I want to mention again that I also need to know the state of
the CD door. How will I know when to use one procedure and when to use the oposite ??!
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Hi Matvey,

I gave them as a comment, because I don't know the full answer, but I now looked at the MPlayer.pas source.

I suggest also to look at the MPlayer.Pas source, everything what you need is in there. Also an notify event (MM_MCINotify).

Have fun,
Questions? Just ask,
c.u. ZifNab;

0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
No, I looked at it and it's not the event I want. It's triggered after an mci procedure call, and comes to notify if the action was sucsesfull, and finally it triggers the mpl Notify event.
So I still need help.
Thanks
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Ok, I see, I'll try to do my best. Hopefully others too.
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
The same question is avialable now under the name MatveyB

FOR 200 POINTS!

Matvey
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Matvey, have you already looked at the MCI commands?
Like MCIWND_CANEJECT
or mciwndf_notifymedia
or mciwndf_notifymode
Just a guess.
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
Hello again!

Yes you are right! but the only thing you are right, I think, is about the MCIwnd - it looks like smth that works.

I have an ActiveX - Microsoft MCIwnd and it seems to fire those events. ( do you have it? ) It has no help, but I have some help in delphi for MCIwnd.
Can you send me an exmple of code that uses this animal, and it's events? I'll be realy happy!

Thanks,
Matvey
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Sorry, don't know yet how to work with this animal.
By the way, why do you need to know it? If you call the eject button and it's already on this position, nothing will happen, same for a close button.

But, maybe these papers are interesting :

http://www.borland.com/delphi/papers/multimedia/multimedia.html
http://www.borland.com/borlandcpp/news/cobb/bcj3_1a.html

Have lot's of reading pleasure!
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
Well, all I can say is that those pages were usefull.
But they aren't about the stuff I need.

And to add some more bad news: I was disapointed by the MCIWnd -  all it has is a timer that checks if the door is closed or not... This is what I currently use, already for soooome time.

I guess I'll stick to it, and wait for an answere.

By the way, do you know how can I easyly check if the CD is audio or data?

And about the eject button - I want to make smth similar to eject button of thw windows CD player, not two buttons but ONE. Other ideas?

Waiting for help,
Matvey
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Sorry about MCIWnd, just wanted to help.

About eject button :

You can use an internal boolean : e.g. CDDOOROPEN;

if CDDOOROPEN then begin
  eject procedure
  CDDOOROPEN := false;
 end
  else begin
   open procedure;
   CDDOOROPEN := true;
  end;

-> Only need one button.

About CD, audio or data. I have something about how information is stored on an audio cd (I'll look if there is something interesting).
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
I'll be really thankfull about the thing you will find...

And if the door is opened by the user manually? In this case I have to know it. So now I do it the hard way. Maybe, one day...
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Before I give some thing about that audio or data. How do you do it at the moment? So I don't give you the same solution like you already did.
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
I check if it has only one track-then it's a data CD (well, there can be theoreticaly one audio track on CD, but I don't know any other way).

And I still have a timer to check the door state...
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Well, about that door state, I really can't find something at the moment, sorry...

You will always have to check a track I guess. Maybe this way is more interesting :

 CDA music tracks file format
  by Wojtek Kaniewski 1997

  Note: Everything in this file is based on my own investigations.
        All information that you'll find in this text file do not
        come from Microsoft Corp.

  CDA files are generally RIFF resources. The RIFF id of .CDA file is
  "CDDA" (43h, 44h, 44h, 41h). They contain only one data block
  called "fmt " (66h, 6dh, 74h, 20h). In current version of .CDA file,
  this block is 24 bytes long. Here's structure of it:

     Offset  Length  Description
     00h     02h     CDA file version. Currently equals 1. If it has
                     other value, following data may be out of date.
     02h     02h     Number of track.
     04h     04h     CD disc serial number (the one stored in CDPLAYER.INI)
     08h     04h     Beginning of the track in HSG format.
     0Ch     04h     Length of the track in HSG format.
     10h     04h     Beginning of the track in Red-Book format.
     14h     04h     Length of the track in Red-Book format.

  As you see, time is represented in two formats: HSG and Red-Book.
  HSG can be calculated as following:
   
    time = minute * 4500 + second * 75 + frame

  Red-book is much easier to use, because it contains minutes,
  seconds and frames in unmodified form, byte-packed:

     Offset  Length  Description
     00h     01h     Frame
     01h     01h     Second
     02h     01h     Minute
     03h     01h     not used

  Now, I'll show you an example file. First part is a hex dump
  of the file, the second is the explanation of the fields.

     52 49 46 46 24 00 00 00  43 44 44 41 66 6D 74 20  RIFF$...CDDAfmt
     18 00 00 00 01 00 04 00  B8 24 F6 00 F7 11 01 00  .........$......
     B4 5C 00 00 0A 25 0F 00  20 10 05 00              .\...%.. ...

     01 00       - first version of CDA file :)
     04 00       - fourth track
     B8 24 F6 00 - serial number of CD in CDPLAYER.INI is [F623B8]

     F7 11 01 00 - begining of track in HSG format
     B4 5C 00 00 - length of track in HSG format

     0A 25 0F 00 - begining of track in Red-Book format (15:37)
     20 10 05 00 - length of track in Red-book format (05:16)

  That's all. It should be enough to write CDA Viewer :) If you need more
  info or something isn't clear, feel free to write.

  Wojtek Kaniewski
  wojtekka@logonet.com.pl


0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
Whoow! this information is very useful, maybe even one of the only oportunities to find it. - Thanks.

But I was thinking of smth just for detecting if the CD is Data or Audio.
MCI thinks that any CD is an audio CD - just the data CDs have one track - a long one (70 minutes). And I have to filter those CDs to play only the Audio ones.
Maybe you can help me with a simple piece of code that looks for files or smth on the CD, simple code that check if the CD IS A DATA CD (well, maybe there is an API function that tells it...).
I was trying some things bud the didn't work.
Sugestions are wellcome!

Thanks,
Matvey
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
I run through the net, but couldn't find a real solution. Even, most people thought that there isn't a solution. But maybe this is a solution :

Q) How can I tell if a given CD-ROM Drive contains an Audio CD?

A) You can use the Windows API function GetDriveType() to test
  if the drive is a CD-ROM drive then use the Windows API function
 
GetVolumeInformation() to test if the VolumeName is 'Audio CD'.
Example:

function IsAudioCD(Drive : char) : bool;
 var
   DrivePath : string;
   MaximumComponentLength : DWORD;
   FileSystemFlags : DWORD;
   VolumeName : string;
  begin
   Result := false;
   DrivePath := Drive + ':\';
   if GetDriveType(PChar(DrivePath)) <> DRIVE_CDROM then exit;
   SetLength(VolumeName, 64);
                               GetVolumeInformation(PChar(DrivePath),                                                    PChar(VolumeName),                                                  Length(VolumeName),                                                    nil,                                                    MaximumComponentLength,                                                    FileSystemFlags,                                                    nil, 0);

if lStrCmp(PChar(VolumeName),'Audio CD') = 0 then result := true;
end;

                             function PlayAudioCD(Drive : char) : bool;
                             var
                               mp : TMediaPlayer;
                             begin
                               result := false;
                               Application.ProcessMessages;
                               if not IsAudioCD(Drive) then exit;
                               mp := TMediaPlayer.Create(nil);
                               mp.Visible := false;
                               mp.Parent := Application.MainForm;
                               mp.Shareable := true;
                               mp.DeviceType := dtCDAudio;
                               mp.FileName := Drive + ':';
                               mp.Shareable := true;
                               mp.Open;
                               Application.ProcessMessages;
                               mp.Play;
                               Application.ProcessMessages;
                               mp.Close;
                               Application.ProcessMessages;
                               mp.free;
                               result := true;
                             end;

                             procedure TForm1.Button1Click(Sender: TObject);
                             begin
                               if not PlayAudioCD('D') then
                                 ShowMessage('Not an Audio CD');
                             end;

                             Joe
                             --
                             Joe C. Hecht
                             joehecht@gte.net
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
About detecting cd change :
This is all i could find. Last resort...

A : Respond to the WM_DEVICECHANGE message with a DBT_DEVICEARRIVAL and/or DBT_DEVICEREMOVECOMPLETE event.
See also http://www.microsoft.com/kb/articles/q163/5/03.htm

B:unfortunatly, this does not work on all machines. My
laptop only gets this message if you eject the cd with code.

And guess what! The link still exists and has some source code example!

Hope this is what you need!

P.S. May I see the end result?
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
Thanks!

That answeres my question!

But there is no such a constant: DBT_DEVICEARRIVAL (or removecompleete...), do you know if it's OK to check for the value of wParm just as an integer number (to check it onece with a wathch and create my own constant?)? or this constant exists?

Could you post as an ANSWERE an examle of the last comment as a pascal procedure so I won't mess with it too much (a message handler that checks if it's really a CD that was inserted or removed, and, for example, shows a message like 'CD removed' or 'CD insrted') ?

I'll be glad to give you the OTHER 200 points and thoug I won't have use of this question anymore you can get those points too( 40 ), so don't feel shy to answere this one also!

The other question is at the adress http://www.experts-exchange.com/topics/bin/ShowQ?qid=8630031967

I thank you so much!

And about the end product - I'll be glad to send it to you, and also to everybody that helps me - it'll be finished sooner or later.
But because I do it for fun(in my very free time)I don't know how much it will take me (a radius of half a year).

Thanks again!
Matvey
0
 
LVL 8

Accepted Solution

by:
ZifNab earned 40 total points
Comment Utility
Well, I don't have the fully answer yet, but here is already something :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons;

const
 (* I'm not really sure about these values!
    values are put int the wParam *)

 DBT_DEVICEARRIVAL = 32772;
 DBT_DEVICEREMOVECOMPLETE = 32768;

Type
  TfBitmap = class(TForm)
   procedure WndProc(var Msg: TMessage); override;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation


{$R *.DFM}

procedure TfBitmap.WndProc(var Msg: TMessage);
begin
 if Msg.Msg = WM_DEVICECHANGE then begin
  (* Here I have a problem : lParam contains an adress to a record
     DEV_BROADCAST_HDR, in here you've got the DBT_DEVTYP_VOLUME,
     you need to check this to be sure that the event comes from
     a volume device, but I don't know how I can get to this *)
  case Msg.wParam of
   DBT_DEVICEARRIVAL : begin
     showmessage('CD DOOR OPEN');
    end;
   DBT_DEVICEREMOVECOMPLETE : begin
     showmessage('CD DOOR CLOSE');
    end;
  end;
 end
   else inherited WndProc(MSg);
end;




end.
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
Well, maybe you'll find smth new in the win32.hlp in this message topic (wm_devicechange).
I'll search and reply.

Matvey
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Well, I'm going home for the weekend. I'll try to find it in some books at home. Have you tried the source already? It works with this computer (even if you don't check if it's the right volume). I tried everything, sending data to com port, new disk, etc. It only gave an event when opening and closing the CD-Drive.
!LOOK OUT! This only works if the medium changes!! If you have no cd-rom in it and you open and close the cd drive no event happens! If you open the cd drive put a new cd in it, it works. If you open the cd drive and takes the cd out or changes the cd it works also!

Regards,
Zif.
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
HI Matvey!!!!

This should it be! Although I'm not really sure about the constants I declared (I don't have a book of windows). I got them just by experimenting. Please try this code out on your computer. If it works, then I'm almost sure it will work on every other computer. This is the first time I program something like this. So i'm a little bit proud! Hope you give me some credits in your program!
I'm thinking of making a component for this, (when I find some time) what do you think?

PS. If you find a windows book where they declare these constants , can you give me a hint then? (just the values, the booknumber or the link)

Thanks.

unit drive;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons;

const
 (* I'm not really sure about these values!
    values are put int the wParam *)

 DBT_DEVICEARRIVAL = 32772;
 DBT_DEVICEREMOVECOMPLETE = 32768;

 (* I'm not really sure about these values!
    values are put in a datastruct (lpatam) *)

 DBT_DEVTYP_OEM = 1;
 DBT_DEVTYP_VOLUME = 2;
 DBT_DEVTYP_PORT = 3;

 (* I found everything just by experimenting, so don't shoot me if
    something went wrong, just tell me the error and I'll see what I
    can do!                                                          *)

Type
  PBroadCastStruct = ^TBroadCastStruct;
  TBroadCastStruct = packed record
    dbch_Size : ULong;
    dbch_devicetype : ULong;
    dbch_reserved : ULong;
  end;

  TWMDeviceChange = record
   Msg : Cardinal;
   Event : Uint;
   DataStruct : PBroadCastStruct;
   Result : LongInt;
  end;

  TfBitmap = class(TForm)
  private
    { Private declarations }
   procedure Test(var Msg: TWMDeviceChange); message WM_DEVICECHANGE;
  public
    { Public declarations }
  end;

var fBitmap : TFBitmap;
    Bericht : TWMDeviceChange;

implementation


{$R *.DFM}


procedure TfBitmap.Test(var Msg:TWMDEVICECHANGE);
var i : integer;
begin
if Msg.Msg = WM_DEVICECHANGE then begin
  if Msg.DataStruct^.dbch_devicetype = DBT_DEVTYP_VOLUME then begin
   case Msg.Event of
    DBT_DEVICEARRIVAL : begin
      showmessage('CD DOOR OPEN');
     end;
    DBT_DEVICEREMOVECOMPLETE : begin
      showmessage('CD DOOR CLOSE');
     end;
   end;
  end;
 end;
end;

end.

Please : Try it out and let me know if it works!
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
ASAP. 10x
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
Hi! And Matvey, does it works? Give me some comment here, thanks.
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
Hi!

Sorry for the pause, it was due to a total crash of my system.

Yes! it seems to work! And a component isn't a bad idea at all!

Sorry, don't know of any book right now.

And by the way, never used it so, how do I find information in the Microsoft site?(how did you find this one?)

Could you also check my new question about the component, at
http://www.experts-exchange.com/topics/bin/ShowQ?qid=8630032874

And check the SendMessage question, it seemed to have no responce from my last comment...,
and don't feel shy to get the other 200 points!

Credits will be given, really thankfull,
Matvey

PS what's your full name?:)
0
 
LVL 3

Author Comment

by:Matvey
Comment Utility
Oooops! forgot to give you points! sorry...

Matvey
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
This video discusses moving either the default database or any database to a new volume.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now