DECLARE SUB DisplayInfo ()
DECLARE SUB SortSongsRev ()
DECLARE SUB SortSongs ()
DECLARE SUB InitScreen ()
DECLARE SUB PlaySongs ()
DECLARE SUB SetTags (x!)
DECLARE SUB PointAt (position!, Symbol$)
DECLARE SUB ListSongs ()
DECLARE SUB GetDir ()

CONST MaxListSize = 1024
DIM SHARED Song$(MaxListSize), Tag(MaxListSize)
DIM SHARED NoOfSongs, MIDDir$, ListPortal, ListCursor, Parameter$, RptFlag

Parameter$ = ""
RptFlag = NOT 0
FirstTime = NOT 0

MIDDir$ = "."

CLS
GOTO SkipAskDir

Start:

CLS
INPUT "Enter directory: ", MIDDir$

IF MIDDir$ = "" THEN MIDDir$ = "."

SkipAskDir:

GetDir

REM IF NoOfSongs = 0 THEN
REM     PRINT "No MIDI files found.  Exiting..."
REM     GOTO Done
REM END IF
SetTags (0)
ListPortal = 1
ListCursor = 1

CLS
InitScreen
ListSongs

IF (NoOfSongs = 0) AND FirstTime THEN DisplayInfo

DO
    
     IF ListCursor > NoOfSongs THEN
          ListCursor = NoOfSongs
     ELSEIF ListCursor < 1 THEN
          ListCursor = 1
     END IF

     CALL PointAt(ListCursor, ">")

     DO
          a$ = INKEY$
          IF a$ = CHR$(0) + CHR$(72) THEN
               CALL PointAt(ListCursor, " ")
               ListCursor = ListCursor - 1
               EXIT DO
          ELSEIF a$ = CHR$(0) + CHR$(80) THEN
               CALL PointAt(ListCursor, " ")
               ListCursor = ListCursor + 1
               EXIT DO
          ELSEIF a$ = CHR$(0) + CHR$(77) THEN
               CALL PointAt(ListCursor, " ")
               ListCursor = ListCursor + 20
               EXIT DO
          ELSEIF a$ = CHR$(0) + CHR$(75) THEN
               CALL PointAt(ListCursor, " ")
               ListCursor = ListCursor - 20
               EXIT DO
          ELSEIF a$ = " " THEN
               Tag(ListCursor) = NOT Tag(ListCursor)
               CALL PointAt(ListCursor, " ")
               ListCursor = ListCursor + 1
               EXIT DO
          ELSEIF (a$ = "m") AND (NoOfSongs > 0) THEN
               DO
                    CALL PointAt(ListCursor, "=")
                    DO
                         a$ = INKEY$
                         IF (a$ = CHR$(0) + CHR$(72)) AND (ListCursor > 1) THEN
                              temp$ = Song$(ListCursor)
                              tempt = Tag(ListCursor)
                              Song$(ListCursor) = Song$(ListCursor - 1)
                              Tag(ListCursor) = Tag(ListCursor - 1)
                              Song$(ListCursor - 1) = temp$
                              Tag(ListCursor - 1) = tempt
                              CALL PointAt(ListCursor, " ")
                              ListCursor = ListCursor - 1
                              EXIT DO
                         ELSEIF (a$ = CHR$(0) + CHR$(80)) AND (ListCursor < NoOfSongs) THEN
                              temp$ = Song$(ListCursor)
                              tempt = Tag(ListCursor)
                              Song$(ListCursor) = Song$(ListCursor + 1)
                              Tag(ListCursor) = Tag(ListCursor + 1)
                              Song$(ListCursor + 1) = temp$
                              Tag(ListCursor + 1) = tempt
                              CALL PointAt(ListCursor, " ")
                              ListCursor = ListCursor + 1
                              EXIT DO
                         ELSEIF (a$ = CHR$(0) + CHR$(77)) AND ((ListCursor + 20) <= NoOfSongs) THEN
                              temp$ = Song$(ListCursor)
                              tempt = Tag(ListCursor)
                              Song$(ListCursor) = Song$(ListCursor + 20)
                              Tag(ListCursor) = Tag(ListCursor + 20)
                              Song$(ListCursor + 20) = temp$
                              Tag(ListCursor + 20) = tempt
                              CALL PointAt(ListCursor, " ")
                              ListCursor = ListCursor + 20
                              EXIT DO
                         ELSEIF (a$ = CHR$(0) + CHR$(75)) AND ((ListCursor - 20) >= 1) THEN
                              temp$ = Song$(ListCursor)
                              tempt = Tag(ListCursor)
                              Song$(ListCursor) = Song$(ListCursor - 20)
                              Tag(ListCursor) = Tag(ListCursor - 20)
                              Song$(ListCursor - 20) = temp$
                              Tag(ListCursor - 20) = tempt
                              CALL PointAt(ListCursor, " ")
                              ListCursor = ListCursor - 20
                              EXIT DO
                         ELSEIF a$ = " " OR a$ = "m" OR a$ = CHR$(27) THEN
                              GOTO ExitDrag
                         END IF
                    LOOP
               LOOP
ExitDrag:
               EXIT DO
          ELSEIF a$ = "a" THEN
               SetTags (NOT 0)
               ListSongs
               EXIT DO
          ELSEIF (a$ = "s") AND (NoOfSongs) > 0 THEN
               SortSongs
               ListSongs
               EXIT DO
          ELSEIF (a$ = "S") AND (NoOfSongs > 0) THEN
               SortSongsRev
               ListSongs
               EXIT DO
          ELSEIF a$ = "t" THEN
               FOR i = 1 TO NoOfSongs
                    Tag(i) = NOT Tag(i)
               NEXT i
               ListSongs
               EXIT DO
          ELSEIF a$ = "p" THEN
               CLS
               INPUT "Enter PLAYMIDI parameters: ", Parameter$
               CLS
               InitScreen
               ListSongs
               EXIT DO
          ELSEIF a$ = "r" THEN
               RptFlag = NOT RptFlag
               InitScreen
               EXIT DO
          ELSEIF a$ = "d" THEN
               FirstTime = 0
               GOTO Start
          ELSEIF a$ = CHR$(27) THEN
               GOTO Done
          ELSEIF a$ = CHR$(13) THEN
               PlaySongs
               CLS
               InitScreen
               ListSongs
               EXIT DO
          END IF
     LOOP

LOOP

Done:
CLS
DisplayInfo
END

SUB DisplayInfo

     LOCATE 3, 1

     PRINT "  UltraSound MIDI JukeBox"
     PRINT "  ======================="
     PRINT
     PRINT "  This program is a simple jukebox MIDI file player that I"
     PRINT "  whipped up during a couple of free nights.  It's basically"
     PRINT "  a shell that calls up PLAYMIDI to actually play the songs."
     PRINT "  Due to PLAYMIDI's extravagant use of memory, some .mid files"
     PRINT "  may not play from the jukebox.  Play these files at the bare"
     PRINT "  DOS prompt instead."
     PRINT
     PRINT "  I release this program to the public domain, and shall not"
     PRINT "  be held responsible for any damages that may result from its"
     PRINT "  use or abuse."
     PRINT
     PRINT "  If anybody wants the source, just ask.  It's in QuickBASIC,"
     PRINT "  since I'm a biochem, not CS, major."
     PRINT
     PRINT "  Have fun!!!"
     PRINT "  Phat Tran (ptran@sciborg.uwaterloo.ca)"

END SUB

SUB GetDir

     NoOfSongs = 0
     SHELL "dir " + MIDDir$ + "\*.mid /b > midfiles.lst"
     OPEN "midfiles.lst" FOR INPUT AS #1
     FOR i = 1 TO MaxListSize
          IF EOF(1) THEN
               NoOfSongs = i - 1
               EXIT FOR
          ELSE
               INPUT #1, Song$(i)
          END IF
     NEXT i
     CLOSE 1
     SHELL "del midfiles.lst"

END SUB

SUB InitScreen
     
     LOCATE 1, 1
     PRINT "Directory: "; MIDDir$;
     KEY OFF
     LOCATE 24, 1
     PRINT "[P]-Set PLAYMIDI parameters [R]-Repeat (Currently ";
     IF RptFlag THEN
          PRINT "YES)";
     ELSE
          PRINT "NO )";
     END IF
     PRINT " [M]-Move [S]-Sort";
     LOCATE 25, 1
     PRINT "[SPACE]-Toggle [A]-Select all [T]-Toggle all [D]-Dir [Enter]-Play [Esc]-Quit";

END SUB

SUB ListSongs

     FOR column = 1 TO 5
          FOR row = 1 TO 20
               LOCATE row + 2, (column - 1) * 16 + 2
               PRINT "               ";
               LOCATE row + 2, (column - 1) * 16 + 2
               finger = ListPortal + (column - 1) * 20 + row - 1
               IF (finger <= NoOfSongs) AND (NoOfSongs > 0) THEN
                    IF Tag(finger) THEN
                         PRINT "*";
                    ELSE
                         PRINT " ";
                    END IF
                    PRINT Song$(finger);
               END IF
          NEXT row
     NEXT column

END SUB

SUB PlaySongs
    
     FOR i = 1 TO NoOfSongs
          IF Tag(i) THEN GOTO GoodSelection
     NEXT i
     EXIT SUB

GoodSelection:
     CLS
     PRINT "Now playing...  [Press a key twice, in rapid succession, to stop.]"
     PRINT
     DO
          FOR i = 1 TO NoOfSongs
               IF Tag(i) THEN
                    PRINT "Playing: "; Song$(i)
                    SHELL "playmidi " + Parameter$ + " " + MIDDir$ + "\" + Song$(i)
                    SLEEP 1
               END IF
               IF INKEY$ <> "" THEN EXIT SUB
          NEXT i

          IF NOT RptFlag THEN
               EXIT DO
          ELSE
               PRINT "Repeating entire selection..."
          END IF

     LOOP

END SUB

SUB PointAt (position, Symbol$)

     IF NoOfSongs = 0 THEN EXIT SUB

     DO

          PhysPos = position - ListPortal
          IF PhysPos < 0 THEN
               ListPortal = ListPortal - 20
               IF ListPortal < 1 THEN EXIT SUB
               ListSongs
          ELSEIF PhysPos > 99 THEN
               ListPortal = ListPortal + 20
               IF ListPortal > NoOfSongs THEN EXIT SUB
               ListSongs
          ELSE
               EXIT DO
          END IF
     
     LOOP

     IF PhysPos < 0 OR PhysPos > 99 THEN
          EXIT SUB
     ELSE
          column = INT(PhysPos / 20)
          row = PhysPos - column * 20
          LOCATE row + 3, column * 16 + 1
          PRINT "               ";
          LOCATE row + 3, column * 16 + 1
          PRINT Symbol$;
          IF Tag(ListCursor) THEN
               PRINT "*";
          ELSE
               PRINT " ";
          END IF
          PRINT Song$(position);
     END IF

END SUB

SUB SetTags (x)
     FOR i = 1 TO NoOfSongs
          Tag(i) = x
     NEXT i
END SUB

SUB SortSongs
     LOCATE 12, 30
     PRINT "                     "
     LOCATE 13, 30
     PRINT "     Sorting....     "
     LOCATE 14, 30
     PRINT "                     "
     FOR i = 1 TO NoOfSongs - 1
          xchange = i
          FOR j = 1 + i TO NoOfSongs
               IF Song$(j) < Song$(xchange) THEN xchange = j
          NEXT j
          IF i <> xchange THEN
               temp$ = Song$(i)
               tempt = Tag(i)
               Song$(i) = Song$(xchange)
               Tag(i) = Tag(xchange)
               Song$(xchange) = temp$
               Tag(xchange) = tempt
          END IF
     NEXT i
END SUB

SUB SortSongsRev
     LOCATE 12, 30
     PRINT "                     "
     LOCATE 13, 30
     PRINT "     Sorting....     "
     LOCATE 14, 30
     PRINT "                     "
     FOR i = 1 TO NoOfSongs - 1
          xchange = i
          FOR j = 1 + i TO NoOfSongs
               IF Song$(j) > Song$(xchange) THEN xchange = j
          NEXT j
          IF i <> xchange THEN
               temp$ = Song$(i)
               tempt = Tag(i)
               Song$(i) = Song$(xchange)
               Tag(i) = Tag(xchange)
               Song$(xchange) = temp$
               Tag(xchange) = tempt
          END IF
     NEXT i
END SUB

