TIP: Click on subject to list as thread! ANSI
echo: os2prog
to: All
from: Gerard Gerritsen
date: 1996-01-09 14:26:02
subject: CD AUDIOplayer unit for Virtual Pas

Hello All!

This unit makes use of the DosDevIoCtl api to get cd audio working.

Message to Footprint software, this unit ( and the example program ) may be
included as examples for the Virtual Pascal package )


=== Begin cd2.pas ===
UNIT CD2;

{
 A cdaudio unit for Virtual Pascal Version 1 ( EEP 3 )
 which makes use of the OS2 API. ( instead of MMPM/2 )

 ( it should work with other versions of Virtual Pascal )

 Please note, that "I" am not an "experienced"
programmer and these
 routines could prove to be absolutely useless in the real world.

 I assert no promises or guarantees in relation to these routines.
 Nor do I claim any "rights" to their use. If however you make
 improvements to them, please drop me a line at one of the address below
 so I can update my routines.

 These routines are not complete, but should be enough to get a simple player
 working.

 By Gerard Gerritsen,
 2:283/203.18 {at}fidonet.org
 1000521{at}et.fnt.hvu.nl

 written on 01-05-1996 but released 01-13-1996, due to circumstances
 ( new processor, unexpected but welcome night work etc. ( a local building had
   burned down a little bit, and they needed people to clean up the mess.... )
   And the most important reason, school :^(
 )

 Thanks and greetings to:
 David Muir       -> for posting his serial I/O routines with dosdevioctl...
                     and his disclaimer...
 Kiril Lebedev    -> For sending the source of CrazyCdPm
 Eelco Dolstra    -> you know why...
 Irina Mikhailets -> for the nice postcard you sent me
 Ineka Sawyer     -> ..................................................
 Ernst Steenbrink -> For some hints for the sample program

 Acknowledgement appreciated

}

INTERFACE

USES OS2DEF, os2base;

  (* CONST *)

CONST
  { addresing mode }
  MSF                 = 1;
  LOGICAL             = 0;

  { device status }
  Door_open           = 1;
  { door is open }

  { b.t.w. checking if the door is open after obtaining a file handle,
    will not work very well, since the door must be closed for dosopen to
    work :^ ( }

  Door_locked         = 2;
  { door is locked        }
  Cooked_and_raw      = 4;
  { device supports cooked & raw }
  Read_and_write      = 8;
  { device can read & write }
  Audio_and_video     = 16;
  { can play audio and video }
  ISO_interleaving    = 32;
  { supports ISO interleaving }
  Prefetch_supported  = 64;
  { supports prefetch }
  Audio_manipulation  = 128;
  { support audio channel manipulation }
  Logical_and_MSF_address = 256;
  { supports logical and MSF addresses }
  Form_1_and_form_2   = 512;
  { support form 1 and form 2 sectors }
  Disc_present        = 1024;
  { Disc present... }
  Playing_audio       = 2048;
  { Drive is playing... }

  (* TYPE  *)

TYPE
  track_position      = RECORD
                          frames,
                          seconds,
                          minutes             : Byte;
                        END;

  track_start_stop    = RECORD
                          start,
                          stop                : track_position;
                        END;

  cd_struct           = RECORD
                          first_track,
                          last_track          : Byte
                        END;

  complete_cd         = ARRAY[1..255] OF track_start_stop;
                        { well I have not seen a CD bigger than 32 tracks
                        { and DosDevIoCtl does not support more then
                        { 255 tracks }

  complete_cd_pointer = ^complete_cd;

  Current_position    = RECORD          { MSF format }
                          current             : track_position;
                          Dummy               : Byte;
                        END;

  Device_status_param = RECORD
                          status              : Ulong;
                        END;


  (* VARIABLES *)

VAR
  device_handle       : hfile;         { file handle }
  track_pointer       : complete_cd_pointer;
  first_track,
  last_track          : Byte;



  (* INTERFACE FUNCTIONS *)

FUNCTION Open_cdrom(drive_label : PChar; VAR device_handle : hfile) : Boolean;
  { simply opens device driver }

FUNCTION Close_cdrom(device_handle : hfile) : Boolean;
  { Closes cdrom. Returns true upon succes }

FUNCTION Device_status(device_handle : hfile; VAR param : Device_status_param)
         :Boolean;
  { returns information about player and CD. Returns true upon succes }

FUNCTION Disc_in_drive(device_handle : hfile) : Boolean;
  { returns true if there is a CD in the drive }

FUNCTION Get_current_location(device_handle : hfile; VAR head_location
         : Current_position) : Boolean;
  { Returns current position in MSF or LOGICAL block format }
  { can be used regardless whether the drive is already playing }
  { Returns true upon success }

FUNCTION Open_tray(device_handle : hfile) : Boolean;
  { Ejects disk i.e. duck for cover :^) }

FUNCTION Close_tray(device_handle : hfile) : Boolean;
  { Closes cdrom tray if open. Returns true upon success }

FUNCTION Stop_playing(device_handle : hfile) : Boolean;
  { Stops playing. Returns true upon succes }

FUNCTION Resume_playing(device_handle : hfile) : Boolean;
  { Resumes playing. Returns true upon succes }

FUNCTION Query_cdrom(device_handle : hfile; VAR cd : cd_struct) : Boolean;
  { Returns first and last track. Returns true upon succes }

FUNCTION Query_track(device_handle : hfile; track : Byte; VAR track_pos
         : track_start_stop) : Boolean;
  { Returns begin and endposition of a given track. Returns true upon success }

FUNCTION Play_track(device_handle : hfile; track_pos : track_start_stop)
         :Boolean;
  { Plays cd from start_of_track to end_of_track. Returns true upon succes }
  { start_of_track&end_of_track are in MSF format               }
  { see record current_position for a description of the MSF format }

FUNCTION Init_cdrom(VAR device_handle : hfile; VAR track_pointer :
         complete_cd_pointer) : Boolean;

IMPLEMENTATION

USES crt;
TYPE

  Return_tracks_param = RECORD
                          first_last          : cd_struct;
                          end_last_track      : track_position;
                          Dummy               : Byte;
                        END;

  Label_drive         = String[2];

  Return_track_command = RECORD
                           Signature           : ARRAY[1..4] OF Char;
                           track               : Byte;
                         END;

  Play_track_command  = RECORD
                          Signature           : ARRAY[1..4] OF Char;
                          address_mode        : Byte;
                          start               : track_position;
                          dummy_byte          : Byte;
                          end_track           : track_position;
                          Dummy               : Byte;
                        END;

  get_current_location_command = RECORD
                                   Signature           : ARRAY[1..4] OF Char;
                                   address_mode        : Byte;
                                 END;

  Standard_command    = RECORD
                          Signature           : ARRAY[1..4] OF Char;
                        END;

  Return_track_param  = RECORD
                          begin_of_track      : track_position;
                          dummy_byte          : Byte;
                          track_ctl           : Byte;      { track ctl_info }
                        END;

  Standard_param      = RECORD
                          Dummy               : Byte;
                        END;


  (*      Here are the functions and procedures           *)

  (*                      Variables       *)

VAR
  CD_structure        : Return_tracks_param;
  { for internal reference }

  FUNCTION Stop_playing(device_handle : hfile) : Boolean;

  VAR
    command             : Standard_command;
    param               : Standard_param;
    command_size,
    param_size          : Ulong;

  BEGIN
    command.Signature := 'CD01';
    command_size := SizeOf(command);
    param_size := SizeOf(param);

    IF dosdevioctl(device_handle, $81, $51, {at}command, command_size,
                   {at}command_size, {at}param, param_size, {at}param_size) = 0
    THEN Stop_playing := True ELSE Stop_playing := False;
  END;


  FUNCTION Can_play_audio(device_handle : hfile) : Boolean;

  VAR
    status              : Device_status_param;

  BEGIN
    IF Device_status(device_handle, status)
    THEN IF (status.status AND Audio_and_video) = Audio_and_video
      THEN
        BEGIN
          Can_play_audio := True;
          Exit;
        END;
    Can_play_audio := False;
  END;


  FUNCTION Disc_in_drive(device_handle : hfile) : Boolean;

  VAR
    status              : Device_status_param;

  BEGIN
    IF Device_status(device_handle, status)
    THEN IF (status.status AND Disc_present) = Disc_present
      THEN
        BEGIN
          Disc_in_drive := True;
          Exit;
        END;
    Disc_in_drive := False;
  END;

  FUNCTION Device_status(device_handle : hfile; VAR param :
           Device_status_param) : Boolean;

  VAR
    command             : Standard_command;
    command_size,
    param_size          : Ulong;

  BEGIN
    command.Signature := 'CD01';
    command_size := SizeOf(command);
    param_size := SizeOf(param);

    IF dosdevioctl(device_handle, $80, $60, {at}command, command_size,
                   {at}command_size, {at}param, param_size, {at}param_size) = 0
    THEN Device_status := True ELSE Device_status := False;
  END;

  FUNCTION Is_Cdrom(device_handle : hfile) : Boolean;

  VAR
    command             : Standard_command;
    param               : Standard_command;
    command_size,
    param_size          : Ulong;

  BEGIN
    command.Signature := 'CD01';
    command_size := SizeOf(command);
    param_size := SizeOf(param);

    IF dosdevioctl(device_handle, $80, $61, {at}command, command_size,
                   {at}command_size, {at}param, param_size, {at}param_size) = 0
    THEN
      IF param.Signature = command.Signature THEN Is_Cdrom := True
      ELSE Is_Cdrom := False;
  END;

  FUNCTION find_valid_cdrom(VAR device_handle:hfile) : Boolean;

  VAR
    counter             : Integer;
    device_label        : String[2];

  BEGIN
    device_label[2] := ':';        { we need that }
    FOR counter := Ord('C') TO Ord('Z') DO
      BEGIN
        device_label[1] := Char(counter);
        IF Open_cdrom({at}device_label[1], device_handle) THEN
          IF Is_Cdrom(device_handle) THEN
            BEGIN
              find_valid_cdrom := True;
              Exit;
            END
      ELSE close_cdrom(device_handle);
      { otherwise we will run out of file handle soon.... :^(   }
      END;
    find_valid_cdrom := False;
  END;


  { Get current location of the head}
  FUNCTION Get_current_location(device_handle : hfile; VAR head_location :
           Current_position) : Boolean;

  VAR
    command             : get_current_location_command;
    param               : Current_position;
    command_size,
    param_size          : Ulong;
    address_mode        : Byte;

  BEGIN
    command.Signature := 'CD01';
    command.address_mode := MSF;
    { can only be MSF or LOGICAL }
    command_size := SizeOf(command);
    param_size := SizeOf(param);

    IF dosdevioctl(device_handle, $80, $70, {at}command, command_size,
                   {at}command_size, {at}param, param_size, {at}param_size) = 0
    THEN
      BEGIN
        Get_current_location := True;
        head_location := param;
      END
    ELSE Get_current_location := False;
  END;


  { close tray }
  FUNCTION Close_tray(device_handle : hfile) : Boolean;

  VAR

    command             : Standard_command;
    param               : Standard_param;
    command_size,
    param_size          : Ulong;

  BEGIN
    command.Signature := 'CD01';
    command_size := SizeOf(command);
    param_size := SizeOf(param);


    WriteLn(dosdevioctl(device_handle, $80, $45, {at}command, command_size,
                        {at}command_size, {at}param, param_size, {at}param_size));
    Close_tray := True;
    REPEAT
    UNTIL keypressed;
  END;

  { ejects disk }
  FUNCTION Open_tray(device_handle : hfile) : Boolean;

  VAR
    command             : Standard_command;
    param               : Standard_param;
    command_size,
    param_size          : Ulong;

  BEGIN
    command.Signature := 'CD01';
    command_size := SizeOf(command);
    param_size := SizeOf(param);

    IF dosdevioctl(device_handle, $80, $44, {at}command, command_size,
                   {at}command_size, {at}param, param_size, {at}param_size) = 0
    THEN Open_tray := True ELSE Open_tray := False;

  END;


  { resume playing when playing had been stopped by stop_playing }
  FUNCTION Resume_playing(device_handle : hfile) : Boolean;

  VAR
    command             : Standard_command;
    param               : Standard_param;
    command_size,
    param_size          : Ulong;

  BEGIN
    command.Signature := 'CD01';
    command_size := SizeOf(command);
    param_size := SizeOf(param);

    IF dosdevioctl(device_handle, $81, $52, {at}command, command_size,
                   {at}command_size, {at}param, param_size, {at}param_size) = 0
    THEN Resume_playing := True ELSE Resume_playing := False;
  END;

  { close cdrom drive }
  FUNCTION Close_cdrom(device_handle : hfile) : Boolean;

  BEGIN
    IF dosclose(device_handle) = 0 THEN Close_cdrom := True ELSE
       Close_cdrom := False;
  END;

  { opens cdrom drive and returns file handle to cdrom }
  FUNCTION Open_cdrom(drive_label : PChar; VAR device_handle : hfile) : Boolean;
  VAR
    action              : Ulong;
    { action taken by dosopen }

  BEGIN ;
    IF dosopen(
      {file_name}  drive_label,
      {filehandle} device_handle,
      {action}     action,
      {file size}  0,
      {attributes} file_normal,
      {openflags}  file_open OR open_action_open_if_exists
                   OR open_action_fail_if_new,
      {openmode}   Open_Access_readWrite OR Open_share_Denynone
                   OR open_flags_dasd,
      { no E.A.}   Peaop2(0)) = 0
      THEN Open_cdrom := True ELSE Open_cdrom := False;
  END;

  { initialize cdrom, checks if audio capable and closes tray }
  FUNCTION Init_cdrom(VAR device_handle : hfile; VAR track_pointer
           : complete_cd_pointer) : Boolean;

  VAR
    status              : Device_status_param;
    counter             : Byte;
    cd                  : cd_struct;
    drive_label         : Label_drive;

  BEGIN
--- Fmail/2 1.02 Registered
* Origin: Yet another forgotten area! (2:283/203.18)
SEEN-BY: 50/99 270/101 620/243 711/401 409 410 413 430 808 809 934 955
SEEN-BY: 712/407 515 517 628 713/888 800/1 7877/2809
@PATH: 283/203 2 6 1 512 280/801 270/101 712/515 711/808 809 934

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.