home *** CD-ROM | disk | FTP | other *** search
/ Dr. CD ROM (Annual Premium Edition) / premium.zip / premium / IBMOS2_1 / INSCDP.ZIP / cdplayer.c next >
Text File  |  1993-10-23  |  52KB  |  1,248 lines

  1. /*************************************************************************
  2.  * Dateiname    :  cdplayer.c    
  3.  *
  4.  * Beschreibung :  Beispielprogramm eines CD-Players unter Verwendung des
  5.  *                 Multimedia Toolkits und der MCI String Command 
  6.  *                 Schnittstelle.
  7.  *
  8.  * Inhalt       :  Dieses Beispielprogramm zeigt auf, wie einfach eine 
  9.  *                 Multimediaanwendung unter Verwendung der Textschnitt-
  10.  *                 stelle entwickelt werden kann.
  11.  *
  12.  *                 Eine Audio-CD wird gelesen und kann abgespielt werden.
  13.  *                 Zusätzlich können die Titel der CD in eine Datenbank
  14.  *                 eingetragen werden. Die Datenbank ist als INI-Datei
  15.  *                 organisiert (der Einfachheit wegen).
  16.  *
  17.  * MMPM/2 API's :  Folgende MMPM/2 API's werden verwendet
  18.  *
  19.  *
  20.  * Alle Dateien :  cdplayer.c     Source Code.
  21.  *                 cdplayer.h     Include Datei.
  22.  *                 cdplayer.rc    Resource Datei.
  23.  *                 cdplayer.dlg   Dialog Definition.
  24.  *                 cdplayer.mak   Datei für NMAKE.
  25.  *                 cdplayer.def   Datei für LINK386.
  26.  *                 cdplayer.ico   CD-Player Icon.
  27.  *
  28.  * Copyright (C) 1993 Axel Salomon, für Inside OS/2 Ausgabe November '93 
  29.  *************************************************************************/
  30.  
  31. #define  INCL_WIN                   /* Win  APIs einbinden.              */
  32. #define  INCL_PM                    /* PM   APIs einbinden.              */
  33. #define  INCL_OS2MM                 /* Multimedia APIs einbinden         */
  34. #define  INCL_SW                    /* für 'secondary windows'           */
  35.  
  36. #include <os2.h>
  37. #include <os2me.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41.  
  42. #include <sw.h>
  43.  
  44. #include "cdplayer.h"
  45.  
  46. #define MCI_STRING_LENGTH           256
  47. #define MCI_ERROR_STRING_LENGTH     128
  48. #define MCI_RETURN_STRING_LENGTH    128
  49.  
  50. /*
  51.  * Prototyping.
  52.  */
  53.  
  54. MRESULT EXPENTRY CdplayerDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
  55. MRESULT EXPENTRY MehrDlgProc    ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
  56.  
  57. INT     main( INT argc, CHAR *argv[] );
  58. VOID    Beenden( VOID );
  59. VOID    Initialisierung( VOID );
  60. ULONG   SendStringToMCI( PSZ pszCmd, HWND hwndNotify, USHORT usUserParam );
  61. VOID    CdpInitContainer( VOID );
  62. VOID    CdpSetupAudioCDInfo( VOID );
  63. VOID    CdpClearAudioCDInfo( VOID );
  64. VOID    CdpUpdateTrack( LONG lTrack, LONG lFlag );
  65. VOID    CdpUpdateAktuell( VOID );
  66. VOID    CdpEnableObjects( BOOL bFlag );
  67.  
  68. /*
  69.  * Globale Variablen.
  70.  */
  71.  
  72. /* Handle der verschiedenen Objekte */
  73. HAB    hab;                            /* Handle Anchor Block       */
  74. HMQ    hmq;                            /* Handle Message Queue      */
  75. HWND   hwndFrame,hwndFrame2;           /* Handle des framewindows   */
  76. HWND   hwndCdplayer;                   /* Handle des Dialoges       */
  77. HWND   hwndCdmehr;                     /* Handle des MehrDialoges   */
  78. HWND   hwndContainer;                  /* Containerhandle           */
  79. HWND   hwndSpinVolume;                 /* Handle für die Lautstärke */
  80. HWND   hwndSpinbutton;                 /* Handle für die Titelwahl  */
  81. HWND   hwndScrollbar;                  /* Handle für die Zeitansteuerung */
  82. HWND   hwndCheckbox;                   /* Handle für Musikkopplung  */
  83. HWND   hwndEFCDTitel;                  /* Eingabefeldhandle ...     */
  84. HWND   hwndEFCDID;
  85. HWND   hwndEFAutor;
  86. HWND   hwndEFTitel;
  87. HWND   hwndEFLaenge;
  88. HWND   hwndEFAktuell;
  89. HWND   hwndEFMusik;                    /* Handles für den Mehr ... Dialog */
  90. HWND   hwndEFText;
  91. HWND   hwndEFRichtung;
  92. HWND   hwndEFTakte;
  93. HWND   hwndEFAusgabe;
  94. HWND   hwndMLEBemerk;  
  95. HINI   hiniCdplayer;                   /* Handle der CD-Player INI-Datei */
  96. HPOINTER  hptrWait, hptrArrow;         /* Handle für die Zeiger Uhr und Pfeil */
  97.  
  98. /* Container Variable */
  99. CNRINFO cnri;                          /* Container Info Struktur */
  100. ULONG   cnriFlags;
  101.  
  102. FIELDINFOINSERT fii;                   /* Struktur für das Anfügen von Spalten */
  103.  
  104. #define CNR_COLUMN_NUM 10              /* Anzahl der Spalten */
  105.  
  106. UCHAR achColumnTitle[CNR_COLUMN_NUM][20] = { "Nr.", "Titel", "Autor", "Länge", "Musik von", "Text von", "Musikrichtung", "Erscheinungsdatum", "Bemerkungen", "Millisekunden" };
  107. ULONG aulColumnData [CNR_COLUMN_NUM]     = {CFA_ULONG, CFA_STRING, CFA_STRING, CFA_STRING, CFA_STRING, CFA_STRING, CFA_STRING, CFA_STRING, CFA_STRING, CFA_ULONG };
  108.  
  109. /* Textspeicher */ 
  110. UCHAR achMciSnd[MCI_STRING_LENGTH];         /* Kommando      für mciSendString() */
  111. UCHAR achReturn[MCI_RETURN_STRING_LENGTH];  /* Rückgabe */
  112. UCHAR achError [MCI_ERROR_STRING_LENGTH];   /* Fehler   */
  113.  
  114. CHAR acBuffer[128];                         /* temporärer Textspeicher */
  115.  
  116. /* CD Daten */
  117. UCHAR acHexID[19];                     /* CD-ID in HEX Format             */
  118. UCHAR acHex[17];
  119.  
  120. UCHAR acCdDevice[20];                  /* Parameter 1 des CDPLAYER's      */
  121.   
  122. UCHAR acCDTitel[128];                  
  123. LONG  lNumOfTracks;                    /* Anzahl der Titel                */
  124. LONG  lCurrTrack, lUnlinkedTrack;      /* Steuerung des Titelwahl         */
  125. LONG  lVolume = 75;                    /* Lautstärke: 75%                 */
  126. BOOL  bIsPlaying;                      /* Schalter: Musik läuft           */
  127. BOOL  bIsMediaPres;                    /*           Audio CD eingelegt    */
  128. BOOL  bIsLinked;                       /*           Musik/Titel verbunden */
  129. BOOL  bIsMehr = FALSE;                 /*           "Mehr" Dialog aktiv   */
  130.  
  131. /* Titeldaten */
  132. typedef struct _CDTITELINFO { /* Für Eingabefelder */
  133.         UCHAR  acAutor[128];
  134.         UCHAR  acTitel[128];
  135.         UCHAR  acLaenge[16];
  136.         UCHAR  acMusik[128];
  137.         UCHAR  acText[128];
  138.         UCHAR  acRichtung[128];
  139.         UCHAR  acTakte[128];
  140.         UCHAR  acAusgabe[30];
  141.         UCHAR  acBemerkung[4096];
  142.         LONG   lMillisec;
  143.         PRECORDCORE prcCnrDaten;
  144.       } CDTITELINFO;
  145.  
  146. typedef union _DATEN { /* Für Containerrecords */
  147.         LONG     lWert;
  148.         PSZ      pszString;
  149.         PVOID    pOther;
  150.         CDATE    date;
  151.         CTIME    time;
  152.         HBITMAP  bitmap;
  153.         HPOINTER icon;
  154.       } DATEN;
  155.  
  156. #define MAX_CD_TITEL 99 
  157.  
  158. CDTITELINFO aCDTitel[MAX_CD_TITEL];
  159.  
  160. /* Definitionen für CD-Datenaktualisierung */
  161. #define CDP_KEEPTIME       0x0001   /* Musikposition beibehalten     */
  162. #define CDP_NOCNRUPDATE    0x0002   /* Container nicht aktualisieren */
  163. #define CDP_UPDATETEXTONLY 0x0004   /* Musik nicht aktualisieren     */
  164.  
  165. /*
  166.  * Main.
  167.  */
  168.  
  169. INT main( INT argc, CHAR *argv[] )
  170. {
  171.    QMSG    qmsg;
  172.  
  173. /* Der 1. Parameter von CDPLAYER kann ein cdaudio-Gerät in der Form 
  174.    cdaudio01, cdaudio02, cdaudio03, etc. sein */
  175.  
  176.    if( argc >= 2 )
  177.        strcpy( acCdDevice, argv[1] );
  178.    else
  179.       strcpy( acCdDevice, "cdaudio" );
  180.  
  181.    Initialisierung();
  182.  
  183.    while ( WinGetMsg( hab, (PQMSG) &qmsg, (HWND) NULL, 0, 0) )
  184.       WinDispatchMsg( hab, (PQMSG) &qmsg );
  185.  
  186.    Beenden();
  187.  
  188.    return( TRUE);
  189.  
  190.  
  191. /*
  192.  * Initialisierung.
  193.  */
  194.  
  195. VOID Initialisierung( VOID)
  196. {
  197.    hab       = WinInitialize( 0);
  198.    hmq       = WinCreateMsgQueue( hab, 0);
  199.  
  200.    /* Profile öffnen */
  201.    hiniCdplayer = PrfOpenProfile( hab, "CDPLAYER.INI" );
  202.  
  203.    /* ID-konvertierung vorbereiten */
  204.    strcpy( acHex, "0123456789ABCDEF" );
  205.    strcpy( acHexID, "0x00000000" );
  206.  
  207.    /* Handle der Zeiger erfragen und auf Warten setzen */
  208.    hptrArrow = WinQuerySysPointer ( HWND_DESKTOP, SPTR_ARROW, FALSE );
  209.    hptrWait  = WinQuerySysPointer ( HWND_DESKTOP, SPTR_WAIT,  FALSE );
  210.  
  211.    WinSetPointer ( HWND_DESKTOP, hptrWait );
  212.  
  213.    /* Dialog laden */
  214.    hwndFrame =                    /* Handle des Framewindows               */
  215.        WinLoadSecondaryWindow(
  216.           HWND_DESKTOP,           /* Elternteil des Dialoges               */
  217.           HWND_DESKTOP,           /* Eigentümer des Dialoges               */
  218.           (PFNWP) CdplayerDlgProc,/* Prozedur des Dailoges                 */
  219.           (HMODULE) NULL,         /* Dialog befindet sich in der EXE-Datei */
  220.           ID_DLG_CDPLAYER,        /* Dialog ID                             */
  221.           (PVOID) NULL);          /* Parameter für den Dialog              */
  222.  
  223.    /* "Standardgröße" zum Systemmenü hinzufügen */
  224.    WinInsertDefaultSize(hwndFrame, "~Standardgröße");
  225.  
  226.    /* Handle des Dialogs erfragen */
  227.    hwndCdplayer = WinQuerySecondaryHWND(hwndFrame, QS_DIALOG);
  228.  
  229.    /* Dialog anzeigen */
  230.    WinShowWindow( hwndFrame, TRUE );        /* Dialog anzeigen             */
  231.  
  232.    /* Zeiger wieder zurücksetzen */
  233.    WinSetPointer ( HWND_DESKTOP, hptrArrow );
  234.  
  235. }
  236.  
  237.  
  238. /*
  239.  * Beenden.
  240.  */
  241.  
  242. VOID Beenden( VOID )
  243. {
  244.    /* Ini-Datei schließen */
  245.    PrfCloseProfile( hiniCdplayer );
  246.  
  247.    WinDestroySecondaryWindow( hwndFrame ); 
  248.    WinDestroyMsgQueue( hmq );
  249.    WinTerminate( hab );
  250. }  
  251.  
  252.  
  253. /*
  254.  * CdplayerDlgProc.
  255.  */
  256.  
  257. MRESULT EXPENTRY CdplayerDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  258. {
  259.   NOTIFYRECORDEMPHASIS *nre;      /* Struktur für die Aktivierung von Containersätzen */
  260.   HPOINTER hpPrgIcon;             /* Handle für das Programmicon */
  261.   HACCEL   hAcc;                  /* Kurztasten Handle */
  262.   PSZ      pszReturnString;       /* Zeiger auf ein Rückgabetext */
  263.   USHORT   id;                    /* id des Objektes, daß ein Mitteilung (WM_CONTROL) bekommen hat */
  264.   LONG     lMinuten, lSekunden, lTrack, lMaxMin, lMaxSec; /* Zeitwerte */
  265.   ULONG    ni, ulRet;             /* ni = notify information; Rückgabewert von Funktionen */
  266.   SHORT    nc, slpos, cmd, sSec;  /* nc = notify command; slpos Musikposition / Sliderposition in msec. */
  267.   PVOID    pUser;                 /* Zeiger auf private Daten eines Containerdatensatzes */
  268.   DATEN   *pDaten;                /* Zeiger auf ein Array von Daten eines Containerdatensatzes */
  269.   static BOOL bIsInit = TRUE;     /* Initialisierung aktiv ? */
  270.  
  271.    switch( msg ) {
  272.      case WM_INITDLG :
  273.           /* ICON für den Dialog laden und anzeigen */
  274.           hpPrgIcon = WinLoadPointer( HWND_DESKTOP, (HMODULE) NULL, ID_IC_CDPLAYER );
  275.           WinDefSecondaryWindowProc( hwndFrame, WM_SETICON, (MPARAM) hpPrgIcon, (MPARAM) 0 );
  276.           hAcc = WinLoadAccelTable( hab, (HMODULE) NULL, ID_AC_CDPLAYER );
  277.           WinSetAccelTable( hab, hAcc, hwndFrame );
  278.  
  279.           /* Handle der Objekte sichern */
  280.           hwndCdplayer   = hwnd;
  281.           hwndContainer  = WinWindowFromID( hwnd, ID_CNR_TITELANZEIGE  );
  282.           hwndSpinbutton = WinWindowFromID( hwnd, ID_SB_LIEDNR         );
  283.           hwndSpinVolume = WinWindowFromID( hwnd, ID_SB_VOLUME         );
  284.           hwndScrollbar  = WinWindowFromID( hwnd, ID_SCR_ANZEIGE       );
  285.           hwndCheckbox   = WinWindowFromID( hwnd, ID_CKB_TRENNEN       );
  286.           hwndEFCDTitel  = WinWindowFromID( hwnd, ID_EF_CDTITEL        );
  287.           hwndEFCDID     = WinWindowFromID( hwnd, ID_EF_CDID           );
  288.           hwndEFAutor    = WinWindowFromID( hwnd, ID_EF_AUTOR          );
  289.           hwndEFTitel    = WinWindowFromID( hwnd, ID_EF_TITEL          );
  290.           hwndEFLaenge   = WinWindowFromID( hwnd, ID_EF_LAENGE         );
  291.           hwndEFAktuell  = WinWindowFromID( hwnd, ID_EF_ZEITAKTUELL    );
  292.  
  293.           /* Eingabefeldlängen sichern */
  294.           WinSendMsg( hwndEFCDTitel, EM_SETTEXTLIMIT, (MPARAM) 128, (MPARAM) NULL );
  295.           WinSendMsg( hwndEFAutor  , EM_SETTEXTLIMIT, (MPARAM) 128, (MPARAM) NULL );
  296.           WinSendMsg( hwndEFTitel  , EM_SETTEXTLIMIT, (MPARAM) 128, (MPARAM) NULL );
  297.  
  298.           /* Container initialisieren, Titel, Spalten, etc. */
  299.           CdpInitContainer();
  300.  
  301.           /* Audio CD Gerät öffnen und CD prüfen */
  302.           sprintf( achMciSnd, "open %s alias cd wait", acCdDevice );
  303.           SendStringToMCI( achMciSnd, hwnd, 0 );
  304.           SendStringToMCI( "status cd media present wait", hwnd, 0 );
  305.  
  306.           /* Ist eine Audio CD eingelegt, Daten auswerten, sonst Daten zurücksetzen */
  307.           if( strcmp( achReturn, "TRUE" ) == 0 )
  308.           {
  309.               CdpSetupAudioCDInfo();
  310.           }
  311.           else
  312.           {
  313.               CdpClearAudioCDInfo();
  314.           }
  315.  
  316.           /* Schalter setzen */
  317.           bIsPlaying = FALSE;
  318.           bIsInit = FALSE;
  319.  
  320.           /* Timer starten, um Anzeige zu aktualisieren und Medium zu prüfen */
  321.           WinStartTimer( hab, hwnd, 1, 1000 );
  322.  
  323.           return( (MRESULT) 0);
  324.  
  325.      case WM_TIMER: /* Eine Sekunde ist vorbei ... */
  326.           if( mp1 != (MPARAM) 1)
  327.               return (MRESULT) 0;
  328.  
  329.           /* Timer anhalten, falls eine CD ausgelesen worden ist, würde dies zu Lange dauern
  330.              und es würden weitere WM_TIMER - Msg. auflaufen */
  331.           WinStopTimer( hab, hwnd, 1 );
  332.  
  333.           /* Medium prüfen */
  334.           SendStringToMCI( "status cd media present wait", hwnd, 0 );
  335.  
  336.           if( strcmp( achReturn, "FALSE" ) == 0 && bIsMediaPres )       /* Die CD wurde herausgenommen */
  337.           {
  338.               WinSetPointer ( HWND_DESKTOP, hptrWait );
  339.               CdpClearAudioCDInfo();
  340.               WinSetPointer ( HWND_DESKTOP, hptrArrow );
  341.           }
  342.           else if( strcmp( achReturn, "TRUE" ) == 0 && ! bIsMediaPres ) /* Eine CD wurde eingelegt */
  343.           {
  344.               WinSetPointer ( HWND_DESKTOP, hptrWait );
  345.               CdpSetupAudioCDInfo();
  346.               WinSetPointer ( HWND_DESKTOP, hptrArrow );
  347.           }
  348.           else /* Anzeige aktuallisieren */
  349.           {
  350.              if( bIsMediaPres && bIsPlaying)
  351.                  CdpUpdateAktuell();
  352.           }
  353.  
  354.           /* Timer wieder starten */
  355.           WinStartTimer( hab, hwnd, 1, 1000 );
  356.           return (MRESULT) 0;
  357.  
  358.      case WM_CLOSE : /* Der Dialog wird geschlossen */
  359.           /* Timer stoppen */
  360.           WinStopTimer( hab, hwnd, 1 );
  361.  
  362.           /* Audio CD Gerät schließen */
  363.           SendStringToMCI( "close cd wait", hwnd, 0 );
  364.  
  365.           /* "Mehr" Dialog schließen, falls noch aktiv ... */
  366.           if( bIsMehr )
  367.               WinSendMsg( hwndCdmehr, WM_CLOSE, (MPARAM) NULL, (MPARAM) NULL );
  368.  
  369.           return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  370.  
  371.      case WM_CONTROL: /* Ein Objekt hat ein Mitteilung verschickt */
  372.           /* Während der Initialisierung oder wenn keine CD eingelegt wurde, haben wir nichts zu tun */
  373.           if( bIsInit || ! bIsMediaPres )
  374.               return (MRESULT) 0;
  375.  
  376.           id = (USHORT) SHORT1FROMMP( mp1 ); /* Objekt-Id speichern  */
  377.           nc = (USHORT) SHORT2FROMMP( mp1 ); /* Notify Cmd speichern */
  378.           ni = (ULONG) mp2;                  /* Weitere Informationen zu dieser Mitteilung */
  379.  
  380.           switch( id ){
  381.             case ID_SB_LIEDNR: /* Spinbutton Titelauswahl */
  382.                  switch( nc ){
  383.                    case SPBN_CHANGE:
  384.                    case SPBN_ENDSPIN:
  385.                         WinSendMsg( hwndSpinbutton, SPBM_QUERYVALUE, &lTrack, MPFROM2SHORT( 0, SPBQ_UPDATEIFVALID ) );
  386.                         break;
  387.                    default:
  388.                         return (MRESULT) 0;
  389.                  }
  390.                  /* Aktuallisiere Eingabefelder, Scrollbar und Audio-CD */
  391.                  if( (bIsLinked && lTrack != lCurrTrack) || (!bIsLinked && lTrack != lUnlinkedTrack) )
  392.                      CdpUpdateTrack( lTrack, (bIsLinked ? 0 : CDP_UPDATETEXTONLY) );
  393.                  return (MRESULT) 0;
  394.  
  395.             case ID_SB_VOLUME: /* Spinbutton Lautstärke */
  396.                  switch( nc ){
  397.                    case SPBN_CHANGE:
  398.                    case SPBN_ENDSPIN:
  399.                         WinSendMsg( hwndSpinVolume, SPBM_QUERYVALUE, &lVolume, MPFROM2SHORT( 0, SPBQ_UPDATEIFVALID ) );
  400.                         break;
  401.                    default:
  402.                         return (MRESULT) 0;
  403.                  }
  404.                  /* Aktuallisiere Lautstärke */
  405.                  sprintf( acBuffer, "set cd audio volume %i wait", lVolume );
  406.                  SendStringToMci( acBuffer, hwndCdplayer, 0 );
  407.                  return (MRESULT) 0;
  408.  
  409.             case ID_EF_CDTITEL: /* Eingabefeld CD-Titel */
  410.                  switch( nc ){
  411.                    case EN_CHANGE:
  412.                         WinQueryWindowText( hwndEFCDTitel, 128, acBuffer );
  413.                         if( strcmp( acBuffer, acCDTitel ) )  /* Titel bei Änderung aktualisieren */
  414.                         {
  415.                             strcpy( acCDTitel, acBuffer );   /* sichern */ /* In INI-Datei speichern */
  416.                             PrfWriteProfileString( hiniCdplayer, acHexID, "CD-Titel", acCDTitel );
  417.                             memset( &cnri, 0, sizeof(cnri)); /* Container aktualisieren */
  418.                             cnri.pszCnrTitle = acCDTitel; 
  419.                             cnriFlags        = CMA_CNRTITLE;
  420.                             WinSendMsg( hwndContainer, CM_SETCNRINFO, (MPARAM) &cnri, (MPARAM) cnriFlags );
  421.                         }
  422.                         break;
  423.                    default:
  424.                         return (MRESULT) 0;
  425.                  }
  426.                  return (MRESULT) 0;
  427.  
  428.             case ID_EF_AUTOR: /* Eingabefeld Autor */
  429.                  switch( nc ){
  430.                    case EN_CHANGE:
  431.                         /* aktuelle TitelNr abfragen, Autor in der INI-Datei speichern, Container aktualisieren */
  432.                         WinSendMsg( hwndSpinbutton, SPBM_QUERYVALUE, &lTrack, MPFROM2SHORT( 0, SPBQ_UPDATEIFVALID ) );
  433.                         WinQueryWindowText( hwndEFAutor, 128, acBuffer );
  434.                         if( strcmp( aCDTitel[lTrack-1].acAutor, acBuffer ) )
  435.                         {
  436.                             strcpy( aCDTitel[lTrack-1].acAutor, acBuffer );
  437.                             sprintf( acBuffer, "AUTOR%i", lTrack );
  438.                             PrfWriteProfileString( hiniCdplayer, acHexID, acBuffer, aCDTitel[lTrack-1].acAutor );
  439.                             WinSendMsg( hwndContainer, CM_INVALIDATERECORD, (MPARAM) &aCDTitel[lTrack-1].prcCnrDaten, MPFROM2SHORT( 1, CMA_TEXTCHANGED ) );
  440.                         }
  441.                         break;
  442.                    default:
  443.                         return (MRESULT) 0;
  444.                  }
  445.                  return (MRESULT) 0;
  446.  
  447.             case ID_EF_TITEL: /* Eingabefeld Titel */
  448.                  switch( nc ){
  449.                    case EN_CHANGE:
  450.                         /* aktuelle TitelNr abfragen, Titel in der INI-Datei speichern, Container aktualisieren */
  451.                         WinSendMsg( hwndSpinbutton, SPBM_QUERYVALUE, &lTrack, MPFROM2SHORT( 0, SPBQ_UPDATEIFVALID ) );
  452.                         WinQueryWindowText( hwndEFTitel, 128, acBuffer );
  453.                         if( strcmp( aCDTitel[lTrack-1].acTitel, acBuffer ) )
  454.                         {
  455.                             strcpy( aCDTitel[lTrack-1].acTitel, acBuffer );
  456.                             sprintf( acBuffer, "TITEL%i", lTrack );
  457.                             PrfWriteProfileString( hiniCdplayer, acHexID, acBuffer, aCDTitel[lTrack-1].acTitel );
  458.                             WinSendMsg( hwndContainer, CM_INVALIDATERECORD, (MPARAM) &aCDTitel[lTrack-1].prcCnrDaten, MPFROM2SHORT( 1, CMA_TEXTCHANGED ) );
  459.                         }
  460.                         break;
  461.                    default:
  462.                         return (MRESULT) 0;
  463.                  }
  464.                  return (MRESULT) 0;
  465.  
  466.             case ID_CNR_TITELANZEIGE: /* Container */
  467.                  switch(nc) {
  468.                    case CN_ENTER: /* Auswahl ... ok */
  469.                         break;
  470.  
  471.                    case CN_EMPHASIS: /* Hervorhebung : nur wenn ein Datensatz ausgewählt worden ist */
  472.                         nre = (NOTIFYRECORDEMPHASIS *)ni;
  473.                         if( !( nre->fEmphasisMask & CRA_SELECTED ) || !( nre->pRecord->flRecordAttr & CRA_SELECTED ) )
  474.                             return (MRESULT) 0;
  475.                         break;
  476.                    default:
  477.                         return (MRESULT) 0;
  478.                  }
  479.  
  480.                  /* Datensatz erfragen und Zeiger setzen */
  481.                  pUser = (PVOID) WinSendMsg( hwndContainer, CM_QUERYRECORDEMPHASIS, (MPARAM) CMA_FIRST, (MPARAM) CRA_SELECTED );
  482.                  if( pUser == (PVOID) NULL || (LONG) pUser < 0 )
  483.                      return (MRESULT) NULL;
  484.                  pDaten = (DATEN *)(((PBYTE) pUser)+sizeof(RECORDCORE));
  485.                  pDaten--; /* Irgendetwas stimmt mit dem Beginn der User-Daten nicht, daher 4 Bytes zurück (warum ?) */
  486.  
  487.                  /* Titel erfragen und Dialog aktualisieren (etwas kompliziert, sorry, wegen der Entkopplung) */
  488.                  lTrack = pDaten[0].lWert; 
  489.                  if( lTrack > 0 && lTrack <= lNumOfTracks )
  490.                      if( (bIsLinked && lTrack != lCurrTrack) || (!bIsLinked && lTrack != lUnlinkedTrack) )
  491.                          CdpUpdateTrack( lTrack, CDP_NOCNRUPDATE | (bIsLinked ? 0 : CDP_UPDATETEXTONLY) );
  492.                  return (MRESULT) 0;
  493.  
  494.             case ID_CKB_TRENNEN: /* Checkbox Titelwahl und Musik trennen */
  495.                  switch( nc ){
  496.                    case BN_CLICKED:
  497.                    case BN_DBLCLICKED: /* Status abfragen */
  498.                         bIsLinked = (BOOL)WinSendMsg( hwndCheckbox, BM_QUERYCHECK, (MPARAM) NULL, (MPARAM) NULL );
  499.                         break;
  500.                    default:
  501.                         return (MRESULT) 0;
  502.                  }
  503.                  /* Aktuallisiere Eingabefelder, Scrollbar und Audio-CD */
  504.                  WinSendMsg( hwndSpinbutton, SPBM_QUERYVALUE, &lTrack, MPFROM2SHORT( 0, SPBQ_UPDATEIFVALID ) );
  505.                  if( lTrack != lCurrTrack )
  506.                      CdpUpdateTrack( lTrack, (bIsLinked ? 0 : CDP_UPDATETEXTONLY) );
  507.                  return (MRESULT) 0;
  508.  
  509.             default:
  510.                  return (MRESULT) 0;
  511.           }
  512.           return( (MRESULT) 0);
  513.  
  514.      case WM_HSCROLL: /* Die Scrollbar wurde neu positioniert */
  515.           if( bIsInit || ! bIsMediaPres )
  516.               return (MRESULT) 0;
  517.  
  518.           id      = (USHORT) mp1;          /* Objekt Id */
  519.           cmd     = SHORT2FROMMP( mp2 );   /* Scrollbar-Befehl */ /* Aktuelle Position */
  520.           slpos   = SHORT1FROMMP( mp2 );
  521.           if( slpos == 0 )
  522.               slpos   = (SHORT)WinSendMsg( hwndScrollbar, SBM_QUERYPOS, (MPARAM) NULL, (MPARAM) NULL );
  523.  
  524.           /* Minuten und Sekunden berechnen */
  525.           lMinuten  = (LONG)slpos / 60;
  526.           lSekunden = (LONG)slpos % 60;
  527.  
  528.           switch( cmd ){
  529.             case SB_LINELEFT: /* Eine Sekunde zurück */
  530.                  slpos --;
  531.                  if( slpos < 0 )
  532.                      slpos = 0;
  533.                  WinSendMsg( hwndScrollbar, SBM_SETPOS, MPFROMSHORT(slpos), (MPARAM) NULL );
  534.                  break;
  535.             case SB_LINERIGHT: /* Ein Sekunde vor */
  536.                  slpos ++;
  537.                  if( (LONG)slpos * 1000 > aCDTitel[lCurrTrack-1].lMillisec )
  538.                      slpos = (SHORT) (aCDTitel[lCurrTrack-1].lMillisec / 1000);
  539.                  WinSendMsg( hwndScrollbar, SBM_SETPOS, MPFROMSHORT(slpos), (MPARAM) NULL );
  540.                  break;
  541.             case SB_PAGELEFT: /* Eine Minute zurück */
  542.                  slpos -= 60;
  543.                  if( slpos < 0 )
  544.                      slpos = 0;
  545.                  WinSendMsg( hwndScrollbar, SBM_SETPOS, MPFROMSHORT(slpos), (MPARAM) NULL );
  546.                  break;
  547.             case SB_PAGERIGHT: /* Eine Minute vor */
  548.                  slpos += 60;
  549.                  if( (LONG)slpos * 1000 > aCDTitel[lCurrTrack-1].lMillisec )
  550.                      slpos = (SHORT) (aCDTitel[lCurrTrack-1].lMillisec / 1000);
  551.                  WinSendMsg( hwndScrollbar, SBM_SETPOS, MPFROMSHORT(slpos), (MPARAM) NULL );
  552.                  break;
  553.             case SB_SLIDERPOSITION: /* Position hat sich durch "tracking" geändert */
  554.                  break;
  555.  
  556.             case SB_SLIDERTRACK: /* Der Slider wird bewegt, Achtung! Timer ist noch aktiv: Überschneidung. */
  557.                  sprintf( acBuffer, "%02i:%02i:%02i:00", lCurrTrack, lMinuten, lSekunden );
  558.                  WinSetWindowText( hwndEFAktuell, acBuffer );
  559.                  return (MRESULT) 0;
  560.  
  561.             default:
  562.                  return (MRESULT) 0;
  563.           }
  564.  
  565.           /* Musik neu positionieren */
  566.           SendStringToMci( "set cd time format tmsf wait", hwnd, 0 );
  567.           sprintf( achMciSnd, "seek cd to %i:%i:%i:00 wait", lCurrTrack, lMinuten, lSekunden );
  568.           SendStringToMci( achMciSnd, hwnd, 0 );
  569.           SendStringToMci( "status cd position wait", hwnd, 0 );
  570.  
  571.           /* Anzeige aktuallisieren */
  572.           WinSetWindowText( hwndEFAktuell, achReturn );
  573.  
  574.           /* Wurde die Musik gespielt, weiter speilen (sollte eigendlich automatisch gehen)  */
  575.           if( bIsPlaying )
  576.               SendStringToMci( "play cd", hwnd, 0 );
  577.  
  578.           return( (MRESULT) 0);
  579.  
  580.      case WM_COMMAND : /* Ein Psuhbutton wurde gedrückt */
  581.           if( bIsInit || ! bIsMediaPres )
  582.               return (MRESULT) 0;
  583.  
  584.           switch (SHORT1FROMMP(mp1)){
  585.             case ID_PB_PLAY: /* Musik abspielen */
  586.                  if( bIsPlaying )
  587.                      break;
  588.                  bIsPlaying = TRUE;
  589.                  SendStringToMci( "play cd", hwnd, 0 );
  590.                  break;
  591.             case ID_PB_PAUSE: /* Musik anhalten */
  592.                  if( ! bIsPlaying )
  593.                      break;
  594.                  bIsPlaying = FALSE;
  595.                  SendStringToMci( "pause cd wait", hwnd, 0 );
  596.                  break;
  597.             case ID_PB_STOP: /* Musik anhalten */
  598.                  bIsPlaying = FALSE;
  599.                  SendStringToMci( "stop cd wait", hwnd, 0 );
  600.                  break;
  601.             case ID_PB_START: /* Zum ersten Titel der CD springen, Dialog aktuallisieren */
  602.                  lCurrTrack = 1;
  603.                  CdpUpdateTrack( lCurrTrack, 0 );
  604.                  break;
  605.             case ID_PB_REWIND: /* Ein Titel zurück, Dialog aktuallisieren */
  606.                  lCurrTrack --;
  607.                  if( lCurrTrack < 1 )
  608.                      lCurrTrack = lNumOfTracks;
  609.                  CdpUpdateTrack( lCurrTrack, 0 );
  610.                  break;
  611.             case ID_PB_SECBACKWARD: /* 10 Sekunden des aktuellen Titels zurück, Dialog aktuallisieren */
  612.                  SendStringToMci( "status cd position wait", hwnd, 0 );
  613.                  lTrack    = atol( achReturn   );
  614.                  lMinuten  = atol( achReturn+3 );
  615.                  lSekunden = atol( achReturn+6 );
  616.  
  617.                  lSekunden -= 10;
  618.                  if( lSekunden < 0 )
  619.                  {
  620.                      lSekunden += 60;
  621.                      lMinuten--;
  622.                      if( lMinuten < 0 )
  623.                      {
  624.                          lTrack--;
  625.                          if( lTrack < 1 )
  626.                              lTrack = lNumOfTracks;
  627.                          lMinuten  = atol( aCDTitel[lTrack-1].acLaenge   );
  628.                          lSekunden = atol( aCDTitel[lTrack-1].acLaenge+3 );
  629.                      }
  630.                  }
  631.                  SendStringToMci( "set cd time format tmsf wait", hwnd, 0 );
  632.                  sprintf( achMciSnd, "seek cd to %i:%i:%i:00 wait", lTrack, lMinuten, lSekunden );
  633.                  SendStringToMci( achMciSnd, hwnd, 0 );
  634.                  if( bIsPlaying )
  635.                      SendStringToMci( "play cd", hwndCdplayer, 0 );
  636.                  CdpUpdateAktuell();
  637.                  break;
  638.             case ID_PB_SECFORWARD: /* 10 Sekunden des aktuellen Titels weiter, Dialog aktuallisieren */
  639.                  SendStringToMci( "status cd position wait", hwnd, 0 );
  640.                  lTrack    = atol( achReturn   );
  641.                  lMinuten  = atol( achReturn+3 );
  642.                  lSekunden = atol( achReturn+6 );
  643.                  lMaxMin   = atol( aCDTitel[lTrack-1].acLaenge   );
  644.                  lMaxSec   = atol( aCDTitel[lTrack-1].acLaenge+3 );
  645.  
  646.                  lSekunden += 10;
  647.                  if( lSekunden > 60 || (lSekunden > lMaxSec && lMinuten == lMaxMin) )
  648.                  {
  649.                      if( lSekunden > 60 )
  650.                          lSekunden -= 60;
  651.  
  652.                      lMinuten++;
  653.  
  654.                      if( lMinuten > lMaxMin )
  655.                      {
  656.                          lTrack++;
  657.                          if( lTrack > lNumOfTracks )
  658.                              lTrack = 1;
  659.                          lMinuten  = 0;
  660.                          lSekunden = 0;
  661.                      }
  662.                  }
  663.                  SendStringToMci( "set cd time format tmsf wait", hwnd, 0 );
  664.                  sprintf( achMciSnd, "seek cd to %i:%i:%i:00 wait", lTrack, lMinuten, lSekunden );
  665.                  SendStringToMci( achMciSnd, hwnd, 0 );
  666.                  if( bIsPlaying )
  667.                      SendStringToMci( "play cd", hwndCdplayer, 0 );
  668.                  CdpUpdateAktuell();
  669.                  break;
  670.             case ID_PB_FORWARD: /* Zum nächsten Titel springen, Dialog aktuallisieren */ 
  671.                  lCurrTrack ++;
  672.                  if( lCurrTrack > lNumOfTracks )
  673.                      lCurrTrack = 1;
  674.                  CdpUpdateTrack( lCurrTrack, 0 );
  675.                  break;
  676.             case ID_PB_END: /* Zum letzten Titel springen, Dialog aktuallisieren */
  677.                  lCurrTrack = lNumOfTracks;
  678.                  CdpUpdateTrack( lCurrTrack, 0 );
  679.                  break;
  680.             case ID_PB_EJECT: /* CD auswerfen */
  681.                  SendStringToMci( "set cd door open wait", hwnd, 0 );
  682.                  break;
  683.             case ID_PB_MEHR: /* Zusätzliche Daten zum Titel erfassen */
  684.                  /* Mehr-Pushbutton ausschalten und Uhr als Zeiger setzen */
  685.                  WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_MEHR ), FALSE );
  686.                  WinSetPointer ( HWND_DESKTOP, hptrWait );
  687.  
  688.                  /* Aktuelle TitelNr erfragen */
  689.                  WinSendMsg( hwndSpinbutton, SPBM_QUERYVALUE, &lTrack, MPFROM2SHORT( 0, SPBQ_UPDATEIFVALID ) );
  690.  
  691.                  /* Dialog laden, Standardgröße in Systemmenü setzen, Handle erfragen, Dialog anzeigen */
  692.                  bIsMehr = TRUE;
  693.                  hwndFrame2 = WinLoadSecondaryWindow( HWND_DESKTOP, HWND_DESKTOP, (PFNWP) MehrDlgProc, (HMODULE) NULL, ID_DLG_MEHR, (PVOID) lTrack);
  694.                  WinInsertDefaultSize(hwndFrame2, "~Standardgröße");
  695.                  hwndCdmehr = WinQuerySecondaryHWND(hwndFrame2, QS_DIALOG);
  696.                  WinShowWindow( hwndFrame2, TRUE );
  697.  
  698.                  /* Dialog abarbeiten und Rückgabewert auswerten */
  699.                  ulRet = WinProcessSecondaryWindow( hwndFrame2 );
  700.                  bIsMehr = FALSE;
  701.  
  702.                  /* Mehr-Pushbutton wieder aktivieren, falls CD noch vorhanden, und Zeiger zurücksetzen */
  703.                  WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_MEHR ), bIsMediaPres );
  704.                  WinSetPointer ( HWND_DESKTOP, hptrArrow );
  705.  
  706.                  /* Wurden die Daten gespeichert, Container aktualisieren */
  707.                  if( ulRet )
  708.                      WinSendMsg( hwndContainer, CM_INVALIDATERECORD, (MPARAM) &aCDTitel[ulRet-1].prcCnrDaten, MPFROM2SHORT( 1, CMA_TEXTCHANGED ) );                    
  709.                  break;
  710.  
  711.             default:
  712.                  break;
  713.           }  
  714.           return( (MRESULT) 0);
  715.      default:
  716.           return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2));
  717.    }
  718. }
  719.  
  720. /*
  721.  * CdpInitContainer.
  722.  */
  723.  
  724. VOID CdpInitContainer( VOID )
  725. {
  726.   FIELDINFO *fi1st, *filocal;
  727.   MRESULT rc;
  728.   INT j;
  729.  
  730.   /* Containerinfo setzen */
  731.  
  732.   memset( &cnri, 0, sizeof(cnri) );
  733.  
  734.   cnri.cb               = sizeof(cnri);
  735.   cnri.flWindowAttr     = CV_DETAIL | CA_CONTAINERTITLE | CA_TITLEREADONLY | CA_TITLESEPARATOR | CA_TITLECENTER | CA_DETAILSVIEWTITLES;
  736.   cnri.xVertSplitbar    = -1;
  737.   cnri.pFieldInfoLast   = (PFIELDINFO) NULL;       
  738.   cnri.pFieldInfoObject = (PFIELDINFO) NULL;      
  739.   cnri.cFields          = 0;
  740.  
  741.   cnriFlags          = 0x7FFF;
  742.  
  743.   WinSendMsg( hwndContainer, CM_SETCNRINFO, (MPARAM) &cnri, (MPARAM) cnriFlags );
  744.  
  745.   /* Spalten definieren */
  746.   fi1st = (FIELDINFO *) WinSendMsg( hwndContainer, CM_ALLOCDETAILFIELDINFO, (MPARAM) CNR_COLUMN_NUM, (MPARAM) NULL );
  747.  
  748.   filocal = fi1st;
  749.  
  750.   for( j=0; j<CNR_COLUMN_NUM; j++ )
  751.   {
  752.        /* Initialisierung */
  753.        if( j == CNR_COLUMN_NUM-1 )
  754.            filocal->flData = CFA_LEFT | CFA_VCENTER | CFA_FIREADONLY | aulColumnData[j];
  755.        else
  756.            filocal->flData = CFA_LEFT | CFA_VCENTER | CFA_FIREADONLY | CFA_SEPARATOR | aulColumnData[j];
  757.  
  758.        filocal->flTitle = CFA_CENTER | CFA_VCENTER | CFA_STRING | CFA_FITITLEREADONLY | CFA_HORZSEPARATOR;
  759.        filocal->pTitleData = (PVOID)achColumnTitle[j];
  760.        filocal->offStruct = sizeof(RECORDCORE)+(j-1)*sizeof(PVOID);
  761.        filocal = filocal->pNextFieldInfo;
  762.   }
  763.  
  764.   /* Erzeugung */
  765.   memset( &fii, 0, sizeof(fii) );
  766.   fii.cb                   = sizeof( fii );
  767.   fii.pFieldInfoOrder      = (PFIELDINFO) CMA_FIRST;
  768.   fii.cFieldInfoInsert     = (SHORT) CNR_COLUMN_NUM;
  769.   fii.fInvalidateFieldInfo = TRUE;
  770.  
  771.   rc = WinSendMsg( hwndContainer, CM_INSERTDETAILFIELDINFO, MPFROMP( fi1st ), MPFROMP( &fii ) );
  772.  
  773. }
  774.  
  775.  
  776. /*
  777.  * CdpSetupAudioCDInfo.
  778.  */
  779.  
  780. VOID CdpSetupAudioCDInfo( VOID )
  781. {
  782.   INT          i,j;
  783.   LONG         lStart, lWert;
  784.   SHORT        sSec, sStartSec;
  785.   ULONG        ulPrfLen;
  786.   RECORDCORE  *prc, *rcfirst;
  787.   DATEN        *pri;
  788.   RECORDINSERT rii;
  789.   APIRET       ret;
  790.  
  791.   /* "Mehr" Dialog schließen, falls noch aktiv ... */
  792.   if( bIsMehr )
  793.       WinSendMsg( hwndCdmehr, WM_CLOSE, (MPARAM) NULL, (MPARAM) NULL );
  794.  
  795.   WinEnableWindowUpdate( hwndCdplayer, FALSE );
  796.   CdpEnableObjects( TRUE );
  797.  
  798.   lCurrTrack = 0;
  799.  
  800.   /* CD-ID ermitteln */
  801.   SendStringToMCI( "info cd id", (HWND) NULL, 0 );
  802.  
  803.   for( i=0; i<8; i++ )
  804.   {
  805.        acHexID[2*(i+1)  ] = acHex[ achReturn[i] / 16 ];
  806.        acHexID[2*(i+1)+1] = acHex[ achReturn[i] % 16 ];
  807.   }
  808.  
  809.   acHexID[18] = '\0';
  810.   WinSetWindowText( hwndEFCDID, acHexID );
  811.  
  812.   /* Anzahl der Lieder ermitteln */
  813.   SendStringToMci( "status cd number of tracks wait" );
  814.  
  815.   lNumOfTracks = atol( achReturn );
  816.         
  817.   /* Profile abfragen, ob CD-ID schon vorhanden, falls ja, Daten auslesen, sonst Daten anlegen */
  818.   memset( acCDTitel, 0, 128 );
  819.   ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, "CD-Titel", (PSZ) NULL, acCDTitel, 128 );
  820.   if( strlen( acCDTitel ) == 0 )
  821.   {
  822.       strcpy( acCDTitel, "< unbekannt >" );
  823.       for( i=0; i<lNumOfTracks; i++ )
  824.       {
  825.            memset( aCDTitel[i].acAutor, 0, 128);
  826.            memset( aCDTitel[i].acTitel, 0, 128);
  827.       }
  828.   }
  829.   else
  830.   {
  831.       for( i=0; i<lNumOfTracks; i++ )
  832.       {
  833.            sprintf( acBuffer, "AUTOR%i", i+1);
  834.            ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, acBuffer, (PSZ) NULL, aCDTitel[i].acAutor, 128 );
  835.            sprintf( acBuffer, "TITEL%i", i+1);
  836.            ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, acBuffer, (PSZ) NULL, aCDTitel[i].acTitel, 128 );
  837.            sprintf( acBuffer, "MUSIK%i", i+1);
  838.            ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, acBuffer, (PSZ) NULL, aCDTitel[i].acMusik, 128 );
  839.            sprintf( acBuffer, "TEXT%i", i+1);
  840.            ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, acBuffer, (PSZ) NULL, aCDTitel[i].acText, 128 );
  841.            sprintf( acBuffer, "RICHTUNG%i", i+1);
  842.            ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, acBuffer, (PSZ) NULL, aCDTitel[i].acRichtung, 128 );
  843.            sprintf( acBuffer, "TAKTE%i", i+1);
  844.            ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, acBuffer, (PSZ) NULL, aCDTitel[i].acTakte, 128 );
  845.            sprintf( acBuffer, "AUSGABE%i", i+1);
  846.            ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, acBuffer, (PSZ) NULL, aCDTitel[i].acAusgabe, 30 );
  847.            sprintf( acBuffer, "BEMERKUNG%i", i+1);
  848.            ulPrfLen = PrfQueryProfileString( hiniCdplayer, acHexID, acBuffer, (PSZ) NULL, aCDTitel[i].acBemerkung, 4096 );
  849.       }
  850.   }
  851.  
  852.   /* CD auf das erste Lied positionieren */
  853.   SendStringToMci( "seek cd to start wait" );
  854.   lCurrTrack = 1;
  855.  
  856.   WinSetWindowText( hwndEFCDTitel, acCDTitel );
  857.   WinSetWindowText( hwndEFAutor, aCDTitel[0].acAutor );
  858.   WinSetWindowText( hwndEFTitel, aCDTitel[0].acTitel );
  859.  
  860.   /* Spinbutton initialisieren */
  861.   WinSendMsg( hwndSpinbutton, SPBM_SETLIMITS, (MPARAM) lNumOfTracks, (MPARAM) 1 );
  862.   WinSendMsg( hwndSpinbutton, SPBM_SETCURRENTVALUE, (MPARAM) 1, (MPARAM) NULL );
  863.  
  864.   WinSendMsg( hwndSpinVolume, SPBM_SETLIMITS, (MPARAM) 100, (MPARAM) 0 );
  865.   WinSendMsg( hwndSpinVolume, SPBM_SETCURRENTVALUE, (MPARAM) lVolume, (MPARAM) NULL );
  866.  
  867.   sprintf( acBuffer, "set cd audio volume %i wait", lVolume );
  868.   SendStringToMci( acBuffer, hwndCdplayer, 0 );
  869.  
  870.   /* Die Längen der einzelnen Tracks erfragen und in CDTITELINFO ablegen */
  871.   for( i=0; i<lNumOfTracks; i++ )
  872.   {
  873.        SendStringToMci( "set cd time format milliseconds wait" );
  874.        sprintf( achMciSnd, "status cd length track %i wait", i+1 );
  875.        SendStringToMci( achMciSnd, (HWND) NULL, 0 );
  876.        aCDTitel[i].lMillisec = atol( achReturn );
  877.  
  878.        SendStringToMci( "set cd time format msf wait" );
  879.        sprintf( achMciSnd, "status cd length track %i wait", i+1 );
  880.        SendStringToMci( achMciSnd, (HWND) NULL, 0 );
  881.        strcpy(aCDTitel[i].acLaenge, achReturn );
  882.   }
  883.  
  884.   SendStringToMci( "set cd time format msf wait" );
  885.  
  886.   /* Container füllen */
  887.   for( i=0; i<lNumOfTracks; i++ )
  888.   {
  889.     rcfirst = (PRECORDCORE) WinSendMsg( hwndContainer, CM_ALLOCRECORD, (MPARAM) ((CNR_COLUMN_NUM) * sizeof(DATEN)), (MPARAM) 1 );
  890.  
  891.     aCDTitel[i].prcCnrDaten = rcfirst;
  892.  
  893.     pri = (DATEN *)(((BYTE *) rcfirst) + sizeof(RECORDCORE));
  894.     pri--;
  895.  
  896.     pri[0].lWert     = i+1;
  897.     pri[1].pszString = aCDTitel[i].acTitel;
  898.     pri[2].pszString = aCDTitel[i].acAutor;
  899.     pri[3].pszString = aCDTitel[i].acLaenge;
  900.     pri[4].pszString = aCDTitel[i].acMusik;
  901.     pri[5].pszString = aCDTitel[i].acText;
  902.     pri[6].pszString = aCDTitel[i].acRichtung;
  903.     pri[7].pszString = aCDTitel[i].acAusgabe;
  904.     pri[8].pszString = aCDTitel[i].acBemerkung;
  905.     pri[9].lWert     = aCDTitel[i].lMillisec;
  906.  
  907.     memset( &rii, 0, sizeof(rii) );
  908.     rii.cb                = sizeof(RECORDINSERT);
  909.     rii.pRecordOrder      = (PRECORDCORE) CMA_END;
  910.     rii.pRecordParent     = (PRECORDCORE) NULL;
  911.     rii.zOrder            = CMA_TOP;
  912.     rii.cRecordsInsert    = 1;
  913.     rii.fInvalidateRecord = TRUE;
  914.    
  915.     WinSendMsg( hwndContainer, CM_INSERTRECORD, (MPARAM) rcfirst, (MPARAM) &rii );
  916.  
  917.   }
  918.  
  919.   /* Containertitel aktualisieren */
  920.   memset( &cnri, 0, sizeof(cnri));
  921.   cnri.pszCnrTitle = acCDTitel;
  922.   cnriFlags        = CMA_CNRTITLE;
  923.   WinSendMsg( hwndContainer, CM_SETCNRINFO, (MPARAM) &cnri, (MPARAM) cnriFlags );
  924.  
  925.   /* Spielzeit des ersten Liedes in Eingabefeld übertragen */
  926.   WinSetWindowText( hwndEFLaenge, aCDTitel[0].acLaenge );
  927.   WinSetWindowText( hwndEFAktuell, "01:00:00:00" );
  928.  
  929.   /* Scrollbar setzten */
  930.   sSec = (SHORT)(aCDTitel[0].lMillisec / 1000);
  931.   WinSendMsg( hwndScrollbar, SBM_SETSCROLLBAR, (MPARAM) 0, MPFROM2SHORT( 0, sSec ) );
  932.   WinSendMsg( hwndScrollbar, SBM_SETTHUMBSIZE, MPFROM2SHORT(1, sSec), (MPARAM) NULL );
  933.  
  934.   /* Checkbutton setzten */
  935.   bIsLinked = TRUE;
  936.   WinSendMsg( hwndCheckbox, BM_SETCHECK, (MPARAM) bIsLinked, (MPARAM) NULL );
  937.  
  938.   bIsMediaPres = TRUE;
  939.   WinEnableWindowUpdate( hwndCdplayer, TRUE );
  940.   WinShowWindow( hwndCdplayer, TRUE );
  941.  
  942. }
  943.  
  944.  
  945. /*
  946.  * CdpClearAudioCDInfo.
  947.  */
  948.  
  949. VOID CdpClearAudioCDInfo( VOID )
  950. {
  951.   bIsMediaPres = FALSE;
  952.  
  953.   /* "Mehr" Dialog schließen, falls noch aktiv ... */
  954.   if( bIsMehr )
  955.       WinSendMsg( hwndCdmehr, WM_CLOSE, (MPARAM) NULL, (MPARAM) NULL );
  956.  
  957.   WinEnableWindowUpdate( hwndCdplayer, FALSE );
  958.  
  959.   /* Eingabefeldinhalt löschen */
  960.   WinSetWindowText( hwndEFCDTitel, "" );
  961.   WinSetWindowText( hwndEFCDID   , "" );
  962.   WinSetWindowText( hwndEFAutor  , "" );
  963.   WinSetWindowText( hwndEFTitel  , "" );
  964.   WinSetWindowText( hwndEFLaenge , "" );
  965.   WinSetWindowText( hwndEFAktuell, "" );
  966.  
  967.   /* Scrollbar zurücksetzten  */
  968.   WinSendMsg( hwndScrollbar, SBM_SETSCROLLBAR, (MPARAM) 0, (MPARAM) MPFROM2SHORT( 0, 0 ) );
  969.   WinSendMsg( hwndScrollbar, SBM_SETTHUMBSIZE, MPFROM2SHORT(0, 0), (MPARAM) NULL );
  970.  
  971.   /* Spinbutton zurücksetzten */
  972.   WinSendMsg( hwndSpinbutton, SPBM_SETLIMITS, (MPARAM) 0, (MPARAM) 0 );
  973.  
  974.   /* Checkbutton zurücksetzten */
  975.   bIsLinked = FALSE;
  976.   WinSendMsg( hwndCheckbox, BM_SETCHECK, (MPARAM) bIsLinked, (MPARAM) NULL );
  977.  
  978.   /* Container zurücksetzten  */
  979.   memset( &cnri, 0, sizeof(cnri));
  980.   cnri.pszCnrTitle = "Legen Sie bitte eine Audio-CD ein ..."; 
  981.   cnriFlags        = CMA_CNRTITLE;
  982.  
  983.   lNumOfTracks = 0;
  984.  
  985.   WinSendMsg( hwndContainer, CM_SETCNRINFO, (MPARAM) &cnri, (MPARAM) cnriFlags );
  986.   WinSendMsg( hwndContainer, CM_REMOVERECORD, (MPARAM) NULL, MPFROM2SHORT(0, (CMA_FREE | CMA_INVALIDATE) ) );
  987.  
  988.   CdpEnableObjects( FALSE );
  989.   WinEnableWindowUpdate( hwndCdplayer, TRUE );
  990.   WinShowWindow( hwndCdplayer, TRUE );
  991. }
  992.  
  993.  
  994. /*
  995.  * CdpEnableObjects.
  996.  */
  997.  
  998. VOID CdpEnableObjects( BOOL bFlag )
  999. {
  1000.   WinEnableWindow( hwndContainer , bFlag );
  1001.   WinEnableWindow( hwndSpinVolume, bFlag );
  1002.   WinEnableWindow( hwndSpinbutton, bFlag );
  1003.   WinEnableWindow( hwndScrollbar , bFlag );
  1004.   WinEnableWindow( hwndCheckbox  , bFlag );
  1005.   WinEnableWindow( hwndEFCDTitel , bFlag );
  1006.   WinEnableWindow( hwndEFCDID    , bFlag );
  1007.   WinEnableWindow( hwndEFAutor   , bFlag );
  1008.   WinEnableWindow( hwndEFTitel   , bFlag );
  1009.   WinEnableWindow( hwndEFLaenge  , bFlag );
  1010.   WinEnableWindow( hwndEFAktuell , bFlag );
  1011.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_PLAY        ), bFlag );
  1012.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_PAUSE       ), bFlag );
  1013.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_STOP        ), bFlag );
  1014.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_START       ), bFlag );
  1015.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_REWIND      ), bFlag );
  1016.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_SECBACKWARD ), bFlag );
  1017.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_SECFORWARD  ), bFlag );
  1018.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_FORWARD     ), bFlag );
  1019.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_END         ), bFlag );
  1020.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_EJECT       ), bFlag );
  1021.   WinEnableWindow( WinWindowFromID( hwndCdplayer, ID_PB_MEHR        ), bFlag );
  1022. }
  1023.  
  1024.  
  1025. /*
  1026.  * SendStringToMCI.
  1027.  */
  1028.  
  1029. ULONG SendStringToMCI( PSZ pszCmd, HWND hwndNotify, USHORT usUserParam )
  1030. {
  1031.   USHORT usResult;
  1032.   ULONG ulRet, lErr;
  1033.  
  1034.   memset( achReturn, 0, MCI_RETURN_STRING_LENGTH );
  1035.   memset( achError , 0, MCI_ERROR_STRING_LENGTH );
  1036.  
  1037.   while( ulRet = mciSendString( pszCmd, achReturn, MCI_RETURN_STRING_LENGTH, hwndNotify, usUserParam ) )
  1038.   {
  1039.     lErr = mciGetErrorString( ulRet, achError, MCI_ERROR_STRING_LENGTH );
  1040.  
  1041.     if( lErr != MCIERR_SUCCESS ) /* Fehler bei Fehlerauswertung */
  1042.     {
  1043.         strcpy( achError, "Es ist ein Fehler bei der Fehlerauswertung aufgetreten." );
  1044.     }
  1045.     usResult = WinMessageBox( HWND_DESKTOP, hwndNotify, achError, pszCmd, 1000, MB_ABORTRETRYIGNORE | MB_MOVEABLE | MB_APPLMODAL | MB_INFORMATION );
  1046.     switch( usResult ) {
  1047.       case MBID_ABORT:
  1048.            WinSendMsg( hwndCdplayer, WM_CLOSE, (MPARAM) NULL, (MPARAM) NULL );
  1049.       case MBID_IGNORE:
  1050.            return(ulRet);
  1051.     }
  1052.   }
  1053.   return(ulRet);
  1054. }
  1055.  
  1056. VOID CdpUpdateAktuell( VOID )
  1057. {
  1058.   LONG lTrack, lMinuten, lSekunden, lMaxMin, lMaxSec;
  1059.  
  1060.   SendStringToMci( "set cd time format tmsf wait", hwndCdplayer, 0 );
  1061.   SendStringToMci( "status cd position wait" );
  1062.  
  1063.   lTrack    = atol( achReturn );
  1064.   lMinuten  = atol( achReturn+3 );
  1065.   lSekunden = atol( achReturn+6 );
  1066.  
  1067.   lMaxMin   = atol( aCDTitel[lTrack-1].acLaenge   );
  1068.   lMaxSec   = atol( aCDTitel[lTrack-1].acLaenge+3 );
  1069.  
  1070.   WinSetWindowText( hwndEFAktuell, achReturn );
  1071.  
  1072.   if( lTrack != lCurrTrack )
  1073.   {
  1074.       CdpUpdateTrack( lTrack, CDP_KEEPTIME );
  1075.   }
  1076.   else
  1077.   {
  1078.       WinSendMsg( hwndScrollbar, SBM_SETPOS, MPFROMSHORT(lMinuten*60+lSekunden), (MPARAM) NULL );
  1079.   }
  1080.  
  1081.   if( lTrack == lNumOfTracks && lSekunden >= lMaxSec && lMinuten >= lMaxMin )
  1082.       WinSendMsg( hwndCdplayer, WM_COMMAND, (MPARAM) ID_PB_START, (MPARAM) NULL );
  1083.  
  1084. }
  1085.  
  1086. VOID CdpUpdateTrack( LONG lTrack, LONG lFlag )
  1087. {
  1088.   LONG lMinuten, lSekunden, lLocal;
  1089.   SHORT sSec;
  1090.   RECTL rct, vrct;
  1091.   QUERYRECORDRECT qrrct;
  1092.   
  1093.   WinSetPointer ( HWND_DESKTOP, hptrWait );
  1094.  
  1095.   if( bIsLinked )
  1096.       lLocal = lUnlinkedTrack = lCurrTrack = lTrack;
  1097.   else if( lFlag & CDP_KEEPTIME )
  1098.       lCurrTrack = lTrack;
  1099.   else 
  1100.       lUnlinkedTrack = lTrack;
  1101.  
  1102.   if( bIsLinked || lFlag & CDP_UPDATETEXTONLY )
  1103.   {
  1104.       if( !(lFlag & CDP_KEEPTIME) )
  1105.           lLocal = lUnlinkedTrack;
  1106.       else
  1107.           lLocal = lCurrTrack;
  1108.     
  1109.       WinSendMsg( hwndSpinbutton, SPBM_SETCURRENTVALUE, (MPARAM) lLocal, (MPARAM) NULL );
  1110.  
  1111.       if( !(lFlag & CDP_NOCNRUPDATE ) )
  1112.       {
  1113.           /* Der Datensatz wird im Container aktiviert */
  1114.           WinSendMsg( hwndContainer, CM_SETRECORDEMPHASIS, (MPARAM) aCDTitel[lLocal-1].prcCnrDaten, MPFROM2SHORT( TRUE, CRA_SELECTED | CRA_CURSORED ) );
  1115.  
  1116.           /* Liegt der aktive Datensatz im unsichtbaren Bereich des Containers, so muß gescrollt werden */
  1117.           qrrct.cb = sizeof(QUERYRECORDRECT);
  1118.           qrrct.pRecord = (PRECORDCORE) aCDTitel[lLocal-1].prcCnrDaten;
  1119.           qrrct.fRightSplitWindow = FALSE;
  1120.           qrrct.fsExtent = CMA_TEXT;
  1121.  
  1122.           WinSendMsg( hwndContainer, CM_QUERYRECORDRECT, (MPARAM) &rct, (MPARAM) &qrrct );
  1123.           WinSendMsg( hwndContainer, CM_QUERYVIEWPORTRECT, (MPARAM) &vrct, MPFROM2SHORT( CMA_WINDOW, FALSE ) );
  1124.  
  1125.           if( vrct.yBottom > rct.yBottom )
  1126.               WinSendMsg( hwndContainer, CM_SCROLLWINDOW, (MPARAM) CMA_VERTICAL, (MPARAM) (vrct.yBottom-rct.yBottom) );
  1127.           else if( vrct.yTop < rct.yTop )
  1128.               WinSendMsg( hwndContainer, CM_SCROLLWINDOW, (MPARAM) CMA_VERTICAL, (MPARAM) (vrct.yTop-rct.yTop) );
  1129.       }
  1130.  
  1131.       WinSetWindowText( hwndEFAutor,   aCDTitel[lLocal-1].acAutor  );
  1132.       WinSetWindowText( hwndEFTitel,   aCDTitel[lLocal-1].acTitel  );
  1133.       WinSetWindowText( hwndEFLaenge,  aCDTitel[lLocal-1].acLaenge );
  1134.   }
  1135.  
  1136.   if( !(lFlag & CDP_UPDATETEXTONLY ) )
  1137.   {
  1138.       if( lFlag & CDP_KEEPTIME )
  1139.       {
  1140.           SendStringToMci( "set cd time format tmsf wait", hwndCdplayer, 0 );
  1141.           SendStringToMci( "status cd position wait" );
  1142.  
  1143.           lMinuten  = atol( achReturn+3 );
  1144.           lSekunden = atol( achReturn+6 );
  1145.  
  1146.           WinSetWindowText( hwndEFAktuell, achReturn );
  1147.  
  1148.           sSec = (SHORT)(aCDTitel[lCurrTrack-1].lMillisec / 1000);
  1149.           WinSendMsg( hwndScrollbar, SBM_SETSCROLLBAR, (MPARAM) (lMinuten*60+lSekunden), MPFROM2SHORT( 0, sSec ) );
  1150.           WinSendMsg( hwndScrollbar, SBM_SETTHUMBSIZE, MPFROM2SHORT(1, sSec), (MPARAM) NULL );
  1151.       }
  1152.       else
  1153.       {
  1154.           sSec = (SHORT)(aCDTitel[lCurrTrack-1].lMillisec / 1000);
  1155.           WinSendMsg( hwndScrollbar, SBM_SETSCROLLBAR, (MPARAM) 0, MPFROM2SHORT( 0, sSec ) );
  1156.           WinSendMsg( hwndScrollbar, SBM_SETTHUMBSIZE, MPFROM2SHORT(1, sSec), (MPARAM) NULL );
  1157.     
  1158.           SendStringToMci( "set cd time format tmsf wait", hwndCdplayer, 0 );
  1159.           sprintf( achMciSnd, "seek cd to %i:00:00:00 wait", lCurrTrack );
  1160.           SendStringToMci( achMciSnd, hwndCdplayer, 0 );
  1161.           SendStringToMci( "status cd position wait", hwndCdplayer, 0 );
  1162.           WinSetWindowText( hwndEFAktuell, achReturn );
  1163.  
  1164.           if( bIsPlaying )
  1165.               SendStringToMci( "play cd", hwndCdplayer, 0 );
  1166.       }
  1167.   }
  1168.  
  1169.   WinSetPointer ( HWND_DESKTOP, hptrArrow );
  1170. }
  1171.  
  1172. /* MehrDlgProc. */
  1173. MRESULT EXPENTRY MehrDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  1174. {
  1175.   USHORT   id;
  1176.   ULONG    ni;
  1177.   SHORT    nc;
  1178.   static LONG lEditTrack;
  1179.  
  1180.    switch( msg ) {
  1181.      case WM_INITDLG :
  1182.           hwndCdmehr     = hwnd;
  1183.           hwndEFMusik    = WinWindowFromID( hwnd, ID_EF_MUSIK        );
  1184.           hwndEFText     = WinWindowFromID( hwnd, ID_EF_TEXT         );
  1185.           hwndEFRichtung = WinWindowFromID( hwnd, ID_EF_RICHTUNG     );
  1186.           hwndEFTakte    = WinWindowFromID( hwnd, ID_EF_TAKTE        );
  1187.           hwndEFAusgabe  = WinWindowFromID( hwnd, ID_EF_AUSGABE      );
  1188.           hwndMLEBemerk  = WinWindowFromID( hwnd, ID_MLE_BEMERKUNGEN );
  1189.  
  1190.           WinSendMsg( hwndEFMusik   , EM_SETTEXTLIMIT,  (MPARAM)  128, (MPARAM) NULL );
  1191.           WinSendMsg( hwndEFText    , EM_SETTEXTLIMIT,  (MPARAM)  128, (MPARAM) NULL );
  1192.           WinSendMsg( hwndEFRichtung, EM_SETTEXTLIMIT,  (MPARAM)  128, (MPARAM) NULL );
  1193.           WinSendMsg( hwndEFTakte   , EM_SETTEXTLIMIT,  (MPARAM)  128, (MPARAM) NULL );
  1194.           WinSendMsg( hwndEFAusgabe , EM_SETTEXTLIMIT,  (MPARAM)   30, (MPARAM) NULL );
  1195.           WinSendMsg( hwndMLEBemerk , MLM_SETTEXTLIMIT, (MPARAM) 4096, (MPARAM) NULL );
  1196.  
  1197.           lEditTrack = (LONG) mp2;
  1198.  
  1199.           WinSetWindowText( hwndEFMusik,    aCDTitel[lEditTrack-1].acMusik     );
  1200.           WinSetWindowText( hwndEFText,     aCDTitel[lEditTrack-1].acText      );
  1201.           WinSetWindowText( hwndEFRichtung, aCDTitel[lEditTrack-1].acRichtung  );
  1202.           WinSetWindowText( hwndEFTakte,    aCDTitel[lEditTrack-1].acTakte     );
  1203.           WinSetWindowText( hwndEFAusgabe,  aCDTitel[lEditTrack-1].acAusgabe   );
  1204.           WinSetWindowText( hwndMLEBemerk,  aCDTitel[lEditTrack-1].acBemerkung );
  1205.  
  1206.           return( (MRESULT) 0);
  1207.  
  1208.      case WM_COMMAND:
  1209.           switch( SHORT1FROMMP(mp1) ){
  1210.             case ID_PB_SPEICHERN:
  1211.                  WinQueryWindowText( hwndEFMusik,    128, aCDTitel[lEditTrack-1].acMusik     );
  1212.                  WinQueryWindowText( hwndEFText,     128, aCDTitel[lEditTrack-1].acText      );
  1213.                  WinQueryWindowText( hwndEFRichtung, 128, aCDTitel[lEditTrack-1].acRichtung  );
  1214.                  WinQueryWindowText( hwndEFTakte,    128, aCDTitel[lEditTrack-1].acTakte     );
  1215.                  WinQueryWindowText( hwndEFAusgabe,   30, aCDTitel[lEditTrack-1].acAusgabe   );
  1216.                  WinQueryWindowText( hwndMLEBemerk, 4096, aCDTitel[lEditTrack-1].acBemerkung );
  1217.                  WinDismissSecondaryWindow( hwnd, lEditTrack );
  1218.                  sprintf( acBuffer, "MUSIK%i", lEditTrack );
  1219.                  PrfWriteProfileString( hiniCdplayer, acHexID, acBuffer, aCDTitel[lEditTrack-1].acMusik );
  1220.                  sprintf( acBuffer, "TEXT%i", lEditTrack );
  1221.                  PrfWriteProfileString( hiniCdplayer, acHexID, acBuffer, aCDTitel[lEditTrack-1].acText );
  1222.                  sprintf( acBuffer, "RICHTUNG%i", lEditTrack );
  1223.                  PrfWriteProfileString( hiniCdplayer, acHexID, acBuffer, aCDTitel[lEditTrack-1].acRichtung );
  1224.                  sprintf( acBuffer, "TAKTE%i", lEditTrack );
  1225.                  PrfWriteProfileString( hiniCdplayer, acHexID, acBuffer, aCDTitel[lEditTrack-1].acTakte );
  1226.                  sprintf( acBuffer, "AUSGABE%i", lEditTrack );
  1227.                  PrfWriteProfileString( hiniCdplayer, acHexID, acBuffer, aCDTitel[lEditTrack-1].acAusgabe );
  1228.                  sprintf( acBuffer, "BEMERKUNG%i", lEditTrack );
  1229.                  PrfWriteProfileString( hiniCdplayer, acHexID, acBuffer, aCDTitel[lEditTrack-1].acBemerkung );
  1230.                  break;
  1231.             case ID_PB_ABBRECHEN:
  1232.                  WinDismissSecondaryWindow( hwnd, FALSE );
  1233.                  break;
  1234.             default:
  1235.                  break;
  1236.           }
  1237.           return (MRESULT) 0;
  1238.  
  1239.      case WM_CLOSE :
  1240.           return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2 ) );
  1241.  
  1242.      default:
  1243.           return( WinDefSecondaryWindowProc( hwnd, msg, mp1, mp2));
  1244.    }
  1245. }
  1246.  
  1247.