' DS4QB v1.1 - Demo program #2 - MP3 Player
' Feel free to use any of these routines in your own programs.

DEFINT A-Z

DECLARE SUB DrawBackground ()
DECLARE SUB DrawWindow (YPos%, XPos%, YSize%, XSize%, Caption AS STRING, TextLine%)
DECLARE SUB GetDirFromUser (Mp3Dir$)
DECLARE SUB SwitchDir (Path AS STRING)
DECLARE SUB FileLists (Mask AS STRING, FList() AS STRING, NumFiles%)
DECLARE SUB CopyFile (SourcePath AS STRING, SourceFile AS STRING, DestPath AS STRING, DestFile AS STRING)
DECLARE FUNCTION CurrentFolder$ ()

'$INCLUDE: 'DEXTERN.BI'

ON ERROR GOTO rNext

DIM FileList(512) AS STRING
DIM StatusStr(5)  AS STRING
DIM Tick(4) AS STRING * 1

' Initialize strings

FileList(0) = "Change Mp3 directory"

StatusStr(0) = "No music is loaded."
StatusStr(1) = "Music is playing."
StatusStr(2) = "Music is stopped."
StatusStr(3) = "Music is paused."
StatusStr(4) = "Loading music..."
StatusStr(5) = "Shutting down..."

Tick(0) = "|"
Tick(1) = "/"
Tick(2) = "-"
Tick(3) = "\"
Tick(4) = "þ"

ScrollView = 0
Status = 0
Volume = 50

SCREEN 0, , 0, 0: CLS

' Initialize DS4QB++
R = DS4QB.Init(CURRENT, DEFAULT)

IF R = -1 THEN
  PRINT "Error! SOUNDSYS.DAT is missing!": END
 ELSEIF R = -3 THEN
  PRINT "Error! Please run SETUP.EXE!": END
 ELSEIF R = -2 THEN
  PRINT "Error! Could not connect to slave!": END
END IF

' Setup dir's and load the list of Mp3's in the current directory

StartDir$ = CurrentFolder$
Mp3Dir$ = StartDir$ + "\Music"

SwitchDir Mp3Dir$
FileLists "*.MP3", FileList(), NumFiles
SwitchDir StartDir$

SCREEN 0, , 2, 0: CLS

' Draw our window and background
DrawBackground
DrawWindow 4, 4, 17, 72, "QB Mp3 Player", 6
COLOR 15, 1: LOCATE 12, 6: PRINT STRING$(70, "Ä");

' Draw command buttons
LOCATE 5, 7: COLOR 7, 1: PRINT "[";
COLOR 15, 1: PRINT "P";
COLOR 7, 1: PRINT "lay]             [P";
COLOR 15, 1: PRINT "a";
COLOR 7, 1: PRINT "use]              [";
COLOR 15, 1: PRINT "R";
COLOR 7, 1: PRINT "esume]              [";
COLOR 15, 1: PRINT "S";
COLOR 7, 1: PRINT "top]"

' (The above is now buffered in video memory page 2)

SCREEN 0, , 1, 0: CLS

DO
 SELECT CASE Status
  CASE 1
   ' Get the current position of our music, we only need to call this about
   ' once a second--it's a good idea to make sure things arn't called more
   ' often then they need to be if you want to keep your program running fast
   ' and lagg-free.
   IF TIMER - T# > 1 THEN
    Position& = DS4QB.GetMusicPosition&(1)
    IF Position& >= Length& THEN Status = 2: Position& = 0
    T# = TIMER
   END IF

  CASE 4
   ' Load Mp3 music, and play it
   DS4QB.DeleteMusic 1
   ' Load our mp3, no flags (disable looping)
   DS4QB.LoadMusic 1, "Temp.Mp3", NULL
   DS4QB.SetMasterVolume Volume
   DS4QB.PlayMusic 1
   ' Retreive the length of our Mp3
   Length& = DS4QB.GetMusicLength&(1)
   Status = 1

  CASE 5
   EXIT DO
 END SELECT

 ' Calculate percentange of the song played
 IF Status THEN PosPer = (100 / Length&) * Position&

 Key$ = UCASE$(INKEY$)
 SELECT CASE Key$
  CASE CHR$(0) + "P"
   ' Move selection down
   SelectPos = SelectPos + 1

  CASE CHR$(0) + "H"
   ' Move selection up
   SelectPos = SelectPos - 1

  CASE "P"
   ' Play music if music is loaded
   IF Status THEN DS4QB.PlayMusic 1: Status = 1

  CASE "A"
   ' Pause music if music is playing
   IF Status = 1 THEN DS4QB.PauseMusic 1: Status = 3

  CASE "S"
   ' Stop music if music is loaded
   IF Status THEN DS4QB.StopMusic 1: Status = 2
   Position& = 0

  CASE "R"
   ' Resume music if music is paused
   IF Status = 3 THEN DS4QB.ResumeMusic 1: Status = 1

  CASE ",", "<"
   ' Lower position 10%
   Position& = Position& - (Length& / 10)
   IF Position& < 0 THEN Position& = 0
   DS4QB.SetMusicPosition 1, Position&
   T# = TIMER

  CASE ".", ">"
   ' Raise position 10%
   Position& = Position& + (Length& / 10)
   IF Position& > Length& THEN Position& = Length&
   DS4QB.SetMusicPosition 1, Position&
   T# = TIMER
  
  CASE "+", "="
   ' Lower volume 5%
   Volume = Volume + 5
   IF Volume > 100 THEN Volume = 100
   DS4QB.SetMasterVolume Volume
   T# = TIMER

  CASE "_", "-"
   ' Rais volume 5%
   Volume = Volume - 5
   IF Volume < 0 THEN Volume = 0
   DS4QB.SetMasterVolume Volume
   T# = TIMER

  CASE CHR$(32), CHR$(13)
   IF SelectPos + SelectView THEN
     ' Load an Mp3
     IF LEN(FileList(SelectPos + ScrollView)) THEN
      CopyFile Mp3Dir$, FileList(SelectPos + ScrollView), StartDir$, "Temp.Mp3"
      NeedDelete = -1
      Status = 4
     END IF
    ELSE
     ' Select a new Mp3 directory
     NumFiles = 0
     GetDirFromUser Mp3Dir$

     IF UCASE$(Mp3Dir$) <> UCASE$(StartDir$) THEN SwitchDir Mp3Dir$
     FileLists "*.MP3", FileList(), NumFiles
     IF UCASE$(Mp3Dir$) <> UCASE$(StartDir$) THEN SwitchDir StartDir$
   END IF

  CASE CHR$(27)
   Status = 5

 END SELECT

 ' Make sure the selector doesn't go out of bounds, and scroll
 ' the view if it does
 IF SelectPos < 0 THEN SelectPos = 0: ScrollView = ScrollView - 1
 IF SelectPos > 8 THEN SelectPos = 8: ScrollView = ScrollView + 1

 ' Make sure the view doesn't go out of bounds
 IF ScrollView < 0 THEN ScrollView = 0
 IF ScrollView > NumFiles - 9 THEN ScrollView = NumFiles - 9
 IF ScrollView < 0 THEN ScrollView = 0

 ' Begin draw
 ' Draw buffered background
 PCOPY 2, 1

 ' Yuck!! o_O (Show our volume/play position meters)
 COLOR 7, 1: LOCATE 7, 9: PRINT "Volume: [";
 COLOR 15, 1: PRINT "-"; : COLOR 7, 1: PRINT "] ";
 IF Volume THEN PRINT STRING$((Volume / 2), "Û");
 IF Volume < 100 THEN PRINT STRING$(50 - (Volume / 2), "±");
 PRINT " ["; : COLOR 15, 1: PRINT "+"; : COLOR 7, 1: PRINT "]";

 COLOR 7, 1: LOCATE 9, 7: PRINT "Position: [";
 COLOR 15, 1: PRINT "<"; : COLOR 7, 1: PRINT "] ";
 IF PosPer THEN PRINT STRING$((PosPer / 2), "Û");
 IF PosPer < 100 THEN PRINT STRING$(50 - (PosPer / 2), "±");
 PRINT " ["; : COLOR 15, 1: PRINT ">"; : COLOR 7, 1: PRINT "]";

 ' Display our file selection menu and stuff
 LOCATE 11, 7
 COLOR 7, 1: PRINT "Current Mp3 directory: ";
 COLOR 15, 1: PRINT MID$(Mp3Dir$, 1, 45)
 FOR i = 0 TO 8
  LOCATE 13 + i, 7
  IF SelectPos = i THEN
    IF ScrollView + i = 0 THEN
      COLOR 15, 7
     ELSE
      COLOR 8, 7
    END IF
    PRINT FileList(i + ScrollView) + SPACE$(68 - LEN(FileList(i + ScrollView)))
   ELSE
    IF ScrollView + i = 0 THEN
      COLOR 15, 1
     ELSE
      COLOR 7, 1
    END IF
    PRINT FileList(i + ScrollView)
   END IF
 NEXT

 ' Draw our status bar
 COLOR 0, 7
 IF TIMER - TickT# > .1 AND Status = 1 THEN Ticker = (Ticker + 1) MOD 4: TickT# = TIMER ELSE IF Status <> 1 THEN Ticker = 4
 Stat$ = Tick(Ticker) + " " + StatusStr(Status)
 LOCATE 25, 1: PRINT "  " + Stat$ + SPACE$(80 - (LEN(Stat$) + 2));

 ' Copy final result to screen
 PCOPY 1, 0
 ' End draw
LOOP

' Close off

DS4QB.Close

IF NeedDelete THEN KILL "Temp.Mp3"
KILL "FileList.TMP"

END

rNext:

RESUME NEXT

SUB CopyFile (SourcePath AS STRING, SourceFile AS STRING, DestPath AS STRING, DestFile AS STRING)
 IF RIGHT$(SourcePath, 1) <> "\" THEN Slash$ = "\"

 Handle = FREEFILE
 OPEN "FL.BAT" FOR OUTPUT AS #Handle
  PRINT #Handle, "@ECHO OFF"
  PRINT #Handle, "@COPY " + CHR$(34) + SourcePath + Slash$ + SourceFile + CHR$(34) + " " + CHR$(34) + DestPath + "\" + DestFile + CHR$(34) + " >FileList.TMP"
 CLOSE #Handle

 SHELL "FL.BAT >FileList.TMP"
 KILL "FileList.TMP"
 KILL "FL.BAT"
END SUB

FUNCTION CurrentFolder$
 SHELL "DIR Soundsys.Dat >FileList.TMP"

 Handle = FREEFILE

 OPEN "FileList.TMP" FOR INPUT AS #Handle
  FOR i = 1 TO 4
   LINE INPUT #Handle, Text$
  NEXT
 CLOSE #Handle

 KILL "FileList.TMP"

 CurrentFolder$ = MID$(Text$, 15, LEN(Text$) - 14)
END FUNCTION

SUB DrawBackground
 COLOR 7, 8
 FOR i = 1 TO 25
  LOCATE i, 1: PRINT STRING$(80, "²");
 NEXT

 Title$ = " þ DS4QB++ v1.1 Demo þ "
 PSNX = 40 - (LEN(Title$) \ 2)

 COLOR 0, 7
 LOCATE 1, 1: PRINT SPACE$(PSNX) + Title$ + SPACE$(80 - PSNX - LEN(Title$));
END SUB

SUB DrawWindow (YPos, XPos, YSize, XSize, Caption AS STRING, TextLine)
 Text$ = " þ " + Caption + " þ "
 CPos = (XSize \ 2) - (LEN(Text$) \ 2)
 COLOR 15, 1: LOCATE YPos, XPos: PRINT "Ú" + STRING$(CPos, "Ä") + Text$ + STRING$(XSize - CPos - LEN(Text$), "Ä");
 COLOR 7, 1: PRINT "¿"
 FOR Y = YPos + 1 TO YPos + YSize
  COLOR 15, 1: LOCATE Y, XPos: PRINT "³" + SPACE$(XSize);
  COLOR 7, 1: PRINT "³";
 NEXT Y
 COLOR 15, 1
 LOCATE Y, XPos: PRINT "À";
 COLOR 7, 1: PRINT STRING$(XSize, "Ä") + "Ù";
 COLOR 15, 1: LOCATE YPos + TextLine, XPos + 2: PRINT STRING$(XSize - 2, "Ä");

 COLOR 8, 0:
 FOR X = XPos + 1 TO XPos + XSize + 2
  LOCATE YPos + YSize + 2, X: PRINT CHR$(SCREEN(YPos + YSize + 2, X));
 NEXT

 FOR Y = YPos + 1 TO YPos + YSize + 1
  LOCATE Y, XPos + XSize + 2: PRINT CHR$(SCREEN(Y, XPos + XSize + 2));
 NEXT
 COLOR 7, 1
END SUB

SUB FileLists (Mask AS STRING, FList() AS STRING, NumFiles)
 SHELL "DIR " + Mask + " >FileList.TMP"

 NumFiles = 0

 Handle = FREEFILE
 OPEN "FileList.TMP" FOR INPUT AS #Handle
  FOR D = 1 TO 5 + (-(DS4QB.GetOS% = WINNT) * 2)
   LINE INPUT #Handle, Text$
  NEXT

  DO
   FileName$ = ""
  
   LINE INPUT #Handle, Text$
   IF INSTR(LCASE$(Text$), "file(s)") THEN EXIT DO

   SELECT CASE DS4QB.GetOS%
    CASE WIN9X
     FOR i = 45 TO LEN(Text$)
      FileName$ = FileName$ + MID$(Text$, i, 1)
     NEXT i
    CASE WINNT
     FOR i = 40 TO LEN(Text$)
      FileName$ = FileName$ + MID$(Text$, i, 1)
     NEXT i
   END SELECT

   IF FileName$ <> "" THEN
    NumFiles = NumFiles + 1
    IF NumFiles > UBOUND(FList, 1) THEN NumFiles = NumFiles - 1: EXIT SUB
    FList(NumFiles) = FileName$
   END IF
  LOOP UNTIL EOF(Handle)
 CLOSE #Handle

 KILL "FileList.TMP"
END SUB

SUB GetDirFromUser (Mp3Dir$)
 ODir$ = Mp3Dir$

 PCOPY 0, 3
 
 SCREEN 0, , 3, 0
 DrawWindow 7, 5, 4, 69, "Select Mp3 directory", 3

 LOCATE 8, 8: PRINT "      Enter the directory in which you have your mp3's in."
 LOCATE 9, 8: PRINT "          Example: D:\MP3 (Don't put a \ at the end)"

 DO
  Key$ = INKEY$
  SELECT CASE UCASE$(Key$)
   CASE "A" TO "Z", "0" TO "9", " ", "\", "-", ":"
    IF LEN(Mp3Dir$) < 128 THEN Mp3Dir$ = Mp3Dir$ + Key$
   CASE CHR$(8)
    IF LEN(Mp3Dir$) > 1 THEN
      Mp3Dir$ = MID$(Mp3Dir$, 1, LEN(Mp3Dir$) - 1)
     ELSE
      Mp3Dir$ = ""
    END IF
   CASE CHR$(13)
    IF Mp3Dir$ = "" THEN Mp3Dir$ = CurrentFolder$
    EXIT DO
   CASE CHR$(27)
    Mp3Dir$ = ODir$
    EXIT DO
  END SELECT
 
  IF TIMER - T# > .5 THEN Cur = (Cur + 1) AND 1: T# = TIMER
  IF Cur THEN Currsor$ = "Û" ELSE Currsor$ = ""
 
  COLOR 7, 1: LOCATE 11, 8
  PRINT MID$(Mp3Dir$, 1, 64) + Currsor$ + " "

  PCOPY 3, 0
 LOOP

 SCREEN 0, , 1, 0
END SUB

SUB SwitchDir (Path AS STRING)
 KILL "FileList.TMP"

 DIM NPath AS STRING: NPath = Path

 IF RIGHT$(NPath, 1) <> "\" THEN Slash$ = "\"
 SHELL MID$(NPath, 1, 2) + Slash$ + " >FileList.TMP"
 SHELL "CD " + CHR$(34) + NPath + CHR$(34) + " >FileList.TMP"
END SUB

