Solved

CD door state

Posted on 1997-12-20
29
523 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
ID: 1354296
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
ID: 1354297
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
ID: 1354298
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
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

 
LVL 3

Author Comment

by:Matvey
ID: 1354299
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
ID: 1354300
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
ID: 1354301
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
ID: 1354302
Ok, I see, I'll try to do my best. Hopefully others too.
0
 
LVL 3

Author Comment

by:Matvey
ID: 1354303
The same question is avialable now under the name MatveyB

FOR 200 POINTS!

Matvey
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1354304
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
ID: 1354305
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
ID: 1354306
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
ID: 1354307
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
ID: 1354308
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
ID: 1354309
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
 
LVL 8

Expert Comment

by:ZifNab
ID: 1354310
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
ID: 1354311
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
ID: 1354312
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
ID: 1354313
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
ID: 1354314
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
ID: 1354315
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
ID: 1354316
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
ID: 1354317
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
ID: 1354318
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
ID: 1354319
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
ID: 1354320
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
ID: 1354321
ASAP. 10x
0
 
LVL 8

Expert Comment

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

Author Comment

by:Matvey
ID: 1354323
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
ID: 1354324
Oooops! forgot to give you points! sorry...

Matvey
0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
indy Tmemory stream non latin charcter issue 2 109
Virtuailstring tree compare node issue 14 116
add combobox item based on numbers 9 141
JAudiorecorder record freezing the app 29 67
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
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 Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

816 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

7 Experts available now in Live!

Get 1:1 Help Now