home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 13 / AACD13.ISO / AACD / Utilities / ACDPlay / src / V1.6 / ACDPlay.c.BAK < prev    next >
Text File  |  1998-07-22  |  76KB  |  2,278 lines

  1. /*************************************************************************
  2.  
  3.         |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
  4.         |            ACDPlay - Utility              |
  5.         |           -------------------             |
  6.         |                                           |
  7.         |            Version 1.6                    |
  8.         |___________________________________________|
  9.  
  10.    Autoren  :    Marc Altmann  [MC3]
  11.         Martin Kresse [mak]
  12.    Copyright:    E-Mailware
  13.  
  14.    Was:        ACDPlay ist ein fantastisches Utility zum Abspielen von
  15.         CDDA-Disks auf SCSI-CD-ROM-Laufwerken.
  16.  
  17.    Umgebung :    Maxon C++ light 3.10.1 auf Amiga 12oo OS3.0 68o3o 2MB Chip 8MB Fast
  18.  
  19.    Status   :    letzte öffentliche Version 1.5
  20.            nächste geplante öffentliche Version 1.6
  21.  
  22.    Bugs     :    Manchmal werden die Parameter von ShowMsgA() in der Shell
  23.         falsch angezeigt
  24.  
  25.  
  26. Autor    Version        Datum        Veränderungen
  27. ------- ---------     --------    ------------------------------------------
  28. MC3    0.1        22.06.96    Ersterstellung (Programmgerüst)
  29.  
  30. mak    0.11        19.09.96    Sourcecode überarbeitet
  31.                     - ShowMsg() dazu
  32.             20.09.96    - OpenLibs() / CloseLibs() dazu
  33.                     - GetMem() / FreeAllMem() dazu
  34.                     - InitCDStruct() / FreeCDStruct() dazu
  35.  
  36. mak    0.12        22.09.96    - OpenApplication() dazu
  37.                     - SetDefaultApplication() vorläufig dazu
  38.                     - OpenApplicationWindow() dazu
  39.             24.09.96    - CloseApplication() dazu
  40.                     - CloseAppWin() dazu
  41.                     - TextWidth() dazu
  42.             26.09.96    - GetMem / FreeAllMem entfernt
  43.                     - CreateApplication() dazu
  44.                     - ReadConfig() dazu
  45.  
  46. MC3    0.13        28.09.96    - IDCMP-Verwaltung implementiert
  47.                     - HandleEvents() dazu (nur rudimentär)
  48.                     - erste Commodity-Eigenschaften (Entfernen)
  49.                     - HandleCommodityEvents() dazu
  50.             29.09.96    - Weitere Commodity-Eigenschaften (Verbergen, Sichtbar)
  51.                     - Hotkey-fähig
  52.                     - CX_PRIORITY-, CX_POPUP-, CX_POPKEY-Unterstützung
  53.  
  54. MC3    0.14        30.09.96    - MakeMenus() dazu (Behelfsversion)
  55.                     - HandleEvents() um MENUPICK-Events ausgebaut
  56.             02.10.96    - MakeMenus() in geplanter Form
  57.                     - FindWidest() dazu
  58.             03.10.96    - About-Window fertiggestellt
  59.                     - Init/OpenCDStruct() und FreeCDStruct() verändert
  60.             04.10.96    - Laufwerksinformationsfenster fertiggestellt
  61.  
  62. mak    0.15        07.10.96    - Konstante STDWINDOWFLG eingeführt
  63.                     - ReadConfig() greift notfalls auf Defaultwerte aus
  64.                     - SaveConfig() und FreeConfig() dazu
  65.             08.10.96    - GetVec() dazu
  66.                     - main() Struktur überarbeitet
  67.                       (keine Enforcer-Hits mehr)
  68.             10.10.96    - Read- und SaveConfig() fertiggestellt
  69.                     - CreateApp.() benutzt jetzt cfg-Struktur
  70.                     - CX-Bug in CreateApp.() entfernt
  71.             11.10.96    - HandleEvents() unterstüzt jetzt "Multi-Selection"
  72.                     - Parameter *Window aus ShowMsg genommen
  73.                     - AllocVec´s() in GetVec´s() geändert
  74.  
  75. mak    0.16.a        12.10.96    - WindowToFront() u. ActivateWindow()
  76.                       sind jetzt in OpenAppWin() integriert
  77.  
  78. mak    0.17.a        12.10.96    - Das EXECUTABLE-Flag wird jetzt bei
  79.                       SaveConfig() gelöscht
  80.                     - Bug in SaveConfig() (wenn app=NULL) entfernt
  81.                     - Bug in HandleEvents() entfernt
  82.                       (wenn Multi-Selection: 1.Verbergen 2.Über)
  83.  
  84. MC3    0.17b        14.10.96    - CxFilter und CxSender zur Timer-Event-Synchronisation
  85.                       erstellt (jede 1/10-Sekunde)
  86.                     - CD- und Laufwerks-Fenster jetzt zusätzlich mit Textgadgets,
  87.                       zur besseren Aktualisierung (beim LW-Fenster unnötig)
  88.                     - Bug in der Hauptschleife behoben. Ein 'done = TRUE' in
  89.                       HandleEvents() wurde mitunter in HandleCommodityEvents()
  90.                       wieder rückgängig gemacht.
  91.                     - FlushMessages() dazu - beantwortet alle Messages eines Ports
  92.  
  93. MC3    0.18        16.10.96    - Gadgets im Hauptfenster fertiggestellt. Durch ein Flag-Word
  94.                       in der Application-Struktur können die einzelnen Reihen mit
  95.                       Bedienungselementen an- oder ausgeschaltet werden.
  96.  
  97. mak    0.19        17.10.96    - einige nichtüberprüfte GetVecs() überarbeitet
  98.                     - SCSI_DEVICE Check in OpenCDStruct() eingebaut
  99.                     - einige überflüssige Befehle entfernt
  100.             18.10.96    - ToolTypes werden jetzt auch gelesen
  101.                     - OpenApplication holt den Screen nach vorne falls
  102.                       die Application schon offen ist
  103.                     - Screennotify-Unterstützung für Open/CloseWorkBench()
  104.                     - Application.Flags kann frei benutzt werden
  105.  
  106. MC3    0.20        19.10.96    - MakeInterior() und UpdateGadgets() erweitert (Fenstertitel)
  107.                     - Menü des Hauptfensters erweitert. Kontrolle der GUI-Elemente
  108.                       nun über Menü möglich
  109.                     - Bug in CloseAppWin() behoben. Bei FreeVec() usw. wurden die
  110.                       Zeiger nicht auf NULL gesetzt
  111.                     - Wenn keine GUI-Elemente angegeben werden, wird das Fenster als
  112.                       Titelzeile *ohne* Zoom-Gadget göffnet
  113.             20.10.96    - Neues Tooltype: PUBSCREEN
  114.                     - PubScreen-Fenster eingebaut (stürzt manchmal ab!)
  115.                     - Allerlei Listenfunktionen erstellt
  116.             21.10.96    - Abstürz-Bug entfernt (siehe 20.10)
  117.                     - GetPubScreenList() und KillPubScreenList() an das
  118.                       Application-Konzept angepaßt
  119.             22.10.96    - Eine Reihe von Abspielfunktionen eingebaut, die sich hoffentlich
  120.                       für AREXX eignen.
  121.  
  122. ???    0.21        ???            ???
  123.  
  124. mak    0.22        24.10.96    - InitList() durch NewList() aus amiga.lib ersetzt
  125.                     - ClearMenuStrip steht jetzt vor CloseWindow() (keine Enforcerhits mehr)
  126.                     - Statusflags in Source eingefügt
  127.                     - das Pubscreen-Fenster wird jetzt richtig aufgefrischt (ohne GimmeZeroZero)
  128.             26.10.96    - Programm lokalisiert
  129.                     - testweise Drive-Info Fenster verändert
  130.  
  131. MC3    0.23        26.10.96    - Gadgets werden beim Öffnen des Fensters geshadet
  132.                     - Trackslider funktioniert (noch nicht ganz bugfrei)
  133.                     - ACDPlay_cat.c ab jetzt überflüssig
  134.             27.10.96    - Bugfix: Wenn die CD zuende war, spielte der Trackslider verrückt
  135.                     - Bugfix: Trackslider-Level wird in MakeGadgets() gesetzt
  136.     0.24        06.11.96    - Alpha-CD-Titel-Verwaltung implementiert
  137.                     - Aktualisierung der Zeitanzeige (pro Sekunde ein neues Gadget - krass!)
  138.                     - KillPubScreenList() entfernt, dafür FreeList() eingeführt
  139.             07.11.96    - Fenstertitel arbeitet jetzt mit wirklichen CD-Namen (UpdateWinTitle())
  140.                     - Kein Flackern mehr beim Pausegadget-Refresh (außerdem: eigene Funktion)
  141.                     - NewSize-Events werden jetzt durch ManageNewSize() gehandhabt
  142.                     - Neues Fenster: Titelauswahl
  143.     0.25        09.11.96    - VANILLAKEY-Support für Direktwahlbuttons
  144.             10.11.96    - Neues Fenster: Titeleingabe (funktioniert!)
  145.                     - In den Info-Fenstern werden Intuitexte jetzt weiß gezeichnet
  146.                     - Index-Anzeige zeigt jetzt '1' beim Spielen an... Fake!  ;-)
  147.  
  148.     0.26        11.11.96    - Neues Tooltype: HOTKEYCAUSES
  149.                     - GetPubScreenName() holt sich einen bestimmten Screennamen
  150.                     - kleine Bugfixes (von >>>mak<<< erwünscht :-)
  151.                     - Im Titelauswahl- und Pubscreenfenster jetzt Doppelklick
  152.                       notwendig, um ein Element auszuwählen
  153.  
  154. mak    0.26b        11.11.96    - Bug in OpenCDStruct() entfernt (zehnstellige Unitnummer :-)
  155.  
  156. MC3    0.27        13.11.96    - Zwei neue Tooltypes: USEWINDOWBAR und USESCREENBAR
  157.                     - Zeitanzeige mit 4 verschiedenen Modi implementiert
  158.                     - Alle Fenster benutzen denselben Menustrip
  159.                     - Code-Ersparnisse in MakeMenus() und HandleEvents()
  160.                     - Cursortasten können benutzt werden (ausprobieren!)
  161.  
  162. mak    0.28        18.11.96    - AsmLib eingeführt, welche OpenLibs(), CloseLibs(), ShowMsg()
  163.                       GetVec(), FlushMessages() und MyFormat() (jetzt FormatA()) durch Assemblerroutinen
  164.                       (z.B. ShowMsgA()) ersetzt. Die Parameter bleiben wie gehabt.
  165.                     - ARexxPort (in AsmLib) integriert
  166.  
  167. MC3    0.29        19.11.96    - Trackwiederholung eingebaut (Problem beim letzten Track)
  168.                     - Schreiben und Lesen von Titeldaten implementiert;
  169.                       Pfad als Tooltype DISKPATH angeben oder "ACDPlay:Disks/"
  170.                     - AllocDosObject()-Einsatz auch in ReadConfig()
  171.  
  172.                     21.11.96    - Bugfix: Wiederholung funktioniert jetzt (bis auf letzter Track)
  173.                                 - Bugfix: Die Cycle-Gadgets zeigen jetzt den richtigen Modus an,
  174.                                   wenn sie erneut erzeugt werden.
  175.                                 - Bugfix: Jede Sekunde wurden 2 * sizeof(Gadget) Bytes 'gefressen'
  176.                                 - Wiederholung Track und Alles funktionieren vollständig (nach
  177.                                   Deinem System)
  178.  
  179.     mak        0.30    23.11.96    - ARexx endlich fertig und integriert (Errorrückgabe muß ich mir noch überlegen)
  180.                                   ACDPlay kennt jetzt: PLAY STOP EJECT NEXTSONG PREVSONG SHOW HIDE und QUIT
  181.                                 - FindARexxPortA() am Anfang eingefügt
  182.  
  183.     MC3        0.31    29.11.96    - Programmierung implementiert (Arexx-günstig)
  184.                     30.11.96    - Bugfixes
  185.  
  186.     mak        0.32    30.11.96    - Volumewindow (z.Z. noch ohne Funktion) eingebaut
  187.                                 - Menupunkt Fixieren funktioniert jetzt
  188.                                 - Bugfix: Absturz im Editwindow wenn Programmwindow nicht offen war
  189.  
  190.     MC3        0.33    07.12.96    - Zufallsmodus eingebaut
  191.                                 - Fixieren fixiert jetzt auch Fenstergrößen
  192.                                 - Volume-Fenster und A-B-Repeat ausgeklammert
  193.                                 - CD-Info-Fenster entsprechend Device-Info-Fenster geändert
  194.  
  195.             0.34    08.12.96    - Neues Tooltype: MAGICWB
  196.                                 - MagicWB-Toggle-Menü funktioniert
  197.                                 - FakeRequestA() bei drei Fenstern eingesetzt (sieht gut aus!)
  198.  
  199.             1.0        14.12.96    - SEARCHSECONDS-Tooltype
  200.                                 - ein paar Bugs weg, Catalogs geändert
  201.  
  202.     mak        1.0b    15.12.96    - Bugfix in MakeInterior (EnforcerHits)
  203.                                 - Volumeüberreste auskommentiert
  204.  
  205.     MC3        1.01a    01.01.97    - 'Update'-Button im Pubscreen-Fenster
  206.                                 - Funktion AdjustNewSize() für zukünftige Sizing-Wins
  207.                                 - In MakeVisuals() (ehem. MakeGadgets()) aufgeräumt
  208.                     02.01.97    - Die beiden Info-Fenster sind jetzt größenveränderbar
  209.                     04.01.97    - Das About-Fenster scrollt jetzt - mußte dazu leider die
  210.                                   Parameter bei TextWidth() und FindWidest() ändern.
  211.                                 - Nicht-aktualisierte-Titel-Bug ist weg... :-)
  212.             1.01ß    05.01.97    - numeric-Keypad-Bug ist weg!  :-)
  213.                                 - Neue Menüs
  214.  
  215.             1.1        26.01.97    - Config-Teil total verändert
  216.                                 - wahnsinnig viel anderes verändert :-)    (2 Tooltypes)
  217.                                 - CLI-Parameter
  218.  
  219.             1.12    29.01.97    - AppIcon
  220.  
  221.     mak        1.3        02.02.97    - Play überspringt Datentracks am Anfang
  222.                                 - viele CDPlayLib-Funktionen durch eigene ersetzt
  223.                     03.02.97    - Bug in ChangeButtonText() und ReadArguments() entfernt
  224.                     08.02.97    - restliche CD-Routinen ersetzt
  225.                                 - einige Optimierungen im Source
  226.  
  227.     MC3        1.31    14.02.97    - ChangeButtonText() optimiert (ein ½ Hack!) + Asm
  228.                                 - Richtige Searchbuttons... (und Trackslider)
  229.                                   (Ich weiß leider nicht, wie Du das im SCSI-Test-Programm
  230.                                   implementiert hattest. Wenn es besser war, bitte ersetzen)
  231.                                 - den Betatestern gegeben
  232.  
  233.             1.32    16.02.97    - "PROGDIR:ARexx" wird im ARexx-Menü angezeigt
  234.                                 - "Execute ARexx..." geht. mit Asl-Requester (nur mit asl.lib)
  235.  
  236.             1.33    16.02.97    - Neues Fenster A-B-Repeat: Vorsicht mit dem Konfig-File! Wenn man
  237.                                   ein neues Konfig-File hat und ein altes ACDP lädt, stürzt es ab(!)
  238.                                 - Lokalisiert (catalogs version 2)
  239.  
  240.             1.34    17.02.97    - Programm- und
  241.                     19.02.97    - Titeleingabefenster sind jetzt größenveränderbar
  242.  
  243.     mak        1.35    01.03.97    - ExecuteARexx() funktioniert jetzt in Asm
  244.                                 - Bugs in CloseApplication(), ReadConfig(), GetDir() und CreateAppIcon() beseitigt
  245.                                 - ARexxfunktionen geben jetzt endlich definierte Rückgabewerte zurück
  246.                                 - cdplay.library vollständig eleminiert
  247.                                 - NULL-test in einige Funktionen eingebaut
  248.  
  249.     MC3        1.36    11.03.97    - A-B-Repeat funktioniert
  250.                                 - alte ChangeButtonText()-Funktion
  251.                                 - []-Bug entfernt (hoffentlich!)
  252.                                 - setzen der Statusflags (im Source) vergessen... :-(
  253.  
  254.     mak        1.37    12.03.97    - Eject funktioniert jetzt richtig
  255.                                 - Laufwerkssperre und Unit/LUN-Wechsel funktionieren jetzt
  256.                                 - ACDPlay spult jetzt nicht mehr selbstständig
  257.                                 - MathLib Check entfernt: nutzte nichts :-(
  258.                     13.03.97    - an einige Betatester gegeben
  259.  
  260.     MC3        1.4        14.03.97    - A-B-Repeat-Bug entfernt
  261.                                 - Volumefenster im Menü geshadet
  262.                                 - ans Amiga-Magazin geschickt
  263.  
  264.             1.41    23.03.97    - UpdateGadgets() in viele Funktionen aufgeteilt
  265.                                 - einige Aktionen lösen jetzt direkt Aktualisierungen aus
  266.                                   (Trackslider, etc.)
  267.                                 - BF: HOTKEYCAUSES-Tooltype war immer auf HIDE
  268.  
  269.     mak        1.42    27.03.97    - BF: Konfig wird jetzt auch in ENV: gespeichert
  270.                     28.03.97    - Volumefenster funktioniert jetzt
  271.                                 - Konfigversion 3 (da Fenster dazu: sonst Absturz)
  272.  
  273.     MC3        1.43    28.03.97    - A-B-Repeat-Sicherheitsleck behoben
  274.                                 - neues Tooltype: SEARCHMODE
  275.                                   (Ergebnis steht in app->cdstr->searchmode)
  276.                                 - Beim Titeleditieren werden Standardtitel gelöscht
  277.                                 - Pfusch am Volume-Fenster :-)
  278.  
  279.     mak        1.44    29.03.97    - Slider im Volumefenster funktionieren jetzt unabhängig
  280.                                 - cdx_SimpleStatus in cdx_Active zurückumbenannt
  281.                     02.04.97    - verschiedene Searchmodi
  282.                     03.04.97    - das Indexgadget ist jetzt kein Fake mehr
  283.  
  284.             1.45    05.04.97    - Sony-Searchmode dazu
  285.                                 - globale Variablen CDROM_DEVICE und CDROM_UNIT werden benutzt,
  286.                                   falls kein ToolType oder Parameter vorhanden
  287.                                 - bei DOS-Fehlern werden nun Fehlermeldungen statt Codes ausgegeben
  288.                                 - UpdateUnitLUN() arbeitet jetzt vernünftig, glaube ich...
  289.  
  290. MC3    1.46        05.04.97    - Öfteres Aktualisieren beim Spulen
  291.                     - ein paar Verbesserungen
  292. mak            08.04.97    - TOC wird bei zu langer Updatezeit aktualisiert
  293.     1.47        20.04.97    - Volumerefreshing in MakeInterior() eingebaut
  294.                     - Tracktest in ProgramAppendElement() eingebaut (für ARexx)
  295.     1.48        27.04.97    - MainWindow wird in ProcessStruktur eingetragen (für Requester)
  296.                     - WindowTitel flackern jetzt nicht mehr bei Volume-Fade-Makros
  297.                     - viele neue ARexx-Cmds dazu
  298. mak    1.49        11.07.97    - 2 Enforcerhits entfernt
  299.                     - ListEmpty() durch IsListEmpty()/exec.library ersetzt
  300.             16.07.97    - MakeBusy() erstellt und in ARexxMenü eingebaut
  301.                     - kleine Verbesserungen
  302.             28.07.97    - Menü Laufwerk/Laufwerksperre wird jetzt abhängig von cdx_Flags & SPECIALF_LOCKED gesetzt
  303.             30.07.97    - cd.device-Laustärkeeinstellung (MONO) implementiert (was bei mir nicht funktioniert!)
  304.  
  305. MC3    1.5        18.10.97    - Über Shift und Alt jetzt auch die Tracks 11-30 direkt anwählbar
  306.                     - ACDP kommt jetzt mit unvollständigen Titeldateien zurecht
  307.  
  308.     1.51        13.11.97    - Die A-B-Range wird jetzt durch absolute Adressen angegeben
  309.                       -> Geschwindigkeitssteigerung bei TestABRepeat()
  310.                     - Fenster zur Audioabspeicherung programmiert
  311.             22.11.97    - neue Verwaltung für ASL-Requester (ähnlich AppWindows)
  312.                     - GetFileName() ist jetzt allgemein verwendbar
  313.             29.11.97    - ExamineDiskSpace() für Audiosaving entwickelt
  314.  
  315.     1.52        25.12.97    - "T"-Button im Hauptmenü öffnet jetzt das Titelauswahlfenster
  316.                     - Zeitanzeige jetzt nicht mehr ein ständig neugenerierter Button,
  317.                       sondern ein Button und ein darübergelegtes Textshow-Gadget.
  318.                       (sieht zwar blöder aus, ist aber schneller)
  319.             27.12.97    - Panelgadgets sind jetzt Vektorgadgets! Größe durch PANELWIDTH und PANELHEIGHT
  320.                       einstellbar
  321.  
  322.     1.53        28.12.97    - Vektorpanelgadgets für MagicWB-Modus funktioniert jetzt,
  323.                       wenn auch noch ohne MWB-Pattern
  324.  
  325.  
  326. **************************************************************************/
  327.  
  328.  
  329. /*    Erklärung der Statusflags:    < > keine Änderung
  330.                     <c> verändert
  331.                     <n> neu
  332.                     <x> entfernt */
  333.  
  334. /*----- Includes ---------------< >-*/
  335. #include "Constants.h"
  336.  
  337. #include <exec/types.h>
  338. #include <exec/memory.h>
  339. #include <exec/libraries.h>
  340. #include <intuition/intuition.h>
  341. #include <intuition/intuitionbase.h>
  342. #include <intuition/gadgetclass.h>
  343. #include <libraries/gadtools.h>
  344. #include <libraries/commodities.h>
  345. #include <libraries/asl.h>
  346. #include <graphics/rastport.h>
  347. #include <devices/scsidisk.h>
  348. #include <devices/cd.h>
  349. #include <libraries/screennotify.h>
  350. #include <pragma/screennotify_lib.h>
  351. #include "AsmLib/CD-ROM.h"
  352. #include "Locale.h"
  353. #include "Structures/Application.h"
  354. #include "Structures/DirNode.h"
  355. #include "Structures/MyPubScreenNode.h"
  356.  
  357. #include <clib/alib_protos.h>
  358. #include <clib/dos_protos.h>
  359. #include <clib/exec_protos.h>
  360. #include <clib/asl_protos.h>
  361. #include <clib/gadtools_protos.h>
  362. #include <clib/graphics_protos.h>
  363. #include <clib/intuition_protos.h>
  364. #include <clib/commodities_protos.h>
  365. #include <clib/icon_protos.h>
  366. #include <clib/locale_protos.h>
  367. #include <clib/wb_protos.h>
  368. #include <wbstartup.h>
  369. #include <string.h>
  370. #include <stdlib.h>
  371. #include <stdio.h>
  372. #include <math.h>
  373. #include "ACDPlay_protos.h"
  374.  
  375. /*----- globale Variablen ------< >-*/
  376. #define UNIT 0
  377.  
  378. char *ls[ANZ_MSG];
  379. struct LocaleInfo li = {NULL, NULL};
  380.  
  381. struct Library *IntuitionBase        = NULL;
  382. struct Library *CxBase            = NULL;
  383. struct Library *GadToolsBase        = NULL;
  384. struct Library *GfxBase            = NULL;
  385. struct Library *IconBase        = NULL;
  386. struct Library *LocaleBase        = NULL;
  387. struct Library *RexxSysBase        = NULL;
  388. struct Library *ScreenNotifyBase    = NULL;
  389. struct Library *WorkbenchBase        = NULL;
  390. struct Library *AslBase            = NULL;
  391.  
  392. static char    PROG_VERSION[]        = "\0$VER: ACDPlay 1.6 [000] ("__DATE2__")";
  393. char            *PROG_FULLNAME        = PROG_VERSION + 7;
  394. char         PROG_NAME[]        = "ACDPlay";
  395.  
  396.  
  397. /*------------------ main() -----------------------------------< >-*/
  398. int main(int argc, char *argv[])
  399. {
  400.     struct Application *app = NULL;
  401.     ULONG rc = RETURN_FAIL;                    /* Return-Wert auf 20 setzen */
  402.  
  403.     if (OpenLibsA())
  404.     {
  405.         if (app = CreateApplication(argv[0]))
  406.         {
  407.             ULONG        signals;
  408.             ULONG        waitbitmask;
  409.             BOOL        done = FALSE;
  410.  
  411.             if (app->cx_popup)
  412.                 OpenApplication(app, (app->flag_tool & FLAG_TOOL_AUTOACTIVE) ? TRUE : FALSE);    /* nur öffnen, wenn CX_POPUP */
  413.             else
  414.                 CreateAppItem(app);
  415.  
  416.             /***********************************
  417.             ** Hier beginnt die Event-Abfrage **
  418.             ***********************************/
  419.             while (!done)
  420.             {
  421.                 waitbitmask    = 0;
  422.  
  423.                 /* Control-C Signalbit dazu setzen */
  424.                 waitbitmask |= SIGBREAKF_CTRL_C;
  425.  
  426.                 /* Signalbits des IDCMP dazu setzen */
  427.                 if (app->idcmp)
  428.                     waitbitmask |= (1L << app->idcmp->mp_SigBit);
  429.  
  430.                 /* ARexxportsignalbit dazu odern :-) */
  431.                 waitbitmask |= (1L << app->arexx_mp->mp_SigBit);
  432.  
  433.                 /* Das AppItem-Bit auch noch */
  434.                 if (app->appitem_mp && app->hidemode != HIDEMODE_NONE)
  435.                     waitbitmask |= (1L << app->appitem_mp->mp_SigBit);
  436.  
  437.                 /* Signalbit des Broker-Messageports dazu setzen */
  438.                 waitbitmask |= (1L << app->broker_mp->mp_SigBit);
  439.  
  440.                 /* Signalbit des Screennotify-Ports dazu setzen */
  441.                 if (app->scrnotify_mp)
  442.                     waitbitmask |= (1L << app->scrnotify_mp->mp_SigBit);
  443.  
  444.                 signals = Wait(waitbitmask);
  445.  
  446.                 if (app->idcmp)
  447.                     if ((signals & (1L << app->idcmp->mp_SigBit)) && !done)
  448.                         done = HandleEvents(app);
  449.  
  450.                 if ((signals & (1L << app->arexx_mp->mp_SigBit)) && !done)
  451.                     done = HandleARexxMsgA(app->arexx_mp, app);
  452.  
  453.                 if (app->appitem_mp && app->hidemode != HIDEMODE_NONE)
  454.                     if ((signals & (1L << app->appitem_mp->mp_SigBit)) && !done)
  455.                         HandleAppItemEvents(app);
  456.  
  457.                 if ((signals & (1L << app->broker_mp->mp_SigBit)) && !done)
  458.                     done = HandleCommodityEvents(app);
  459.  
  460.                 if (app->scrnotify_mp)
  461.                     if (signals & (1L << app->scrnotify_mp->mp_SigBit))
  462.                         HandleScreenNotify(app);
  463.  
  464.                 if (signals & SIGBREAKF_CTRL_C)
  465.                     done = TRUE;
  466.             }
  467.             rc = RETURN_OK;
  468.             DeleteApplication(app);
  469.         }
  470.     }
  471.  
  472.     CloseLibsA();
  473.     return rc;
  474. }
  475.  
  476. void CopyRange(struct Application *app)
  477. {
  478.     char    *buf;
  479.     UBYTE    command[12];
  480.     int        i;
  481.  
  482.     struct SCSICmd *cmd;
  483.  
  484.     printf("Not yet implemented.  :-)");
  485.  
  486.     if (buf = (char *)GetVecA(100000, MEMF_PUBLIC | MEMF_CLEAR))
  487.     {
  488.         printf("1");
  489.  
  490.         command[0] = 0x28;    /* Command Description Block ausfüllen */
  491.         command[1] = 0x00;
  492.         command[2] = (app->cdstr->a_adr >> 24);
  493.         command[3] = ((app->cdstr->a_adr >> 16) & 0xFF);
  494.         command[4] = ((app->cdstr->a_adr >> 8) & 0xFF);
  495.         command[5] = (app->cdstr->a_adr & 0xFF);
  496.         command[6] = 0x0;
  497.         command[7] = 0x0;
  498.         command[8] = 0x0;
  499.         command[9] = 0x01;
  500.         command[10] = 0x0;
  501.         command[11] = 0x0;
  502.  
  503.         cmd = app->cdstr->cdx->cdx_Cmd;
  504.  
  505.         printf("2");
  506.  
  507.         if (cmd)
  508.         {
  509.             cmd->scsi_Data            = (UWORD *)buf;
  510.             cmd->scsi_Length        = 100000;
  511.             cmd->scsi_Actual        = 0;
  512.             cmd->scsi_Command          = command;
  513.             cmd->scsi_CmdLength        = 12;
  514.             cmd->scsi_CmdActual        = 0;
  515.             cmd->scsi_Flags            = SCSIF_READ | SCSIF_AUTOSENSE;
  516.             cmd->scsi_Status        = 0;
  517.             cmd->scsi_SenseData        = app->cdstr->cdx->cdx_SCSISense;
  518.             cmd->scsi_SenseLength    = 252;
  519.             cmd->scsi_SenseActual    = 0;
  520.  
  521.             printf("3");
  522.  
  523.             if (app->cdstr->cdx->cdx_IORequest)
  524.             {
  525.                 app->cdstr->cdx->cdx_IORequest->io_Command = HD_SCSICMD;
  526.                 app->cdstr->cdx->cdx_IORequest->io_Length = sizeof(struct SCSICmd);
  527.                 app->cdstr->cdx->cdx_IORequest->io_Data = (APTR)app->cdstr->cdx->cdx_Cmd;
  528.                 printf("4");
  529.                 printf("  %d  ", DoIO((struct IORequest *)app->cdstr->cdx->cdx_IORequest));
  530.                 printf("5");
  531.  
  532.                 /* Ausgabe */
  533.                 printf("\nSCSI-Command:");
  534.                 for (i = 0; i < 10; i++)
  535.                     printf(" %02x", (int)command[i]);
  536.  
  537.                 printf("\nSense Key:");
  538.                 for (i = 2; i < 4; i++)
  539.                     printf(" %02x", (int)*(((char *)cmd->scsi_SenseData) + i));
  540.  
  541.                 printf("\nAdditional Sense Code & Qualifier:");
  542.                 for (i = 12; i < 14; i++)
  543.                     printf(" %02x", (int)*(((char *)cmd->scsi_SenseData) + i));
  544.  
  545.                 SaveFile("ram:test", buf, 100000);
  546.             }
  547.         }
  548.         FreeVec(buf);
  549.     }
  550.  
  551.  
  552.     DoCDDBID(app->cdstr);
  553.     printf("ID:");
  554.     printf(app->cdstr->buf_cddb_id);
  555.  
  556.  
  557. }
  558.  
  559. /*------------------ ReadConfig() -----------------------------< >-*/
  560. void ReadConfig(struct Application *app, char *filename)
  561. {
  562.     WORD *buffer = NULL;
  563.     WORD i;
  564.     LONG err;
  565.  
  566.     /* Voreinstellungen */
  567.     for (i = 0; i < ANZ_WINDOWS; i++)
  568.     {
  569.         app->appwin[i].minsize[LEFT]    = 0;
  570.         app->appwin[i].minsize[TOP]        = 0;
  571.         app->appwin[i].minsize[WIDTH]    = MINWIDTH_LISTVIEWWIN;
  572.         /* Sonst wird aus nichtinitialisierten Feldern gelesen */
  573.         if (app->screen)
  574.             app->appwin[i].minsize[HEIGHT]    = MINHEIGHT_LISTVIEWWIN;
  575.         else
  576.             app->appwin[i].minsize[HEIGHT]    = 100;
  577.  
  578.         app->appwin[i].maxsize[LEFT]    = 200;
  579.         app->appwin[i].maxsize[TOP]        = 100;
  580.         app->appwin[i].maxsize[WIDTH]    = 150;
  581.         app->appwin[i].maxsize[HEIGHT]    = 150;
  582.  
  583.         app->appwin[i].maxwidth            = ~0;
  584.         app->appwin[i].maxheight        = ~0;
  585.     }
  586.     app->flag_main = FLAG_MAIN_DIRECTCHOICE0 | FLAG_MAIN_DIRECTCHOICE1 | FLAG_MAIN_TITLE | FLAG_MAIN_TIME | FLAG_MAIN_MODE | FLAG_MAIN_PANEL | FLAG_MAIN_TRACKSLIDER;
  587.  
  588.     if (buffer = (WORD *)OpenFile(filename))
  589.     {
  590.         WORD *offset = buffer;
  591.  
  592.         if ((*(LONG *)offset) == MAGIC)
  593.         {
  594.             UWORD win_anz, win_size, j;
  595.  
  596.             offset       += 2;
  597.             win_anz        = *(offset++);
  598.             win_size    = *(offset++);
  599.  
  600.             for (i = 0; i < (ANZ_WINDOWS > win_anz ? ANZ_WINDOWS : win_anz); i++)
  601.             {
  602.                 for (j = 0; j < 4; j++)
  603.                     app->appwin[i].minsize[j] = *(offset++);
  604.                 for (j = 0; j < 4; j++)
  605.                     app->appwin[i].maxsize[j] = *(offset++);
  606.  
  607.                 app->appwin[i].winopen = *(offset++);
  608.  
  609.                 ((char *)offset) += win_size - SIZE_WINDOW;
  610.             }
  611.  
  612.             ((char *)offset) += (win_anz - ANZ_WINDOWS) * win_size;
  613.             app->flag_main = *(LONG *)offset;
  614.         }
  615.         else ShowMsgA(ls[MSG_ERROR_TITLE], ls[MSG_NO_CFGFILE], filename);
  616.  
  617.         FreeVec(buffer);
  618.     }
  619.     else if ((err=IoErr()) != ERROR_OBJECT_NOT_FOUND)    /* nervt sonst... */
  620.     {
  621.         char errmsg[FAULT_MAX];
  622.         Fault(err, NULL, errmsg, FAULT_MAX);
  623.         ShowMsgA(ls[MSG_ERROR_TITLE], ls[MSG_BAD_FILE], filename, errmsg);
  624.     }
  625.  
  626.     /* Das auf jeden Fall */
  627.     app->appwin[WINDOW_MAIN].winopen = TRUE;
  628.     app->appwin[WINDOW_SAVING].winopen = FALSE;
  629.     app->appwin[WINDOW_SAVEAUDIO].winopen = FALSE;
  630. }
  631. /*------------------ SaveConfig() -----------------------------< >-*/
  632. BOOL SaveConfig(Application *app, char *filename)
  633. {
  634.     BOOL success = FALSE;
  635.     WORD i, j;
  636.     WORD *buffer = NULL;
  637.  
  638.     /* Wenn die Application noch offen ist, werden die Windowkoordinaten */
  639.     /* ausgelesen. Sonst hat CloseApplication() das schon erledigt. */
  640.     if (app->screen)
  641.     {
  642.         for (i = ANZ_WINDOWS-1; i >= 0; i--)
  643.         {
  644.             if (app->appwin[i].winopen && app->appwin[i].window)
  645.             {
  646.                 app->appwin[i].maxsize[LEFT]    = app->appwin[i].window->LeftEdge;
  647.                 app->appwin[i].maxsize[TOP]        = app->appwin[i].window->TopEdge;
  648.             }
  649.         }
  650.     }
  651.  
  652.     /* Ein wenig Speicher allozieren und dort alles hineinschreiben */
  653.     if (buffer = GetVecA(SIZE_CONFIG, MEMF_PUBLIC | MEMF_CLEAR))
  654.     {
  655.         WORD *offset = buffer;
  656.  
  657.         *(LONG *)offset = MAGIC;
  658.         offset += 2;
  659.  
  660.         *(offset++) = ANZ_WINDOWS;
  661.         *(offset++) = SIZE_WINDOW;
  662.  
  663.         for (i = 0; i < ANZ_WINDOWS; i++)
  664.         {
  665.             for (j = 0; j < 4; j++)
  666.                 *(offset++) = app->appwin[i].minsize[j];
  667.             for (j = 0; j < 4; j++)
  668.                 *(offset++) = app->appwin[i].maxsize[j];
  669.  
  670.             *(offset++) = app->appwin[i].winopen;
  671.         }
  672.  
  673.         *(LONG *)offset = app->flag_main;
  674.  
  675.         if (SaveFile(filename, (char *)buffer, SIZE_CONFIG))
  676.             success = TRUE;
  677.  
  678.         /* Execute-Flag löschen */
  679.         SetProtection(filename, FIBF_EXECUTE);
  680.  
  681.         FreeVec(buffer);
  682.     }
  683.  
  684.     return (success);
  685. }
  686. /*------------------ ReadArguments() --------------------------< >-*/
  687. void ReadArguments(struct Application *app)
  688. {
  689.     struct RDArgs *rda;
  690.     struct DiskObject *dobj;
  691.     char **toolarray, *s;
  692.     char var[30];
  693.  
  694.     /* Erst werden die Voreinstellungen gesetzt */
  695.     LONG    unit        = 0,
  696.         lun        = 0,
  697.         panelwidth    = 28,
  698.         panelheight    = 23,
  699.         updatedelay    = 5,
  700.         priority    = 0;
  701.  
  702.     LONG vec[] = {
  703.         (LONG)    "1230scsi.device",
  704.         (LONG)    &unit,
  705.         (LONG)    &lun,
  706.         (LONG)    "Workbench",
  707.             TRUE,
  708.             FALSE,
  709.         (LONG)    &panelwidth,
  710.         (LONG)    &panelheight,
  711.             TRUE,
  712.             FALSE,
  713.             TRUE,
  714.         (LONG)    NULL,
  715.         (LONG)    NULL,
  716.         (LONG)    &updatedelay,
  717.         (LONG)    NULL,
  718.         (LONG)    NULL,
  719.             TRUE,
  720.         (LONG)    "PROGDIR:Disks/",
  721.             TRUE,
  722.         (LONG)    "alt shift F1",
  723.         (LONG)    &priority };
  724.  
  725.     if (GetVar("CDROM_UNIT", var, 2, 0) != -1)
  726.         unit = atoi(var);
  727.  
  728.     if (GetVar("CDROM_DEVICE", var, 30, 0) != -1)
  729.         vec[0] = (LONG)var;
  730.  
  731.     /* Dann werden diese durch eventuelle Tooltypes überschrieben */
  732.     if (dobj = GetDiskObject(app->progname))
  733.     {
  734.         toolarray = dobj->do_ToolTypes;
  735.  
  736.         if (s = (char *)FindToolType((UBYTE **)toolarray, "DEVICE"))
  737.             vec[0] = (LONG)s;
  738.         if (s = (char *)FindToolType((UBYTE **)toolarray, "UNIT"))
  739.             unit = atoi(s);
  740.         if (s = (char *)FindToolType((UBYTE **)toolarray, "LUN"))
  741.             lun = atoi(s);
  742.         if (s = (char *)FindToolType((UBYTE **)toolarray, "PUBSCREEN"))
  743.             vec[3] = (LONG)s;
  744.         if (s = (char *)FindToolType((UBYTE **)toolarray, "AUTOACTIVE"))
  745.             vec[4] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  746.         if (s = (char *)FindToolType((UBYTE **)toolarray, "MAGICWB"))
  747.             vec[5] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  748.         if (s = (char *)FindToolType((UBYTE **)toolarray, "PANELWIDTH"))
  749.             panelwidth = atoi(s);
  750.         if (s = (char *)FindToolType((UBYTE **)toolarray, "PANELHEIGHT"))
  751.             panelheight = atoi(s);
  752.         if (s = (char *)FindToolType((UBYTE **)toolarray, "USEWINDOWBAR"))
  753.             vec[8] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  754.         if (s = (char *)FindToolType((UBYTE **)toolarray, "USESCREENBAR"))
  755.             vec[9] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  756.         if (s = (char *)FindToolType((UBYTE **)toolarray, "QUITONCLOSE"))
  757.             vec[10] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  758.         if (s = (char *)FindToolType((UBYTE **)toolarray, "HOTKEYCAUSES"))
  759.             vec[11] = (LONG)s;
  760.         if (s = (char *)FindToolType((UBYTE **)toolarray, "HOTKEYMODE"))
  761.             /* das gleiche wie HOTKEYCAUSES */
  762.             vec[11] = (LONG)s;
  763.         if (s = (char *)FindToolType((UBYTE **)toolarray, "HIDEMODE"))
  764.             vec[12] = (LONG)s;
  765.         if (s = (char *)FindToolType((UBYTE **)toolarray, "UPDATEDELAY"))
  766.             updatedelay = atoi(s);
  767.         if (s = (char *)FindToolType((UBYTE **)toolarray, "PLAYMODE"))
  768.             vec[14] = (LONG)s;
  769.         if (s = (char *)FindToolType((UBYTE **)toolarray, "SEARCHMODE"))
  770.             vec[15] = (LONG)s;
  771.         if (s = (char *)FindToolType((UBYTE **)toolarray, "AUTOSTART"))
  772.             vec[16] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  773.         if (s = (char *)FindToolType((UBYTE **)toolarray, "DISKPATH"))
  774.             vec[17] = (LONG)s;
  775.         if (s = (char *)FindToolType((UBYTE **)toolarray, "CX_POPUP"))
  776.             vec[18] = (MatchToolValue(s, "NO") || MatchToolValue(s, "no")) ? FALSE : TRUE;
  777.         if (s = (char *)FindToolType((UBYTE **)toolarray, "CX_POPKEY"))
  778.             vec[19] = (LONG)s;
  779.         if (s = (char *)FindToolType((UBYTE **)toolarray, "CX_PRIORITY"))
  780.             priority = atoi(s);
  781.     }
  782.  
  783.     /* Shell-Argumente können jedoch auch diese überschreiben */
  784.     if (rda = AllocDosObject(DOS_RDARGS, NULL))
  785.     {
  786.         rda->RDA_ExtHelp =    "ACDPlay CLI parameters:\n"
  787.                             "DEVICE:        device driver where the cd drive is connected, default: 1230scsi.device\n"
  788.                             "UNIT:          unit that belongs to the drive, default: 0\n"
  789.                             "LUN:           start logical unit number, default: 0\n"
  790.                             "PUBSCREEN:     where to start ACDPlay, default: Workbench\n"
  791.                             "AUTOACTIVE:    whether ACDPlay's windows should be activated on start, default: yes\n"
  792.                             "MAGICWB:       whether ACDPlay should use MagicWB graphics, default: no\n"
  793.                             "PANELWIDTH:    width of the panel buttons in pixels, default: 28\n"
  794.                             "PANELHEIGHT:   height of the panel buttons in pixels, default: 23\n"
  795.                             "USEWINDOWBAR:  enables window bar as information display, default: yes\n"
  796.                             "USESCREENBAR:  enables screen bar as information display, default: no\n"
  797.                             "QUITONCLOSE:   whether ACDPlay should quit when main window was closed, default: yes\n"
  798.                             "HOTKEYMODE:    SCREENTOFRONT, HIDE or FRONTMOST, default: SCREENTOFRONT\n"
  799.                             "HIDEMODE:      APPICON, APPMENUITEM or NONE, default: APPICON\n"
  800.                             "UPDATEDELAY:   delay between SCSI updates in 1/10 secs, default: 5\n"
  801.                             "PLAYMODE:      CD or PROGRAM, sets initial playmode, default: CD\n"
  802.                             "SEARCHMODE:    STANDARD, TOSHIBA or SONY (advanced search modes), default: STANDARD\n"
  803.                             "AUTOSTART:     whether ACDPlay should play inserted CDs immediately, default: yes\n"
  804.                             "DISKPATH:      path where ID and program files are stored, default: PROGDIR:Disks/\n"
  805.                             "CX_POPUP:      whether the GUI is displayed when started, default: yes\n"
  806.                             "CX_POPKEY:     key combination to popup GUI, default: lshift alt F1\n"
  807.                             "CX_PRIORITY:   priority as a commodity, default: 0\n\n"
  808.                             "Enter parameters";
  809.  
  810.         if (ReadArgs("DEV=DEVICE/K,UNIT/N,LUN/N,PUBSCREEN/K,AUTOACTIVE/T,MWB=MAGICWB/T,PANELWIDTH/N,PANELHEIGHT/N,USEWINDOWBAR/T,USESCREENBAR/T,QUITONCLOSE/T,HOTKEYMODE=HOTKEYCAUSES/K,HIDEMODE/K,UPDATEDELAY/N,PLAYMODE/K,SEARCHMODE/K,AUTOSTART/T,DISKPATH/K,CX_POPUP/T,CX_POPKEY/K,CX_PRIORITY/N", vec, rda))
  811.         {
  812.             FreeArgs(rda);
  813.         }
  814.  
  815.         FreeDosObject(DOS_RDARGS, rda);
  816.     }
  817.  
  818.     /* Werte verbindlich eintragen */
  819.     strncpy(app->cdstr->device,        (char *)vec[0], 30);
  820.     app->cdstr->unit            = FitInteger(*(LONG *)vec[1], 0, 7);
  821.     app->cdstr->lun                = FitInteger(*(LONG *)vec[2], 0, 7);
  822.     strncpy(app->pubscreenname,        (char *)vec[3], MAXPUBSCREENNAME);
  823.     app->flag_tool                = InsertBoolean(app->flag_tool, FLAG_TOOL_AUTOACTIVE, vec[4]);
  824.     app->flag_tool                = InsertBoolean(app->flag_tool, FLAG_TOOL_MWB, vec[5]);
  825.     app->panelwidth                = FitInteger(*(LONG *)vec[6], 13, 100);
  826.     app->panelheight            = FitInteger(*(LONG *)vec[7], 13, 100);
  827.     app->flag_tool                = InsertBoolean(app->flag_tool, FLAG_TOOL_USEWINDOWBAR, vec[8]);
  828.     app->flag_tool                = InsertBoolean(app->flag_tool, FLAG_TOOL_USESCREENBAR, vec[9]);
  829.     app->flag_tool                = InsertBoolean(app->flag_tool, FLAG_TOOL_QUITONCLOSE, vec[10]);
  830.  
  831.     if (vec[11])
  832.     {
  833.         if (strcmp((char *)vec[11], "HIDE") == 0)
  834.             app->hotkeymode   = HOTKEYMODE_HIDE;
  835.         else if (strcmp((char *)vec[11], "FRONTMOST") == 0)
  836.             app->hotkeymode   = HOTKEYMODE_FRONTMOST;
  837.         else
  838.             app->hotkeymode   = HOTKEYMODE_SCREENTOFRONT;
  839.      }
  840.  
  841.      if (vec[12])
  842.      {
  843.          if (strcmp((char *)vec[12], "APPMENUITEM") == 0)
  844.              app->hidemode    = HIDEMODE_APPMENUITEM;
  845.          else if (strcmp((char *)vec[12], "NONE") == 0)
  846.              app->hidemode    = HIDEMODE_NONE;
  847.          else
  848.              app->hidemode    = HIDEMODE_APPICON;
  849.      }
  850.  
  851.     printf("%n", app->hidemode);
  852.  
  853.     app->cdstr->updatedelay        =    FitInteger(*(LONG *)vec[13], 1, 50);
  854.  
  855.     if (vec[14])
  856.     {
  857.         if (strcmp((char *)vec[14], "PROGRAM") == 0)
  858.             app->cdstr->playmode    = PLAYMODE_PROGRAM;
  859.         else
  860.             app->cdstr->playmode    = PLAYMODE_CD;
  861.      }
  862.  
  863.     if (vec[15])
  864.     {
  865.         if (strcmp((char *)vec[15], "TOSHIBA") == 0)
  866.             app->cdstr->searchmode   = SEARCHMODE_TOSHIBA;
  867.         else if (strcmp((char *)vec[15], "SONY") == 0)
  868.             app->cdstr->searchmode   = SEARCHMODE_SONY;
  869.         else
  870.             app->cdstr->searchmode   = SEARCHMODE_STANDARD;
  871.      }
  872.  
  873.     app->flag_tool            = InsertBoolean(app->flag_tool, FLAG_TOOL_AUTOSTART, vec[16]);
  874.     app->cdstr->searchseconds    = 10;
  875.  
  876.     strncpy(app->cdstr->diskpath,    (char *)vec[17], DISKPATHLENGTH - 1);   /* evt. muß noch ein '/' ran */
  877.     if ((app->cdstr->diskpath[strlen(app->cdstr->diskpath) -1] != ':') && (app->cdstr->diskpath[strlen(app->cdstr->diskpath) - 1] != '/'))
  878.         strcat(app->cdstr->diskpath, "/");
  879.  
  880.     app->cx_popup                =    vec[18];
  881.     strncpy(app->cx_popkey,            (char *)vec[19], 40);
  882.     app->cx_priority            =    FitInteger(*(LONG *)vec[20], -128, 127);
  883.  
  884.     if (dobj) FreeDiskObject(dobj);    /* Damit die Strings erhalten bleiben */
  885. }
  886.  
  887. /*------------------ SaveTitles() -----------------------------< >-*/
  888. BOOL SaveTitles(Application *app)
  889. {
  890.     BOOL success     = FALSE;
  891.  
  892.     int i, bufferlen;
  893.     char *buffer;
  894.  
  895.     bufferlen = strlen(app->cdstr->artistname) + strlen(app->cdstr->cdname) + 2;
  896.     for (i = 0; i < app->cdstr->num_track; i++)
  897.         bufferlen += strlen(app->cdstr->tracknames[i]) + 1;
  898.  
  899.     if (buffer = GetVecA(bufferlen, MEMF_PUBLIC | MEMF_CLEAR))
  900.     {
  901.         char *actpos = buffer;
  902.         char *filename;
  903.  
  904.         /* Künstler speichern */
  905.         strcpy(actpos, app->cdstr->artistname);
  906.         actpos += strlen(app->cdstr->artistname);
  907.         *(actpos) = 0x0A;
  908.         actpos++;
  909.  
  910.         /* CD-Name speichern */
  911.         strcpy(actpos, app->cdstr->cdname);
  912.         actpos += strlen(app->cdstr->cdname);
  913.         *(actpos) = 0x0A;
  914.         actpos++;
  915.  
  916.         /* jeden Titel */
  917.         for (i = 0; i < app->cdstr->num_track; i++)
  918.         {
  919.             strcpy(actpos, app->cdstr->tracknames[i]);
  920.             actpos += strlen(app->cdstr->tracknames[i]);
  921.             *(actpos) = 0x0A;
  922.             actpos++;
  923.         }
  924.  
  925.         if (filename = GetVecA(strlen(app->cdstr->diskpath) + 22, MEMF_PUBLIC | MEMF_CLEAR))
  926.         {
  927.             strcpy(filename, app->cdstr->diskpath);
  928.             strcat(filename, "ID");
  929.             strcat(filename, app->cdstr->cdx->cdx_TOCData->CDID);
  930.  
  931.             if (SaveFile(filename, buffer, bufferlen))
  932.                 success = TRUE;
  933.  
  934.             FreeVec(filename);
  935.         }
  936.         FreeVec(buffer);
  937.     }
  938.  
  939.     return (success);
  940. }
  941.  
  942. /*------------------ PlayListStart() --------------------------< >-*/
  943. BOOL PlayListStart(struct CDStruct *cdstr, int starttrack)
  944. {
  945.     /* Ist starttrack != 0, wird ein Node gesucht, der dem
  946.     Track entspricht, ansonsten der erste genommen. */
  947.  
  948.     struct List *playlist = cdstr->playlist[cdstr->playmode];
  949.     BOOL success = FALSE;
  950.  
  951.     if (playlist)
  952.         if (!IsListEmpty(playlist))
  953.         {
  954.             if (cdstr->playrandom)
  955.             {
  956.                 InitRandomElements(playlist);
  957.  
  958.                 if (starttrack == 0)
  959.                     cdstr->currentlyplayed = GetRandomElement(playlist);
  960.                 else
  961.                 {
  962.                     cdstr->currentlyplayed = FindFirstMatchingElement(playlist, starttrack);
  963.                     cdstr->currentlyplayed->pln_randomplayed = TRUE;
  964.                 }
  965.             }
  966.             else
  967.             {
  968.                 if (starttrack == 0)
  969.                     cdstr->currentlyplayed = GetFirstAudioElement(cdstr->cdx->cdx_TOCData, playlist);
  970.                 else
  971.                     cdstr->currentlyplayed = FindFirstMatchingElement(playlist, starttrack);
  972.             }
  973.  
  974.             if (CDPlayA(cdstr->cdx, cdstr->currentlyplayed->pln_track, 1) == RETURN_OK)
  975.                 success = TRUE;
  976.         }
  977.  
  978.     return(success);
  979. }
  980. /*------------------ PlayListNext() ---------------------------< >-*/
  981. BOOL PlayListNext(struct CDStruct *cdstr)
  982. {
  983.     BOOL success = FALSE;
  984.  
  985.     if (cdstr->currentlyplayed)
  986.         if (cdstr->playrandom)
  987.         {
  988.             if (cdstr->currentlyplayed = GetRandomElement(cdstr->playlist[cdstr->playmode]))
  989.             {
  990.                 CDPlayA(cdstr->cdx, cdstr->currentlyplayed->pln_track, 1);
  991.                 success = TRUE;
  992.             }
  993.             else
  994.             {
  995.                 if (cdstr->repeatmode == REPEATMODE_REPALL)
  996.                 {
  997.                     PlayListStart(cdstr);
  998.                     success = TRUE;
  999.                 }
  1000.             }
  1001.         }
  1002.         else
  1003.         {
  1004.             if (cdstr->currentlyplayed == (struct PlayListNode *)cdstr->playlist[cdstr->playmode]->lh_TailPred)
  1005.             {
  1006.                 if (cdstr->repeatmode == REPEATMODE_REPALL)
  1007.                 {
  1008.                     PlayListStart(cdstr);
  1009.                     success = TRUE;
  1010.                 }
  1011.             }
  1012.             else
  1013.             {
  1014.                 cdstr->currentlyplayed = (struct PlayListNode *)cdstr->currentlyplayed->pln_Node.ln_Succ;
  1015.                 CDPlayA(cdstr->cdx, cdstr->currentlyplayed->pln_track, 1);
  1016.                 success = TRUE;
  1017.             }
  1018.         }
  1019.  
  1020.     return (success);
  1021. }
  1022. /*------------------ PlayListPrev() ---------------------------< >-*/
  1023. BOOL PlayListPrev(struct CDStruct *cdstr)
  1024. {
  1025.     BOOL success = FALSE;
  1026.  
  1027.     if (cdstr->currentlyplayed)
  1028.         if (cdstr->playrandom)
  1029.         {
  1030.             if (cdstr->currentlyplayed = GetRandomElement(cdstr->playlist[cdstr->playmode]))
  1031.             {
  1032.                 CDPlayA(cdstr->cdx, cdstr->currentlyplayed->pln_track, 1);
  1033.                 success = TRUE;
  1034.             }
  1035.             else
  1036.             {
  1037.                 if (cdstr->repeatmode == REPEATMODE_REPALL)
  1038.                 {
  1039.                     PlayListStart(cdstr);
  1040.                     success = TRUE;
  1041.                 }
  1042.             }
  1043.         }
  1044.         else
  1045.         {
  1046.             if (cdstr->currentlyplayed != (struct PlayListNode *)cdstr->playlist[cdstr->playmode]->lh_Head)
  1047.             {
  1048.                 cdstr->currentlyplayed = (struct PlayListNode *)cdstr->currentlyplayed->pln_Node.ln_Pred;
  1049.                 CDPlayA(cdstr->cdx, cdstr->currentlyplayed->pln_track, 1);
  1050.                 success = TRUE;
  1051.             }
  1052.         }
  1053.  
  1054.     return (success);
  1055. }
  1056. /*------------------ GetFirstAudioElement() -------------------< >-*/
  1057. struct PlayListNode *GetFirstAudioElement(struct CDxTOC *toc, struct List *playlist)
  1058. {
  1059.     struct PlayListNode *tempnode;
  1060.  
  1061.     for (tempnode = ((struct PlayListNode *)playlist->lh_Head); tempnode->pln_Node.ln_Succ; tempnode = (struct PlayListNode *)tempnode->pln_Node.ln_Succ)
  1062.     {
  1063.         if (!(toc->Entry[tempnode->pln_track].CtlAdr & QCONTROLF_DATA))    /* Datentrack? */
  1064.             break;
  1065.     }
  1066.  
  1067.     return (tempnode);
  1068. }
  1069. /*------------------ GetRandomElement() -----------------------< >-*/
  1070. struct PlayListNode *GetRandomElement(struct List *playlist)
  1071. {
  1072.     /* liefert ein zufälliges Element aus der Playlist und markiert es
  1073.     als "gespielt". Wird keins gefunden, was noch nicht gespielt wurde,
  1074.     so wird NULL zurückgegeben. */
  1075.  
  1076.     struct PlayListNode **buffer;
  1077.     struct PlayListNode *returnnode = NULL;
  1078.  
  1079.     if (buffer = GetVecA(ListLengthA(playlist) * sizeof(struct PlayListNode *), MEMF_PUBLIC | MEMF_CLEAR))
  1080.     {
  1081.         struct Node *tempnode;
  1082.         int j = 0;
  1083.  
  1084.         for (tempnode = playlist->lh_Head; tempnode->ln_Succ; tempnode = tempnode->ln_Succ)
  1085.             if (!(((struct PlayListNode *)tempnode)->pln_randomplayed))
  1086.             {
  1087.                 buffer[j] = (struct PlayListNode *)tempnode;
  1088.                 j++;
  1089.             }
  1090.  
  1091.         if (j > 0)
  1092.         {
  1093.             returnnode = buffer[RandomNum(0, j - 1)];
  1094.             /* Flag auf TRUE setzen */
  1095.             returnnode->pln_randomplayed = TRUE;
  1096.         }
  1097.  
  1098.         FreeVec(buffer);
  1099.     }
  1100.  
  1101.     return (returnnode);
  1102. }
  1103. /*------------------ InitRandomElements() ---------------------< >-*/
  1104. void InitRandomElements(struct List *playlist)
  1105. {
  1106.     /* Dies hier cleared die Random-Flags in jeder einzelnen Node-Struktur */
  1107.     struct Node *tempnode;
  1108.  
  1109.     for (tempnode = playlist->lh_Head; tempnode->ln_Succ; tempnode = tempnode->ln_Succ)
  1110.         ((struct PlayListNode *)tempnode)->pln_randomplayed = FALSE;
  1111. }
  1112. /*------------------ FindFirstMatchingElement() ---------------< >-*/
  1113. struct PlayListNode *FindFirstMatchingElement(struct List *playlist, int track)
  1114. {
  1115.     struct PlayListNode     *tempnode,
  1116.                 *returnnode = NULL;
  1117.  
  1118.     for (tempnode = (struct PlayListNode *)playlist->lh_Head; tempnode->pln_Node.ln_Succ; tempnode = (struct PlayListNode *)tempnode->pln_Node.ln_Succ)
  1119.     {
  1120.         if (tempnode->pln_track == track)
  1121.         {
  1122.             returnnode = tempnode;
  1123.             break;
  1124.         }
  1125.     }
  1126.  
  1127.     return (returnnode);
  1128. }
  1129. /*------------------ CDPlayVerify() ---------------------------< >-*/
  1130. LONG CDPlayVerify(struct CDStruct *cdstr, UBYTE track)
  1131. {
  1132.     LONG suc = RETURN_OK;
  1133.  
  1134.     if (track != cdstr->cur_track)
  1135.         suc = CDPlayA(cdstr->cdx, track, 1);
  1136.  
  1137.     return (suc);
  1138. }
  1139.  
  1140. /*------------------ ProgramDelete() --------------------------< >-*/
  1141. BOOL ProgramDelete(Application *app)
  1142. {
  1143.     BOOL success = FALSE;
  1144.  
  1145.     register struct CDStruct *cdstr = app->cdstr;
  1146.  
  1147.     /* Da diese Funktion auch von Arexx aus aufgerufen wird, muß sie alles mögliche */
  1148.     /* selber machen, z.B: */
  1149.     /* Laufwerk ggf. stoppen, Liste aus LV entfernen, Liste löschen, eine neue erstellen, */
  1150.     /* aus Prinzip Liste wieder ins LV bauen */
  1151.  
  1152.     if ((cdstr->playmode == PLAYMODE_PROGRAM) && ((cdstr->active == AUDIO_STAT_PLAYING) || (cdstr->active == AUDIO_STAT_PAUSED)))
  1153.     {
  1154.         CDStopA(cdstr->cdx);
  1155.         cdstr->useraction = TRUE;
  1156.     }
  1157.  
  1158.     if (app->appwin[WINDOW_PROGRAM].window)
  1159.         GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  1160.     if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1161.         GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, ~0, TAG_END);
  1162.  
  1163.     FreeList(cdstr->playlist[PLAYLIST_PROGRAM]);
  1164.  
  1165.     if (cdstr->playlist[PLAYLIST_PROGRAM] = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR))
  1166.     {
  1167.         NewList(cdstr->playlist[PLAYLIST_PROGRAM]);
  1168.  
  1169.         if (app->appwin[WINDOW_PROGRAM].window)
  1170.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1171.         if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1172.             GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1173.  
  1174.         success = TRUE;
  1175.     }
  1176.  
  1177.     return (success);
  1178. }
  1179. /*------------------ ProgramAppendElement() -------------------< >-*/
  1180. BOOL ProgramAppendElement(Application *app, UWORD track)
  1181. {
  1182.     BOOL success = FALSE;
  1183.     struct PlayListNode *newnode;
  1184.  
  1185.     register struct CDStruct *cdstr = app->cdstr;
  1186.  
  1187.     if ((track > cdstr->cdx->cdx_TOCData->LastTrack) || (track < cdstr->cdx->cdx_TOCData->FirstAudioTrack))
  1188.         return (success);
  1189.  
  1190.     if (newnode = GetVecA(sizeof(struct PlayListNode), MEMF_PUBLIC | MEMF_CLEAR))
  1191.     {
  1192.         if (app->appwin[WINDOW_PROGRAM].window)
  1193.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  1194.         if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1195.             GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, ~0, TAG_END);
  1196.  
  1197.         newnode->pln_track = track;
  1198.         newnode->pln_Node.ln_Name = cdstr->tracknames[track - 1];
  1199.         AddTail(cdstr->playlist[PLAYLIST_PROGRAM], (Node *) newnode);
  1200.  
  1201.         if (app->appwin[WINDOW_PROGRAM].window)
  1202.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1203.         if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1204.             GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1205.  
  1206.         success = TRUE;
  1207.     }
  1208.  
  1209.     return (success);
  1210. }
  1211. /*------------------ ProgramDeleteElement() -------------------< >-*/
  1212. BOOL ProgramDeleteElement(Application *app, ULONG pos)
  1213. {
  1214.     BOOL success = FALSE;
  1215.     struct PlayListNode *oldnode;
  1216.  
  1217.     register struct CDStruct *cdstr = app->cdstr;
  1218.  
  1219.     if (pos < ListLengthA(cdstr->playlist[PLAYLIST_PROGRAM]))
  1220.     {
  1221.         oldnode = (struct PlayListNode *)FindNode(cdstr->playlist[PLAYLIST_PROGRAM], pos);
  1222.  
  1223.         if (app->appwin[WINDOW_PROGRAM].window)
  1224.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  1225.         if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1226.             GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, ~0, TAG_END);
  1227.  
  1228.         /* evt. Spielvorgang abbrechen */
  1229.         if ((cdstr->playmode == PLAYMODE_PROGRAM) && ((cdstr->active == AUDIO_STAT_PLAYING) || (cdstr->active == AUDIO_STAT_PAUSED)) && (app->cdstr->currentlyplayed == oldnode))
  1230.         {
  1231.             CDStopA(cdstr->cdx);
  1232.             cdstr->useraction = TRUE;
  1233.         }
  1234.  
  1235.         Remove((struct Node *)oldnode);
  1236.         FreeVec(oldnode);
  1237.  
  1238.         if (app->appwin[WINDOW_PROGRAM].window)
  1239.             GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1240.         if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1241.             GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1242.  
  1243.         success = TRUE;
  1244.     }
  1245.  
  1246.     return (success);
  1247. }
  1248. /*------------------ ProgramCopyAll() -------------------------< >-*/
  1249. BOOL ProgramCopyAll(Application *app)
  1250. {
  1251.     BOOL success = FALSE;
  1252.  
  1253.     register struct CDStruct *cdstr = app->cdstr;
  1254.  
  1255.     if (app->appwin[WINDOW_PROGRAM].window)
  1256.         GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  1257.     if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1258.         GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, ~0, TAG_END);
  1259.  
  1260.     FreeList(cdstr->playlist[PLAYLIST_PROGRAM]);
  1261.  
  1262.     if (cdstr->playlist[PLAYLIST_PROGRAM] = CopyList(cdstr->playlist[PLAYLIST_CD], sizeof(struct PlayListNode)))
  1263.         if (cdstr->playmode == PLAYMODE_PROGRAM)
  1264.         {
  1265.             switch (cdstr->active)
  1266.             {
  1267.                 case AUDIO_STAT_PLAYING:
  1268.                 case AUDIO_STAT_PAUSED:
  1269.                     PlayListStart(cdstr);
  1270.                     cdstr->useraction = TRUE;
  1271.                     break;
  1272.             }
  1273.             if (cdstr->active == AUDIO_STAT_PAUSED)
  1274.                 CDPauseA(cdstr->cdx, TRUE);
  1275.         }
  1276.  
  1277.     if (app->appwin[WINDOW_PROGRAM].window)
  1278.         GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1279.     if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1280.         GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1281.  
  1282.     return (success);
  1283. }
  1284. /*------------------ ProgramSave() ----------------------------< >-*/
  1285. BOOL ProgramSave(Application *app)
  1286. {
  1287.     BOOL success = FALSE;
  1288.     char *filename;
  1289.  
  1290.     register struct CDStruct *cdstr = app->cdstr;
  1291.  
  1292.     if (filename = GetVecA(strlen(cdstr->diskpath) + 22, MEMF_PUBLIC | MEMF_CLEAR))
  1293.     {
  1294.         /* Dateinamen generieren */
  1295.         strcpy(filename, cdstr->diskpath);
  1296.         strcat(filename, "PR");
  1297.         strcat(filename, cdstr->cdx->cdx_TOCData->CDID);
  1298.  
  1299.         if (IsListEmpty(cdstr->playlist[PLAYLIST_PROGRAM]))
  1300.         {
  1301.             DeleteFile(filename);
  1302.             success = TRUE;
  1303.         }
  1304.         else
  1305.         {
  1306.             int bufferlen;
  1307.             char *buffer;
  1308.  
  1309.             bufferlen = ListLengthA(cdstr->playlist[PLAYLIST_PROGRAM]);
  1310.  
  1311.             if (buffer = GetVecA(bufferlen, MEMF_PUBLIC | MEMF_CLEAR))
  1312.             {
  1313.                 char *actpos = buffer;
  1314.                 struct PlayListNode *tempnode;
  1315.  
  1316.                 for (tempnode = ((struct PlayListNode *)cdstr->playlist[PLAYLIST_PROGRAM]->lh_Head); tempnode->pln_Node.ln_Succ; tempnode = (struct PlayListNode *)tempnode->pln_Node.ln_Succ)
  1317.                 {
  1318.                     *(actpos) = tempnode->pln_track;
  1319.                     actpos++;
  1320.                 }
  1321.  
  1322.                 if (SaveFile(filename, buffer, bufferlen))
  1323.                     success = TRUE;
  1324.  
  1325.                 FreeVec(buffer);
  1326.             }
  1327.         }
  1328.         FreeVec(filename);
  1329.     }
  1330.  
  1331.     return (success);
  1332. }
  1333. /*------------------ ProgramLoad() ----------------------------< >-*/
  1334. BOOL ProgramLoad(Application *app)
  1335. {
  1336.     BOOL success = FALSE;
  1337.     char *wantedname;
  1338.  
  1339.     register struct CDStruct *cdstr = app->cdstr;
  1340.  
  1341.     if (!cdstr->playlist[PLAYLIST_PROGRAM])
  1342.     {
  1343.         cdstr->playlist[PLAYLIST_PROGRAM] = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR);
  1344.         NewList(cdstr->playlist[PLAYLIST_PROGRAM]);
  1345.     }
  1346.  
  1347.     if (wantedname = GetVecA(strlen(cdstr->diskpath) + 22, MEMF_PUBLIC | MEMF_CLEAR))
  1348.     {
  1349.         int filelength;
  1350.         char *filebuffer;
  1351.  
  1352.         strcpy(wantedname, cdstr->diskpath);
  1353.         strcat(wantedname, "PR");
  1354.         strcat(wantedname, cdstr->cdx->cdx_TOCData->CDID);
  1355.  
  1356.         if ((filelength = ExamineFileLength(wantedname)) && (filebuffer = OpenFile(wantedname)))
  1357.         {
  1358.             struct PlayListNode *tempnode;
  1359.  
  1360.             if (app->appwin[WINDOW_PROGRAM].window)
  1361.                 GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, ~0, TAG_END);
  1362.             if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1363.                 GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, ~0, TAG_END);
  1364.  
  1365.             FreeList(cdstr->playlist[PLAYLIST_PROGRAM]);
  1366.             cdstr->playlist[PLAYLIST_PROGRAM] = NULL;
  1367.  
  1368.             if (cdstr->playlist[PLAYLIST_PROGRAM] = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR))
  1369.             {
  1370.                 register int i;
  1371.                 NewList(cdstr->playlist[PLAYLIST_PROGRAM]);
  1372.  
  1373.                 success = TRUE;
  1374.  
  1375.                 /* Für jedes Byte eine Node erstellen und ausfüllen */
  1376.                 for (i = 0; i < filelength; i++)
  1377.                 {
  1378.                     if (tempnode = GetVecA(sizeof(struct PlayListNode), MEMF_PUBLIC | MEMF_CLEAR))
  1379.                     {
  1380.                         tempnode->pln_track = (UBYTE)filebuffer[i];
  1381.                         tempnode->pln_Node.ln_Name = cdstr->tracknames[tempnode->pln_track - 1];
  1382.                         AddTail(cdstr->playlist[PLAYLIST_PROGRAM], (Node *) tempnode);
  1383.                     }
  1384.                     else
  1385.                         success = FALSE;
  1386.                 }
  1387.             }
  1388.  
  1389.             if (app->appwin[WINDOW_PROGRAM].window)
  1390.                 GT_SetGadgetAttrs(app->appwin[WINDOW_PROGRAM].gadget[GADGET_PROGRAM_LVPRG], app->appwin[WINDOW_PROGRAM].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1391.             if (app->appwin[WINDOW_TITLES].window && cdstr->playmode == PLAYMODE_PROGRAM)
  1392.                 GT_SetGadgetAttrs(app->appwin[WINDOW_TITLES].gadget[GADGET_TITLES_LISTVIEW], app->appwin[WINDOW_TITLES].window, NULL, GTLV_Labels, cdstr->playlist[PLAYLIST_PROGRAM], TAG_END);
  1393.  
  1394.             if (cdstr->playmode == PLAYMODE_PROGRAM)
  1395.             {
  1396.                 switch (cdstr->active)
  1397.                 {
  1398.                     case AUDIO_STAT_PLAYING:
  1399.                     case AUDIO_STAT_PAUSED:
  1400.                         PlayListStart(cdstr);
  1401.                         cdstr->useraction = TRUE;
  1402.                         break;
  1403.                 }
  1404.                 if (cdstr->active == AUDIO_STAT_PAUSED)
  1405.                     CDPauseA(cdstr->cdx, TRUE);
  1406.             }
  1407.  
  1408.             FreeVec(filebuffer);
  1409.         }
  1410.         FreeVec(wantedname);
  1411.     }
  1412.  
  1413.     return (success);
  1414. }
  1415.  
  1416. /*------------------ OpenAppWin() -----------------------------< >-*/
  1417. BOOL OpenAppWin(Application *app, WORD win, BOOL activate)
  1418. {
  1419.     BOOL success = FALSE;
  1420.  
  1421.     /* PopUp falls Window schon offen ist */
  1422.     if (app->appwin[win].window != NULL)
  1423.     {
  1424.         WindowToFront(app->appwin[win].window);
  1425.         if (activate)
  1426.             ActivateWindow(app->appwin[win].window);
  1427.         return (TRUE);
  1428.     }
  1429.  
  1430.     if (MakeVisuals(app, win))
  1431.     {
  1432.         ULONG idcmpflags = IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK;
  1433.         struct TagItem wintags[] = {    WA_Left,    app->appwin[win].maxsize[LEFT],
  1434.                         WA_Top,        app->appwin[win].maxsize[TOP],
  1435.                          WA_Width,    app->appwin[win].maxsize[WIDTH],
  1436.                         WA_Height,    app->appwin[win].maxsize[HEIGHT],
  1437.                         WA_Flags,    WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | (activate ? WFLG_ACTIVATE : 0) | WFLG_NEWLOOKMENUS | WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM,
  1438.                         WA_Gadgets,    (ULONG)app->appwin[win].gadgetlist,
  1439.                         WA_PubScreen,    (ULONG)app->screen,
  1440.                         WA_Title,    NULL,
  1441.                         TAG_IGNORE,    (ULONG)&app->appwin[win].minsize,
  1442.                         WA_MinWidth,    app->appwin[win].minwidth,
  1443.                         WA_MinHeight,    app->appwin[win].minheight,
  1444.                         WA_MaxWidth,    app->appwin[win].maxwidth,
  1445.                         WA_MaxHeight,    app->appwin[win].maxheight,
  1446.                         (IntuitionBase->lib_Version >= 39)?WA_BusyPointer:TAG_IGNORE,    (app->Flags & APPF_BUSY)?TRUE:FALSE,
  1447.                         TAG_END        };
  1448.  
  1449.         switch(win)
  1450.         {
  1451.             case WINDOW_MAIN:
  1452.                 idcmpflags |= BUTTONIDCMP | SLIDERIDCMP | IDCMP_VANILLAKEY | IDCMP_RAWKEY | IDCMP_CHANGEWINDOW | IDCMP_INTUITICKS | IDCMP_MOUSEBUTTONS;
  1453.                 wintags[4].ti_Data &= ~(WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM);
  1454.                 /* gegebenenfalls ohne Zoomgadget öffnen */
  1455.                 wintags[8].ti_Tag = app->flag_main ? WA_Zoom : TAG_IGNORE;
  1456.                 break;
  1457.  
  1458.             case WINDOW_ABOUT:
  1459.                 idcmpflags |= BUTTONIDCMP | IDCMP_INTUITICKS;
  1460.                 wintags[4].ti_Data &= ~(WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM);
  1461.                 wintags[7].ti_Data = (ULONG)ls[MSG_ABOUT_TITLE];
  1462.                 break;
  1463.  
  1464.             case WINDOW_CDINFO:
  1465.                 idcmpflags |= BUTTONIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1466.                 wintags[7].ti_Data    = (ULONG)ls[MSG_CDINFO_TITLE];
  1467.                 wintags[8].ti_Tag    = WA_Zoom;
  1468.                 break;
  1469.  
  1470.             case WINDOW_DRIVEINFO:
  1471.                 idcmpflags |= BUTTONIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1472.                 wintags[7].ti_Data    = (ULONG)ls[MSG_DRIVEINFO_TITLE];
  1473.                 wintags[8].ti_Tag    = WA_Zoom;
  1474.                 break;
  1475.  
  1476.             case WINDOW_PUBSCREEN:
  1477.                 idcmpflags |= LISTVIEWIDCMP | BUTTONIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1478.                 wintags[7].ti_Data    = (ULONG)ls[MSG_PUBSCREEN_TITLE];
  1479.                 wintags[8].ti_Tag    = WA_Zoom;
  1480.                 break;
  1481.  
  1482.             case WINDOW_TITLES:
  1483.                 idcmpflags |= LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_RAWKEY | IDCMP_CHANGEWINDOW;
  1484.                 wintags[8].ti_Tag    = WA_Zoom;
  1485.                 break;
  1486.  
  1487.             case WINDOW_EDIT:
  1488.                 idcmpflags |= BUTTONIDCMP | LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1489.                 wintags[7].ti_Data    = (ULONG)ls[MSG_EDIT_TITLE];
  1490.                 wintags[8].ti_Data    = WA_Zoom;
  1491.                 break;
  1492.  
  1493.             case WINDOW_PROGRAM:
  1494.                 idcmpflags |= BUTTONIDCMP | LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1495.                 wintags[7].ti_Data    = (ULONG)ls[MSG_PROGRAM_TITLE];
  1496.                 wintags[8].ti_Tag    = WA_Zoom;
  1497.                 break;
  1498.  
  1499.             case WINDOW_VOLUME:
  1500.                 idcmpflags |= SLIDERIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1501.                 wintags[7].ti_Data = (ULONG)ls[MSG_VOLUME_TITLE];
  1502.                 wintags[8].ti_Tag    = WA_Zoom;
  1503.                 break;
  1504.  
  1505.             case WINDOW_AB:
  1506.                 idcmpflags |= BUTTONIDCMP | STRINGIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1507.                 wintags[7].ti_Data    = (ULONG)ls[MSG_AB_TITLE];
  1508.                 wintags[8].ti_Tag    = WA_Zoom;
  1509.                 break;
  1510.  
  1511.             case WINDOW_SAVEAUDIO:
  1512.                 idcmpflags |= BUTTONIDCMP | STRINGIDCMP | IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW;
  1513.                 wintags[7].ti_Data    = (ULONG)ls[MSG_SAVEAUDIO_TITLE];
  1514.                 wintags[8].ti_Tag    = WA_Zoom;
  1515.                 break;
  1516.  
  1517.             case WINDOW_SAVING:
  1518.                 idcmpflags |= BUTTONIDCMP;
  1519.                 idcmpflags &= (~IDCMP_CLOSEWINDOW);
  1520.                 wintags[4].ti_Data &= ~(WFLG_CLOSEGADGET | WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM);
  1521.                 wintags[7].ti_Data    = (ULONG)ls[MSG_SAVING_TITLE];
  1522.                 break;
  1523.         }
  1524.  
  1525.         if (app->appwin[win].window = OpenWindowTagList(NULL, wintags))
  1526.         {
  1527.             success = TRUE;
  1528.  
  1529.             switch(win)
  1530.             {
  1531.                 case WINDOW_MAIN:
  1532.                     ((struct Process *)FindTask(NULL))->pr_WindowPtr = app->appwin[win].window;
  1533.                     break;
  1534.                 case WINDOW_ABOUT:
  1535.                 case WINDOW_CDINFO:
  1536.                 case WINDOW_DRIVEINFO:
  1537.                     /* cool :-) */
  1538.                     FakeRequestA(app->appwin[win].window, app->visualinfo, FAKEREQUESTSPACE, FAKEREQUESTSPACE, app->appwin[win].maxsize[HEIGHT] - 3 - app->font->ta_YSize - 2 * FAKEREQUESTSPACE - INTERHEIGHT - BUTTONHEIGHT - (win == WINDOW_ABOUT ? 2 : 10));
  1539.                     RefreshGadgets(app->appwin[win].gadgetlist, app->appwin[win].window, NULL);
  1540.                     break;
  1541.                 case WINDOW_PUBSCREEN:
  1542.                     GetPubScreenList(app);
  1543.                     break;
  1544.             }
  1545.  
  1546.             GT_RefreshWindow(app->appwin[win].window, NULL);
  1547.  
  1548.             /* Den shared-IDCMP mit noch einem Fenster teilen */
  1549.             app->appwin[win].window->UserPort = app->idcmp;
  1550.             ModifyIDCMP(app->appwin[win].window, idcmpflags);
  1551.  
  1552.             if (app->appwin[win].img && (win != WINDOW_MAIN))
  1553.                 DrawImage(app->appwin[win].window->RPort, app->appwin[win].img, 0, 0);
  1554.             if (app->appwin[win].itext)
  1555.                 PrintIText(app->appwin[win].window->RPort, app->appwin[win].itext, 0, 0);
  1556.             if (app->appwin[win].bbox)
  1557.                 RefreshBevelBox(app->appwin[win].window->RPort, app->appwin[win].bbox, 0, 0);
  1558.  
  1559.             /*  Menü mit Fenster verbinden  */
  1560.             if (app->menustrip)
  1561.             {
  1562.                 if (!SetMenuStrip(app->appwin[win].window, app->menustrip))
  1563.                 {
  1564.                     CloseWindow(app->appwin[win].window);
  1565.                     return (FALSE);
  1566.                 }
  1567.             }
  1568.  
  1569.             app->appwin[win].winopen = TRUE;
  1570.  
  1571.             /* Gadget-Inhalte zeichnen */
  1572.             MakeInterior(app, win);
  1573.  
  1574.             /* Fenster mit Requester blockieren, falls die Application busy ist */
  1575.             if (app->Flags & APPF_BUSY)
  1576.             {
  1577.                 if (app->appwin[win].request = GetVecA(sizeof(struct Requester), MEMF_PUBLIC))
  1578.                 {
  1579.                     InitRequester(app->appwin[win].request);
  1580.                     if (!Request(app->appwin[win].request, app->appwin[win].window))
  1581.                     {
  1582.                         FreeVec(app->appwin[win].request);
  1583.                         app->appwin[win].request = NULL;
  1584.                     }
  1585.                 }
  1586.             }
  1587.         }
  1588.         else
  1589.             ShowMsgA(ls[MSG_ERROR_TITLE], ls[MSG_NO_WINDOW], app->pubscreenname);
  1590.     }
  1591.  
  1592.     return (success);
  1593. }
  1594. /*------------------ CloseAppWin() ----------------------------< >-*/
  1595. void CloseAppWin(Application *app, WORD win, BOOL realclose)
  1596. {
  1597.     if (!app->appwin[win].window)
  1598.         return;
  1599.  
  1600.     app->appwin[win].maxsize[LEFT]    = app->appwin[win].window->LeftEdge;
  1601.     app->appwin[win].maxsize[TOP]    = app->appwin[win].window->TopEdge;
  1602.  
  1603.     /* Menüs entfernen */
  1604.     if (app->menustrip)
  1605.         ClearMenuStrip(app->appwin[win].window);
  1606.  
  1607.     /* Requester entfernen */
  1608.     if (app->appwin[win].request)
  1609.     {
  1610.         EndRequest(app->appwin[win].request, app->appwin[win].window);
  1611.         FreeVec(app->appwin[win].request);
  1612.         app->appwin[win].request = NULL;
  1613.     }
  1614.  
  1615.     /* So, hier ist die CloseWindowSafely()-Funktion aus den RKMs integriert */
  1616.     Forbid();
  1617.     StripIntuiMessages(app->appwin[win].window);
  1618.     app->appwin[win].window->UserPort = NULL;
  1619.     ModifyIDCMP(app->appwin[win].window, 0L);
  1620.     Permit();
  1621.     /* originalen WindowPointer aus der Process-Struktur wieder eintragen */
  1622.     if (win == WINDOW_MAIN)
  1623.         ((struct Process *)FindTask(NULL))->pr_WindowPtr = app->orgprwin;
  1624.     CloseWindow(app->appwin[win].window);
  1625.     app->appwin[win].window = NULL;
  1626.  
  1627.     if (realclose)
  1628.         app->appwin[win].winopen = FALSE;
  1629.  
  1630.     /* Gadgetliste(n) entfernen */
  1631.     if (app->appwin[win].gadgetlist)
  1632.     {
  1633.         FreeGadgets(app->appwin[win].gadgetlist);
  1634.         app->appwin[win].gadgetlist = NULL;
  1635.     }
  1636.     FreeVec(app->appwin[win].gadget);
  1637.     app->appwin[win].gadget = NULL;
  1638.  
  1639.     /* Intuitexte entfernen */
  1640.     FreeVec(app->appwin[win].itext);
  1641.     app->appwin[win].itext = NULL;
  1642.  
  1643.     /* Images entfernen */
  1644.     FreeVec(app->appwin[win].img);
  1645.     app->appwin[win].img = NULL;
  1646.  
  1647.     /* BevelBoxen entfernen */
  1648.     FreeVec(app->appwin[win].bbox);
  1649.     app->appwin[win].bbox = NULL;
  1650.  
  1651.     /* Window-spezifisches */
  1652.     switch (win)
  1653.     {
  1654.         case WINDOW_MAIN:
  1655.             FreeVec(app->paneldata);
  1656.             app->paneldata = NULL;
  1657.             break;
  1658.         case WINDOW_ABOUT:
  1659.             DisposeScrollObject(app->scroller);
  1660.             break;
  1661.         case WINDOW_PUBSCREEN:
  1662.             FreeList(app->pubscreenlist);
  1663.             app->pubscreenlist = NULL;
  1664.             break;
  1665.         case WINDOW_EDIT:
  1666.             if (realclose)
  1667.                 app->edit_pos = -1;
  1668.             break;
  1669.     }
  1670. }
  1671. /*------------------ StripIntuiMessages() ---------------------< >-*/
  1672. void StripIntuiMessages(struct Window *win)
  1673. {
  1674.     /* Aus den RKMs, aber mit nur einem Parameter */
  1675.  
  1676.     struct IntuiMessage *msg;
  1677.     struct Node *succ;
  1678.  
  1679.     msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
  1680.  
  1681.     while (succ = msg->ExecMessage.mn_Node.ln_Succ)
  1682.     {
  1683.         if (msg->IDCMPWindow == win)
  1684.         {
  1685.             Remove((struct Node *)msg);
  1686.             ReplyMsg((struct Message *)msg);
  1687.         }
  1688.         msg = (struct IntuiMessage *)succ;
  1689.     }
  1690. }
  1691.  
  1692. /*------------------ DoTimeBuffer() ---------------------------< >-*/
  1693. VOID DoTimeBuffer(Application *app)
  1694. {
  1695.     /* Damit ist das Programm tatsächlich kürzer... */
  1696.     register struct CDxRequest *cdx = app->cdstr->cdx;
  1697.  
  1698.     switch (app->cdstr->timemode)
  1699.     {
  1700.         case TIMEMODE_TRACKCUR:
  1701.             FormatA(app->timeshowbuf, "%02ld:%02ld / %02ld:%02ld", (LONG)base2min(cdx->cdx_CurrentRelAddr), (LONG)base2sec(cdx->cdx_CurrentRelAddr), (LONG)base2min(cdx->cdx_TrackLength), (LONG)base2sec(cdx->cdx_TrackLength));
  1702.             break;
  1703.         case TIMEMODE_TRACKREM:
  1704.             FormatA(app->timeshowbuf, "%02ld:%02ld / %02ld:%02ld", (LONG)base2min(cdx->cdx_RelRemainBlocks), (LONG)base2sec(cdx->cdx_RelRemainBlocks), (LONG)base2min(cdx->cdx_TrackLength), (LONG)base2sec(cdx->cdx_TrackLength));
  1705.             break;
  1706.         case TIMEMODE_ALLCUR:
  1707.             FormatA(app->timeshowbuf, "%02ld:%02ld / %02ld:%02ld", (LONG)base2min(cdx->cdx_CurrentAbsAddr), (LONG)base2sec(cdx->cdx_CurrentAbsAddr), (LONG)base2min(cdx->cdx_TOCData->Entry[0].Address), (LONG)base2sec(cdx->cdx_TOCData->Entry[0].Address));
  1708.             break;
  1709.         case TIMEMODE_ALLREM:
  1710.             FormatA(app->timeshowbuf, "%02ld:%02ld / %02ld:%02ld", (LONG)base2min(cdx->cdx_AbsRemainBlocks), (LONG)base2sec(cdx->cdx_AbsRemainBlocks), (LONG)base2min(cdx->cdx_TOCData->Entry[0].Address), (LONG)base2sec(cdx->cdx_TOCData->Entry[0].Address));
  1711.             break;
  1712.     }
  1713. }
  1714. /*------------------ DoABBuffer() -----------------------------< >-*/
  1715. void DoABBuffer(Application *app)
  1716. {
  1717.     if (app->cdstr->a_track > 0)
  1718.         FormatA(app->cdstr->buf_ab_time_a, "%02ld:%02ld.%02ld", (LONG)base2min((app->cdstr->a_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->a_track].Address)), (LONG)base2sec((app->cdstr->a_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->a_track].Address)), (LONG)base2frm((app->cdstr->a_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->a_track].Address)));
  1719.     else
  1720.         strcpy(app->cdstr->buf_ab_time_a, "n/a");
  1721.  
  1722.     if (app->cdstr->b_track > 0)
  1723.         FormatA(app->cdstr->buf_ab_time_b, "%02ld:%02ld.%02ld", (LONG)base2min((app->cdstr->b_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->b_track].Address)), (LONG)base2sec((app->cdstr->b_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->b_track].Address)), (LONG)base2frm((app->cdstr->b_adr - app->cdstr->cdx->cdx_TOCData->Entry[app->cdstr->b_track].Address)));
  1724.     else
  1725.         strcpy(app->cdstr->buf_ab_time_b, "n/a");
  1726.  
  1727.     if (app->appwin[WINDOW_AB].window)
  1728.     {
  1729.         GT_SetGadgetAttrs(app->appwin[WINDOW_AB].gadget[GADGET_AB_A_TIME], app->appwin[WINDOW_AB].window, NULL, GTST_String, app->cdstr->buf_ab_time_a, TAG_END);
  1730.         GT_SetGadgetAttrs(app->appwin[WINDOW_AB].gadget[GADGET_AB_A_TRACK], app->appwin[WINDOW_AB].window, NULL, GTIN_Number, app->cdstr->a_track, TAG_END);
  1731.         GT_SetGadgetAttrs(app->appwin[WINDOW_AB].gadget[GADGET_AB_B_TIME], app->appwin[WINDOW_AB].window, NULL, GTST_String, app->cdstr->buf_ab_time_b, TAG_END);
  1732.         GT_SetGadgetAttrs(app->appwin[WINDOW_AB].gadget[GADGET_AB_B_TRACK], app->appwin[WINDOW_AB].window, NULL, GTIN_Number, app->cdstr->b_track, TAG_END);
  1733.     }
  1734. }
  1735. /*------------------ DoSizeBuffer() ---------------------------< >-*/
  1736. void DoSizeBuffer(Application *app)
  1737. {
  1738.     float    size;
  1739.     BOOL    pointflag;
  1740.     char    str[16];
  1741.     int        pos_s,
  1742.             pos_d,
  1743.             i,
  1744.             j;
  1745.  
  1746.     size = CalcAudioSize(app->cdstr->a_adr, app->cdstr->b_adr, 44100);
  1747.  
  1748.     inttostr((LONG)size, str, 10);
  1749.  
  1750.     pointflag = FALSE;
  1751.     for (pos_s = 0, pos_d = 0; pos_s < strlen(str) % 3; pos_s++, pos_d++)
  1752.     {
  1753.         pointflag = TRUE;
  1754.         app->cdstr->buf_copy_size[pos_d] = str[pos_s];
  1755.     }
  1756.  
  1757.     for (i = 0; i < strlen(str) / 3; i++)
  1758.     {
  1759.         /* Punkt setzen */
  1760.         if (i > 0 || pointflag)
  1761.         {
  1762.             app->cdstr->buf_copy_size[pos_d] = '.';
  1763.             pos_d++;
  1764.         }
  1765.         /* 3 Stellen kopieren */
  1766.         for (j = 0; j < 3; j++, pos_s++, pos_d++)
  1767.             app->cdstr->buf_copy_size[pos_d] = str[pos_s];
  1768.     }
  1769.  
  1770.     /* Nullstelle */
  1771.     app->cdstr->buf_copy_size[pos_d] = 0;
  1772.  
  1773.     if (strlen(app->cdstr->buf_copy_size) < 15)
  1774.     strcat(app->cdstr->buf_copy_size, " Byte");
  1775.  
  1776.     if (app->appwin[WINDOW_SAVEAUDIO].window)
  1777.         GT_SetGadgetAttrs(app->appwin[WINDOW_SAVEAUDIO].gadget[GADGET_SAVEAUDIO_SIZE], app->appwin[WINDOW_SAVEAUDIO].window, NULL, GTTX_Text, app->cdstr->buf_copy_size, TAG_END);
  1778. }
  1779. /*------------------ CalcAudioSize() --------------------------<n>-*/
  1780. float CalcAudioSize(LONG start, LONG end, LONG freq)
  1781. {
  1782.     /* Berechnet die Länge in Bytes bei gegebener Start- und Endadresse
  1783.        und Frequenz in Hz */
  1784.  
  1785.     float    size;
  1786.  
  1787.     size = end - start;
  1788.     /* Abs */
  1789.     if (size < 0)
  1790.         size *= -1;
  1791.  
  1792.     /* Umrechnen in Bytes */
  1793.     return (size / 75 * 4 * freq);
  1794. }
  1795. /*------------------ DoCDDBID() -------------------------------<n>-*/
  1796. void DoCDDBID(struct CDStruct *cdstr)
  1797. {
  1798.     int        i,
  1799.             n         = 0,
  1800.             t         = 0;
  1801.  
  1802.     char    buf[12],
  1803.             *z;
  1804.  
  1805.     struct CDTOCEntry *entry = cdstr->cdx->cdx_TOCData->Entry;
  1806.  
  1807.     for (i = 0; i < cdstr->num_track; i++)
  1808.     {
  1809.         FormatA(buf, "%lu", (int)(entry[i + 1].Address / 75));
  1810.         for (z = buf; *z != 0; z++)    /* Quersumme */
  1811.             n += (*z - '0');
  1812.     }
  1813.  
  1814.     t = ((int)(entry[cdstr->num_track].Address / 75)) - ((int)(entry[0].Address / 75));
  1815.  
  1816.     FormatA(cdstr->buf_cddb_id, "%08x", (((n % 0xff) << 24) | (t << 8) | cdstr->num_track));
  1817. }
  1818.  
  1819. /*------------------ MakeBusy() -------------------------------< >-*/
  1820. void MakeBusy(struct Application *app, BOOL really)
  1821. {
  1822.     WORD win;
  1823.  
  1824.     if (really)
  1825.     {
  1826.         app->Flags |= APPF_BUSY;
  1827.  
  1828.         for (win = ANZ_WINDOWS-1; win >= 0; win--)
  1829.             if (app->appwin[win].window)
  1830.             {
  1831.                 if (IntuitionBase->lib_Version >= 39)
  1832.                     SetWindowPointer(app->appwin[win].window, WA_BusyPointer, TRUE, WA_PointerDelay, TRUE, TAG_END);
  1833.  
  1834.                 if (app->appwin[win].request == NULL)
  1835.                     if (app->appwin[win].request = GetVecA(sizeof(struct Requester), MEMF_PUBLIC))
  1836.                     {
  1837.                         InitRequester(app->appwin[win].request);
  1838.                         if (!Request(app->appwin[win].request, app->appwin[win].window))
  1839.                         {
  1840.                             FreeVec(app->appwin[win].request);
  1841.                             app->appwin[win].request = NULL;
  1842.                         }
  1843.                     }
  1844.             }
  1845.     }
  1846.     else
  1847.     {
  1848.         app->Flags &= ~APPF_BUSY;
  1849.  
  1850.         for (win = ANZ_WINDOWS-1; win >= 0; win--)
  1851.             if (app->appwin[win].window)
  1852.             {
  1853.                 if (IntuitionBase->lib_Version >= 39)
  1854.                     SetWindowPointer(app->appwin[win].window, WA_BusyPointer, FALSE, TAG_END);
  1855.  
  1856.                 if (app->appwin[win].request)
  1857.                 {
  1858.                     EndRequest(app->appwin[win].request, app->appwin[win].window);
  1859.                     FreeVec(app->appwin[win].request);
  1860.                     app->appwin[win].request = NULL;
  1861.                 }
  1862.             }
  1863.     }
  1864. }
  1865.  
  1866. /*------------------ IsDefaultTitle() -------------------------< >-*/
  1867. BOOL IsDefaultTitle(char *str, UBYTE track)
  1868. {
  1869.     char defaultstr[MAXTITLENAME + 1];
  1870.  
  1871.     /* Defaultstring erstellen */
  1872.     strncpy(defaultstr, ls[MSG_CDTITLE_TRACK], MAXTITLENAME - 5);
  1873.     strcat(defaultstr, " #");
  1874.     inttostr(track, defaultstr + strlen(defaultstr), 10);
  1875.  
  1876.     /* Jetzt vergleichen */
  1877.     if (strcmp(str, defaultstr) == 0)
  1878.         return (TRUE);
  1879.     else
  1880.         return (FALSE);
  1881. }
  1882.  
  1883. /*------------------ RefreshBevelBox() ------------------------< >-*/
  1884. void RefreshBevelBox(struct RastPort *rp, struct BevelBox *bbox, WORD xoffset, WORD yoffset)
  1885. {
  1886.     struct BevelBox *tempbox;
  1887.  
  1888.     for (tempbox = bbox; tempbox; tempbox = tempbox->bb_NextBevelBox)
  1889.         DrawBevelBox(rp, xoffset + tempbox->bb_LeftEdge, yoffset + tempbox->bb_TopEdge, tempbox->bb_Width, tempbox->bb_Height,
  1890.                                             GT_VisualInfo,    tempbox->bb_VisualInfo,
  1891.                                             GTBB_FrameType,    tempbox->bb_FrameType,
  1892.                                             GTBB_Recessed,    tempbox->bb_Recessed,
  1893.                                             TAG_DONE);
  1894. }
  1895.  
  1896. /*------------------ ManageNewSize() --------------------------< >-*/
  1897. void ManageNewSize(Application *app, WORD win)
  1898. {
  1899.     register struct AppWin *appwin = &app->appwin[win];
  1900.  
  1901.     appwin->maxsize[WIDTH]    = appwin->window->Width;
  1902.     appwin->maxsize[HEIGHT]    = appwin->window->Height;
  1903.  
  1904.     RemoveGList(appwin->window, appwin->gadgetlist, -1);
  1905.  
  1906.     /* Gadgetliste(n) entfernen */
  1907.     if (appwin->gadgetlist)
  1908.     {
  1909.         FreeGadgets(appwin->gadgetlist);
  1910.         appwin->gadgetlist = NULL;
  1911.     }
  1912.     FreeVec(appwin->gadget);
  1913.     appwin->gadget = NULL;
  1914.  
  1915.     /* Intuitexte entfernen */
  1916.     FreeVec(appwin->itext);
  1917.     appwin->itext = NULL;
  1918.  
  1919.     EraseRect(appwin->window->RPort,appwin->window->BorderLeft,
  1920.                                     appwin->window->BorderTop,
  1921.                                     appwin->window->Width - appwin->window->BorderRight - 1,
  1922.                                     appwin->window->Height - appwin->window->BorderBottom - 1);
  1923.     RefreshWindowFrame(appwin->window);
  1924.     MakeVisuals(app, win);
  1925.     AddGList(appwin->window, appwin->gadgetlist, ~0, -1, NULL);
  1926.  
  1927.     /* Nicht so toll, aber was soll es */
  1928.     switch (win)
  1929.     {
  1930.         case WINDOW_CDINFO:
  1931.         case WINDOW_DRIVEINFO:
  1932.             FakeRequestA(appwin->window, app->visualinfo, FAKEREQUESTSPACE, FAKEREQUESTSPACE, appwin->maxsize[HEIGHT] - 3 - app->font->ta_YSize - 2 * FAKEREQUESTSPACE - INTERHEIGHT - BUTTONHEIGHT - 10);
  1933.             break;
  1934.     }
  1935.  
  1936.     /* ggf. Intuitexte neu */
  1937.     if (appwin->itext)
  1938.         PrintIText(appwin->window->RPort, appwin->itext, 0, 0);
  1939.  
  1940.  
  1941.     MakeInterior(app, win);
  1942.     RefreshGList(appwin->gadgetlist, appwin->window, NULL, -1);
  1943. }
  1944. /*------------------ AdjustNewSize() --------------------------< >-*/
  1945. void AdjustNewSize(struct Application *app, WORD win, WORD newx, WORD newy)
  1946. {
  1947.     register struct AppWin *appwin = &app->appwin[win];
  1948.  
  1949.     /* Manchmal müssen die vorgegebenen Werte bei größenveränderbaren Gadgets */
  1950.     /* überschrieben werden, da die Mindestgröße vom verwendeten Font und     */
  1951.     /* natürlich vom verwendeten Text (Locale) abhängen kann */
  1952.     /* Diese Funktion überprüft also, ob eine derartige Änderung notwendig ist */
  1953.  
  1954.     if (newx > appwin->maxsize[WIDTH])
  1955.         appwin->maxsize[WIDTH] = newx;
  1956.     if (newx > appwin->minsize[WIDTH])
  1957.         appwin->minsize[WIDTH] = newx;
  1958.     if (newx > appwin->minwidth)
  1959.         appwin->minwidth = newx;
  1960.  
  1961.     if (appwin->maxsize[WIDTH] > appwin->maxwidth)
  1962.         appwin->maxsize[WIDTH] = appwin->maxwidth;
  1963.  
  1964.     if (newy > appwin->maxsize[HEIGHT])
  1965.         appwin->maxsize[HEIGHT] = newy;
  1966.     if (newy > appwin->minsize[HEIGHT])
  1967.         appwin->minsize[HEIGHT] = newy;
  1968.     if (newy > appwin->minheight)
  1969.         appwin->minheight = newy;
  1970.  
  1971.     if (appwin->maxsize[HEIGHT] > appwin->maxheight)
  1972.         appwin->maxsize[HEIGHT] = appwin->maxheight;
  1973. }
  1974.  
  1975. /*------------------ TextWidth() ------------------------------< >-*/
  1976. WORD TextWidth(char *text, struct TextAttr *font)
  1977. {
  1978.     struct IntuiText itext = {    1, 0,        /* FrontPen, BackPen */
  1979.                                 JAM1,        /* DrawMode */
  1980.                                 0, 0,        /* LeftEdge, TopEdge */
  1981.                                 font,        /* ITextFont */
  1982.                                 text,        /* IText */
  1983.                                 NULL };        /* NextText */
  1984.  
  1985.     return ((WORD)IntuiTextLength(&itext));
  1986. }
  1987. /*------------------ FindWidest() -----------------------------< >-*/
  1988. WORD FindWidest(char **textarr, struct TextAttr *font)
  1989. {
  1990.     int highest = 0, counter, temp;
  1991.  
  1992.     for (counter = 0; textarr[counter] != NULL; counter++)
  1993.     {
  1994.         temp = TextWidth(textarr[counter], font);
  1995.         if (temp > highest)
  1996.             highest = temp;
  1997.     }
  1998.  
  1999.     return highest;
  2000. }
  2001.  
  2002. /*------------------ NumToStr() -------------------------------< >-*/
  2003. char *NumToStr(LONG number)
  2004. {
  2005.     static char str[14];
  2006.     return (inttostr(number, str, 10));
  2007. }
  2008. /*------------------ RandomNum() ------------------------------< >-*/
  2009. LONG RandomNum(LONG startnum, LONG endnum)
  2010. {
  2011.     LONG result;
  2012.     struct DateStamp date;
  2013.  
  2014.     DateStamp(&date);
  2015.     srand((unsigned int)date.ds_Tick);
  2016.  
  2017.     /* Es wird eine Zahl zwischen startnum und endnum ermittelt */
  2018.     /* (einschließlich startnum bzw. endnum!) */
  2019.  
  2020.     result = LONG((((double)(endnum - startnum + 1) * ((double)rand() / double(RAND_MAX))) + startnum));
  2021.     if (result > endnum) result = endnum;
  2022.     return (result);
  2023. }
  2024. /*------------------ FitInteger() -----------------------------< >-*/
  2025. LONG FitInteger(LONG num, LONG lowborder, LONG highborder)
  2026. {
  2027.     if (num < lowborder)
  2028.         return (lowborder);
  2029.     else if (num > highborder)
  2030.         return (highborder);
  2031.     else
  2032.         return (num);
  2033. }
  2034. /*------------------ InsertBoolean() --------------------------< >-*/
  2035. LONG InsertBoolean(LONG dest, LONG flag, BOOL state)
  2036. {
  2037.     if (state)
  2038.         return (dest | flag);
  2039.     else
  2040.         return (dest & ~flag);
  2041. }
  2042.  
  2043. /*------------------ FreeList() -------------------------------< >-*/
  2044. void FreeList(List *list)
  2045. {
  2046.     if (list)
  2047.     {
  2048.         Node *temp_node, *next_temp_node;
  2049.  
  2050.         for (temp_node = list->lh_Head; temp_node->ln_Succ;)
  2051.         {
  2052.             next_temp_node = temp_node->ln_Succ;
  2053.             FreeVec(temp_node);
  2054.             temp_node = next_temp_node;
  2055.         }
  2056.  
  2057.         FreeVec(list);
  2058.     }
  2059. }
  2060. /*------------------ CopyList() -------------------------------< >-*/
  2061. struct List *CopyList(struct List *quelle, int nodesize)
  2062. {
  2063.     struct Node     *quelltemp,
  2064.             *zieltemp;
  2065.     struct List    *ziel;
  2066.     int        i;
  2067.  
  2068.     if (ziel = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR))
  2069.     {
  2070.         NewList(ziel);
  2071.  
  2072.         for (quelltemp = quelle->lh_Head; quelltemp->ln_Succ; quelltemp = quelltemp->ln_Succ)
  2073.             if (zieltemp = GetVecA(nodesize, MEMF_PUBLIC))
  2074.             {
  2075.                 for (i = 0; i < nodesize; i++)
  2076.                     ((char *)zieltemp)[i] = ((char *)quelltemp)[i];
  2077.  
  2078.                 AddTail(ziel, zieltemp);
  2079.             }
  2080.     }
  2081.  
  2082.     return(ziel);
  2083. }
  2084. /*------------------ FindNode() -------------------------------< >-*/
  2085. Node *FindNode(List * list, ULONG number)
  2086. {
  2087.     Node * tempnode = list->lh_Head;
  2088.     ULONG i;
  2089.  
  2090.     for (i = 0; i < number; i++)
  2091.     {
  2092.         if (tempnode->ln_Succ)
  2093.             tempnode = tempnode->ln_Succ;
  2094.         else
  2095.         {
  2096.             tempnode = NULL;
  2097.             break;
  2098.         }
  2099.     }
  2100.     return (tempnode);
  2101. }
  2102. /*------------------ GetNodeNumber() --------------------------< >-*/
  2103. int GetNodeNumber(struct List *list, struct Node *node)
  2104. {
  2105.     struct Node *tempnode;
  2106.     int count = 0;
  2107.  
  2108.     /* gibt die Nummer der Node in der Liste zurück */
  2109.     if (list && node)
  2110.     {
  2111.         for (tempnode = list->lh_Head; tempnode->ln_Succ; tempnode = tempnode->ln_Succ, count++)
  2112.             if (tempnode == node)
  2113.                 break;
  2114.     }
  2115.  
  2116.     return (count);
  2117. }
  2118.  
  2119. /*------------------ CreateScrollObject() ---------------------< >-*/
  2120. BOOL CreateScrollObject(struct Scroll *so)
  2121. {
  2122.     int widest, count;
  2123.     struct IntuiText *itexts;
  2124.     BOOL success = TRUE;
  2125.  
  2126.     for (count = 0; so->Text[count]; count++)
  2127.     {
  2128.     }
  2129.  
  2130.     so->p_height    = count * so->Font->ta_YSize + 2 * so->Height;
  2131.     so->p_pos    = 0;
  2132.  
  2133.     widest = FindWidest(so->Text, so->Font);
  2134.  
  2135.     if (itexts = GetVecA(sizeof(struct IntuiText) * count, MEMF_CLEAR))
  2136.     {
  2137.         /* Rastport etc. */
  2138.         if (so->RPort = GetVecA(sizeof(struct RastPort), MEMF_CLEAR))
  2139.         {
  2140.             InitRastPort(so->RPort);
  2141.  
  2142.             if (so->RPort->BitMap = GetVecA(sizeof(struct BitMap), MEMF_CLEAR))
  2143.             {
  2144.                 if (so->RPort->BitMap->Planes[0] = GetVecA((so->Width / 8) * so->p_height, MEMF_CLEAR | MEMF_CHIP))
  2145.                 {
  2146.                     int i;
  2147.  
  2148.                     InitBitMap(so->RPort->BitMap, 1, so->Width, so->p_height);
  2149.  
  2150.                     for (i = 0; i < count; i++)
  2151.                     {
  2152.                         itexts[i].FrontPen    = 1;
  2153.                         itexts[i].DrawMode    = JAM1;
  2154.                         itexts[i].LeftEdge    = (so->Width - TextWidth(so->Text[i], so->Font)) / 2;
  2155.                         itexts[i].TopEdge    = so->Height + i * so->Font->ta_YSize;
  2156.                         itexts[i].ITextFont = so->Font;
  2157.                         itexts[i].IText        = so->Text[i];
  2158.                         itexts[i].NextText    = NULL;
  2159.  
  2160.                         PrintIText(so->RPort, &itexts[i], 0, 0);
  2161.                         if (so->Flags[i])
  2162.                             PrintIText(so->RPort, &itexts[i], 1, 0);
  2163.                     }
  2164.  
  2165.                     /* Image vorbereiten */
  2166.                     so->Img.LeftEdge    = so->LeftEdge;
  2167.                     so->Img.TopEdge        = so->TopEdge;
  2168.                     so->Img.Width        = so->Width;
  2169.                     so->Img.Height        = so->Height;
  2170.                     so->Img.Depth        = 1;
  2171.                     so->Img.PlanePick    = 1;
  2172.                     so->Img.PlaneOnOff    = 0;
  2173.                     so->Img.NextImage    = NULL;
  2174.  
  2175.                     success = TRUE;
  2176.                 }
  2177.             }
  2178.         }
  2179.         FreeVec(itexts);
  2180.     }
  2181.  
  2182.     return (success);
  2183. }
  2184. /*------------------ UpdateScrollObject() ---------------------< >-*/
  2185. void UpdateScrollObject(struct Scroll *so, struct Window *win)
  2186. {
  2187.     so->Img.ImageData = (UWORD *)(so->RPort->BitMap->Planes[0] + so->p_pos * (so->Width / 8));
  2188.  
  2189.     so->p_pos++;
  2190.     if (so->p_pos > so->p_height - so->Height)
  2191.         so->p_pos = 0;
  2192.  
  2193.     DrawImage(win->RPort, &(so->Img), 0, 0);
  2194. }
  2195. /*------------------ DisposeScrollObject() --------------------< >-*/
  2196. void DisposeScrollObject(struct Scroll *so)
  2197. {
  2198.     if (so->RPort->BitMap->Planes[0])
  2199.     {
  2200.         FreeVec(so->RPort->BitMap->Planes[0]);
  2201.         so->RPort->BitMap->Planes[0] = NULL;
  2202.     }
  2203.     if (so->RPort->BitMap)
  2204.     {
  2205.         FreeVec(so->RPort->BitMap);
  2206.         so->RPort->BitMap = NULL;
  2207.     }
  2208.     if (so->RPort)
  2209.     {
  2210.         FreeVec(so->RPort);
  2211.         so->RPort = NULL;
  2212.     }
  2213. }
  2214.  
  2215. /*------------------ GetPubScreenName() -----------------------< >-*/
  2216. BOOL GetPubScreenName(struct Screen *wantedscreen, char *buffer)
  2217. {
  2218.     /* Diese Funktion schaut in der PubScreenList nach, ob die Adresse  */
  2219.     /* vorhanden ist, und kopiert den Screennamen in buffer (Buffer muß */
  2220.     /* also mindestens MAXPUBSCREENNAME + 1 lang sein */
  2221.  
  2222.     struct PubScreenNode *actnode = NULL;
  2223.     struct List *pubscreenlist = NULL;
  2224.     BOOL success = FALSE;
  2225.  
  2226.     if (pubscreenlist = LockPubScreenList())
  2227.     {
  2228.         for (actnode = (struct PubScreenNode *)pubscreenlist->lh_Head; actnode->psn_Node.ln_Succ; actnode = (struct PubScreenNode *)actnode->psn_Node.ln_Succ)
  2229.         {
  2230.             if (wantedscreen == actnode->psn_Screen)
  2231.             {
  2232.                 strncpy(buffer, actnode->psn_Node.ln_Name, MAXPUBSCREENNAME);
  2233.                 success = TRUE;
  2234.                 break;
  2235.             }
  2236.         }
  2237.         UnlockPubScreenList();
  2238.     }
  2239.  
  2240.     return (success);
  2241. }
  2242. /*------------------ GetPubScreenList() -----------------------< >-*/
  2243. BOOL GetPubScreenList(Application *app)
  2244. {
  2245.     struct List *systemlist;
  2246.     struct MyPubScreenNode *cur_node;
  2247.     struct Node *temp_node;
  2248.  
  2249.     if (app->appwin[WINDOW_PUBSCREEN].window)
  2250.         GT_SetGadgetAttrs(app->appwin[WINDOW_PUBSCREEN].gadget[GADGET_PUBSCREEN_LISTVIEW], app->appwin[WINDOW_PUBSCREEN].window, NULL, GTLV_Labels, ~0, TAG_END);
  2251.  
  2252.     FreeList(app->pubscreenlist);
  2253.  
  2254.     if (!(app->pubscreenlist = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR)))
  2255.         return (FALSE);
  2256.  
  2257.     NewList(app->pubscreenlist);
  2258.  
  2259.     if (!(systemlist = LockPubScreenList()))
  2260.         return (FALSE);
  2261.  
  2262.     for (temp_node = systemlist->lh_Head; temp_node->ln_Succ; temp_node = temp_node->ln_Succ)
  2263.     {
  2264.         if (!(cur_node = GetVecA(sizeof(struct MyPubScreenNode), MEMF_PUBLIC | MEMF_CLEAR)))
  2265.             return (NULL);
  2266.         strncpy(cur_node->mpsn_pubscreenname, temp_node->ln_Name, MAXPUBSCREENNAME);
  2267.         cur_node->mpsn_Node.ln_Name = cur_node->mpsn_pubscreenname;
  2268.         AddTail(app->pubscreenlist, (Node *) cur_node);
  2269.     }
  2270.  
  2271.     UnlockPubScreenList();
  2272.  
  2273.     if (app->appwin[WINDOW_PUBSCREEN].window)
  2274.         GT_SetGadgetAttrs(app->appwin[WINDOW_PUBSCREEN].gadget[GADGET_PUBSCREEN_LISTVIEW], app->appwin[WINDOW_PUBSCREEN].window, NULL, GTLV_Labels, app->pubscreenlist, TAG_END);
  2275.  
  2276.     return (TRUE);
  2277. }
  2278.