!7 static int songDuration, seekValue; static long songBytes; static int position; static File mp3; static BasicPlayer player; static Int seekTo; static volatile byte[] lastPCMData; static JFrame frame; static new JSlider seeker; static new JLabel text; static JTable table; static JTable lastPlayed; static JButton btnPause; p { print("hello"); swing { substanceLAF("Moderate"); // Fixing the classpath for Java Sound (MP3 + OGG) fixContextClassLoader(); table = tableWithToolTips(); lastPlayed = tableWithToolTips(); } updateLastPlayed(); searchLibrary(); swing { onDoubleClickOrEnter(table, voidfunc(int row) { play(fileFromTable(table, row)); }); onDoubleClickOrEnter(lastPlayed, voidfunc(int row) { play(fileFromTable(lastPlayed, row)); }); // init seeker seeker.setMajorTickSpacing(10000); // 10 seconds seeker.setMinorTickSpacing(10000); // 10 seconds seeker.setPaintTicks(true); seeker.setMaximum(1); seeker.setValue(0); seeker.setEnabled(false); seeker.addChangeListener(new ChangeListener { public void stateChanged(ChangeEvent e) { bool adjusting = seeker.getValueIsAdjusting(); if (adjusting) seekTo = seeker.getValue(); else if (seekTo != null) { seek(seekTo); seekTo = null; } } }); frame = showFrame( centerAndNorth(jtabs( "Library", tableWithSearcher(table), "Last played", tableWithSearcher(lastPlayed)), centerAndSouth( centerAndEast(seeker, text), hgrid( jbutton("play again", "playAgain"), btnPause = jbutton("pause", "pause"), jbutton("upload", "upload"), jbutton("assistance", "assistance")) ))); frame.pack(); setFrameIconLater(frame, "#1003635"); setFrameWidth(frame, 500); exitOnFrameClose(frame); // To immediately stop playback titlePopupMenu(frame, voidfunc(JPopupMenu menu) { menu.add(jmenuItem("Rescan Library", r { searchLibrary() })); }); hideConsole(); player = makeBasicMP3Player(); player.addBasicPlayerListener(new BasicPlayerListener { public void opened(Object stream, Map properties) { for (Object key : properties.keySet()) print("opened: " + key + "=" + properties.get(key)); // Try to find duration of song final Number bytes = (Number) properties.get("audio.length.bytes"); long microseconds = 0; O duration = properties.get("duration"); if (duration instanceof Number) microseconds = ((Number) duration).longValue(); else pcall { long frames = asLong(properties.get("audio.length.frames")); long fps = asLong(properties.get("audio.framerate.fps")); microseconds = frames*1000000/fps; } final long _microseconds = microseconds; awt { songDuration = (int) (_microseconds / 1000); seeker.setMaximum(songDuration); seeker.setEnabled(true); seeker.setMajorTickSpacing(10000); // 10 seconds updateText(); songBytes = bytes.longValue(); } } public void progress(int bytesread, final long microseconds, byte[] pcmdata, Map properties) { lastPCMData = pcmdata; awt { if (!seeker.getValueIsAdjusting()) { int ms = (int) (microseconds / 1000) + seekValue; seeker.setValue(ms); position = ms; updateText(); } } } public void stateUpdated(BasicPlayerEvent event) { awt { updateStateStuff(); } } public void setController(BasicController controller) {} }); makeBot("Music Player."); } } svoid searchLibrary { thread "Searching Music..." { dataToTable_uneditable(table, musicFilesTable(findMusicFiles())); } } svoid play(File f) { if (f == null) ret; mp3 = f; setFrameTitle(frame, f.getName() + " - " + getProgramTitle()); logStructure(getProgramFile("#1003634", "player.log"), litlist(now(), "Playing", f.getAbsolutePath())); play(); updateLastPlayed(); } svoid playAgain() ctex { if (isPaused()) player.resume(); else { logStructure(getProgramFile("#1003634", "player.log"), litlist(now(), "Playing again")); play(); } } svoid play() ctex { seekValue = 0; player.open(mp3); player.play(); } sbool isPlaying() { ret player.getStatus() == player.PLAYING; } sbool isPaused() { ret player.getStatus() == player.PAUSED; } svoid pause() ctex { if (isPaused()) player.resume(); else player.pause(); } svoid updateStateStuff { btnPause.setText(isPaused() ? "resume" : "pause"); } svoid updateText { text.setText(formatMinuteAndSeconds(position/1000) + " / " + formatMinuteAndSeconds(songDuration/1000)); } svoid seek(int milliseconds) { if (mp3 == null) ret; long bytes = (long) (milliseconds*((double) songBytes)/songDuration); print("ms=" + milliseconds + ", songBytes=" + songBytes + ", duration=" + songDuration + ", bytes=" + bytes); pcall { seekValue = milliseconds; player.open(mp3); player.seek(bytes); player.play(); } } static L findLastPlayed() { new L l; new Set seen; for (S s : reversedList(scanLog("#1003634", "player.log"))) pcall { L line = unstructureList(s); if (eq(get(line, 1), "Playing")) { S file = getString(line, 2); if (seen.add(file)) l.add(new File(file)); } } ret l; } static void updateLastPlayed() { dataToTable_uneditable(lastPlayed, musicFilesTable(findLastPlayed())); } static File fileFromTable(JTable table, int row) { SS map = getTableLineAsMap(table, row); File f = new File(map.get("Location"), map.get("Name")); if (!f.exists()) print("Oops, file not found: " + f.getAbsolutePath()); ret f; } static void upload() { thread "Uploading" { loading { uploadFileToPhoneServer(mp3); } } } answer { if "play again" { if (mp3 == null) ret "No song"; swingLater(r { playAgain(); }); ret "OK"; } if "are you playing" ret yn(isPlaying()); if "are you paused" ret yn(isPaused()); if "play file *" { awt { play(new File(m.unq(0))); } ret "OK"; } if "get file" ret structure(mp3); if "pcm data" ret structure(lastPCMData); if "pcm data * " ret lastPCMData == null ? "null" : structure(subArray(lastPCMData, 0, min(lastPCMData.length, m.psi(0)))); } svoid assistance { assist(); }