Jump to content

Pandora Timeshifting App: Main Discussion Thread


Recommended Posts

  • Replies 1.4k
  • Created
  • Last Reply

Top Posters In This Topic

the old code was

for (File file : files) {

if (file.getName().indexOf("access") != -1) {

if (!foundBuffer) {

tmpMp3File1 = file;

foundBuffer = true;

} else {

tmpMp3File2 = file;

break;

}

}

}

the new code would be

for (File file : files) {

try{

Long.parseLong(file.getName());

if (!foundBuffer) {

tmpMp3File1 = file;

foundBuffer = true;

} else {

tmpMp3File2 = file;

break;

}

}catch(NumberFormatException e){

LOG.debug(file.getName()+" is not a long");

}

}

Link to post
Share on other sites

I interpreted your change as this:

Change this:

----------------------------------

if (file.getName().indexOf("access") != -1) {

if (!foundBuffer) {

tmpMp3File1 = file;

foundBuffer = true;

} else {

tmpMp3File2 = file;

break;

}

}

-------------------------------------

to this:

------------------------------------

try{

Long.parseLong(file.getName());

if (!foundBuffer) {

tmpMp3File1 = file;

foundBuffer = true;

} else {

tmpMp3File2 = file;

break;

}

}catch(NumberFormatException e){}

--------------------------------------

I assume this is incorrect since it also didn't work for me.

Link to post
Share on other sites

I trayed your "Fix" but im still geating

INFO [Thread-2] (Mp3Processor.java:39) - access file not found trying again after 1 sec

you are eating the ..PandorassrcutilMp3Processor.java

right?

maby you could post your Mp3Processor.java file?

Link to post
Share on other sites

ok, here goes the whole class

(you know you have to recompile the project and create a new jar, don't you?)

--------------------------------------------------

package util;

import org.blinkenlights.jid3.ID3Exception;

import org.blinkenlights.jid3.MediaFile;

import org.blinkenlights.jid3.MP3File;

import org.blinkenlights.jid3.v2.ID3V2_3_0Tag;

import org.blinkenlights.jid3.v2.APICID3V2Frame;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import java.io.*;

import java.util.Arrays;

import java.util.Comparator;

import enums.FileType;

public class Mp3Processor {

private static String ERR_TMP_NOT_FOUND = "unable to find file make sure you have Pandora running in a FIRFOX browser";

private static Log LOG = LogFactory.getLog(Mp3Processor.class);

public static File findCurrentMP3() throws IOException {

LOG.info("locating mp3");

File pandoraTempDir = findUserTmpDir();

File tmpMp3File = findCurrentTmpMp3(pandoraTempDir);

return copyFile(tmpMp3File, new File(tmpMp3File.getParent(), "temp"));

}

public static File findCurrentTmpMp3(File pandoraTempDir) {

File tmpMp3File2 = null;

try {

tmpMp3File2 = getAccessFile(pandoraTempDir);

if (tmpMp3File2 == null) {

throw new RuntimeException("access file could not be located");

}

} catch (Exception e) {

if (e.getMessage().equals(ERR_TMP_NOT_FOUND)) {

LOG.info("access file not found trying again after 1 sec");

try {

Thread.sleep(2000);

} catch (InterruptedException e1) {

throw new RuntimeException(e1);

}

return findCurrentTmpMp3(pandoraTempDir);

}

}

try {

LOG.debug("sleeping for a couple of seconds");

Thread.sleep(2000);

} catch (InterruptedException e) {

return tmpMp3File2;

}

File currentTmpMp3 = getAccessFile(pandoraTempDir);

LOG.info(currentTmpMp3.getName() + "|" + tmpMp3File2.getName());

if (currentTmpMp3.getName().equals(tmpMp3File2.getName())) {

return tmpMp3File2;

}

LOG.info("Difference found in temp file names looping again");

return findCurrentTmpMp3(pandoraTempDir);

}

private static File getAccessFile(File pandoraTempDir) {

File [] files = pandoraTempDir.listFiles();

sortFilesByMostRecent(files);

boolean foundBuffer = false;

File tmpMp3File1 = null;

File tmpMp3File2 = null;

for (File file : files) {

try{

Long.parseLong(file.getName());

// if (file.getName().indexOf("access") != -1) {

if (!foundBuffer) {

tmpMp3File1 = file;

foundBuffer = true;

} else {

tmpMp3File2 = file;

break;

}

}catch(NumberFormatException e){

LOG.debug(file.getName()+" is not a long");

}

}

if (tmpMp3File2 == null) {

throw new RuntimeException(ERR_TMP_NOT_FOUND);

}

long tmp1Size = tmpMp3File1.length();

long tmp2Size = tmpMp3File2.length();

int loopCount = 0;

while (true) {

try {

LOG.debug("comparing file after 1 sec: tmp2Size: " + tmp2Size);

Thread.sleep(1000);

if ((tmp1Size == tmpMp3File1.length() && tmp2Size == tmpMp3File2.length() && (tmp2Size > (1024 * 1000)))) {

break;

} else {

String absolutePath = tmpMp3File2.getAbsolutePath();

LOG.debug("absolutePath> " + absolutePath);

tmpMp3File2 = new File(absolutePath);

LOG.debug("buffer still building, looping");

tmp1Size = tmpMp3File1.length();

tmp2Size = tmpMp3File2.length();

}

} catch (InterruptedException e) {

break;

}

if (loopCount > 40) {

break;

}

loopCount ++;

}

return tmpMp3File2;

}

public static File findUserTmpDir() {

File tmpDir = new File(System.getenv("TEMP"));

File[] tempFiles = tmpDir.listFiles();

sortFilesByMostRecent(tempFiles);

File pandoraTempDirv = null;

for (File file : tempFiles) {

if (file.getName().indexOf("plugtmp") != -1) {

pandoraTempDirv = file;

break;

}

}

if (pandoraTempDirv == null) {

throw new RuntimeException(ERR_TMP_NOT_FOUND);

}

return pandoraTempDirv;

}

public static void sortFilesByMostRecent(File[] files) {

Arrays.sort(files, new Comparator() {

public int compare(Object o1, Object o2) {

if (((File) o1).lastModified() > ((File) o2).lastModified()) {

return -1;

} else if (((File) o1).lastModified() < ((File) o2).lastModified()) {

return +1;

} else {

return 0;

}

}

});

}

public static File copyFile(File src, File dst) throws IOException {

LOG.info("copying file[" + src.getAbsolutePath() + "] to temp[" + dst.getAbsolutePath() + "]");

InputStream in = new FileInputStream(src);

OutputStream out = new FileOutputStream(dst);

byte[] buf = new byte[1024];

int len;

while ((len = in.read(buf)) > 0) {

out.write(buf, 0, len);

}

in.close();

out.close();

return dst;

}

public static void addID3Tags(File currentMP3, File coverArt, String comment, SongInfo songInfo) throws ID3Exception, IOException {

LOG.info("adding ID3 tags: " + songInfo.toString());

MediaFile oMediaFile = new MP3File(currentMP3);

ID3V2_3_0Tag oID3V2_3_0Tag = new ID3V2_3_0Tag();

if (coverArt != null) {

LOG.info("setting ID3 cover art");

byte[] buffer = new byte[32 * 1024];

BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(coverArt));

ByteArrayOutputStream imageBinary = new ByteArrayOutputStream();

while (bufferedInputStream.read(buffer) != -1) {

imageBinary.write(buffer);

}

APICID3V2Frame apicid3V2Frame = new APICID3V2Frame("image/jpg", APICID3V2Frame.PictureType.Artist, songInfo.getAlbum() != null ? songInfo.getAlbum() : "unknown", imageBinary.toByteArray());

oID3V2_3_0Tag.addAPICFrame(apicid3V2Frame);

}

if (songInfo.getAlbum() != null) {

oID3V2_3_0Tag.setAlbum(songInfo.getAlbum());

}

if (songInfo.getArtist() != null) {

oID3V2_3_0Tag.setArtist(songInfo.getArtist());

}

if (comment != null) {

if (songInfo.getStationName() != null) {

oID3V2_3_0Tag.setComment(songInfo.getStationName());

} else {

oID3V2_3_0Tag.setComment(comment);

}

}

if (songInfo.getTrackNumber() != null) {

Integer i = new Integer(songInfo.getTrackNumber());

oID3V2_3_0Tag.setTrackNumber(i);

}

if (songInfo.getGenre() != null) {

oID3V2_3_0Tag.setGenre(songInfo.getGenre());

}

if (songInfo.getTitle() != null) {

oID3V2_3_0Tag.setTitle(songInfo.getTitle());

}

if (songInfo.getYear() != null) {

try {

Integer y = new Integer(songInfo.getYear());

oID3V2_3_0Tag.setYear(y);

} catch (NumberFormatException e) {

//ignore

}

}

oMediaFile.setID3Tag(oID3V2_3_0Tag);

oMediaFile.sync();

}

public static void saveMP3(SongInfo songInfo, File fileToSave, FileType fileType, DataOutputStream output) throws IOException {

File file = new File(Util.createSongHierarchy(songInfo), SafeString.getSafeFileName(songInfo.getArtist().trim() + "-" + songInfo.getTitle().trim()) + "." + fileType.toString().toLowerCase());

Mp3Processor.copyFile(fileToSave, file);

String mp3Path = file.getAbsolutePath();

LOG.info("nripped file to: " + mp3Path + "nyea baby!!!n");

if (fileType == FileType.MP3) {

output.writeBytes("<span style="font: 12px arial">MP3 tagged and saved:</span><br/><span style="font: 12px arial">" + mp3Path + "</span>");

}

}

}

------------------------------------------------------------------

Link to post
Share on other sites

http://comicnut.speedxs.nl/pandoras-jar-beta.4.zip

Mirror of the above file, however as a zip.

Difference between the previous pandoras-jar-beta.3.b.zip file are:

- Logging went from info to debug (i.e. you'll get more of it)

- The FileType class got an extra import for all util classes (prolly doesn't need it, but harmless)

- Mp3Processor updated to no longer test for an 'access' file, but instead a file with a numeric filename.

And obviously the .jar file changed. Too lazy to verify that that doesn't contain any nastiness. If you're high on paranoia (which would be a good thing) just recompile from source.

I'm really thinking about doing some cleanup of these sources. It looks like this one's gonna be around for a while, and hence is entitled to some in-code documentation at the very least...

Link to post
Share on other sites

I just had a quick look through the code for the LastFmLookup class. I'll do a full review probably around the weekend, but right now there were a few things in this particular class that caught my eye and might be worth fixing for a next release:

- util.LastFmLookup.getStationName() is a Pandora service rather than a LastFmService. Also, I don't get the impression that the page it queries for its information changes very often, so it might be worth while to cache the stations in an ArrayList and only refetch the list when the station can't be found in there.

- util.LastFmLookup.md5() runs the bytes in the string trough the MD5 algorithm, however it first changes them to the CP1252 character set which is a Windows-specific character set, and not one Java is guaranteed to be aware of. The ISO-8859-1 characterset on the other hand IS guaranteed to be known to Java (see javadoc for java.nio.charset.Charset) and to the best of my knowledge is, like CP1252, an 8-bit character set which appears to have been the goal you were after.

- You have a util.Constants file. It should be an abstract class, but let's not get too anal about that. Since you have a place to define constants, why are there still hardcoded URLs in the source? Matter of fact, those URLs should come from a configuration/properties file. Date formats should however definately be in the Constants class.

- util.LastFmLookup.addTrack() first of all doesn't do any looking up at LastFm, so maybe this class needs a different name. The addTrack method authenticates with LastFm every single time which is a bit wasteful. You get a session key, which you're allowed to reuse. Part of the response you get when logging on is an INTERVAL number which is the amount of seconds that the key is valid (or at least that's what it appears to be in the Audioscrobbler source). Store the key and the time it's no-longer valid and only re-authenticate when you need to. Better yet, put the authentication in its own method that returns the session key. Shortens this big addTrack method which currently does more than just adding a track.

I'll check out the other files later.

Link to post
Share on other sites

the access error went away fro me when i downloaded the new .4 beta.

Now something really strange has been happening. The entire page will refresh. sometimes it is after about 10 seongs other times it is after a few hours of listening. Design?

Link to post
Share on other sites

I did a recursive diff over the two versions and listed the differences it found. Nothing in there that would explain this so either it's been doing that in 3b aswell, or something funky is going on.

BTW, I'm contemplating splitting the archive up into 3 parts:

The website part, the jar file for the server and the sources for the jar file.

Whenever a new version comes out most people just need to replace the jar file which is a 92 KB file as opposed to a 3+ MB file that contains everything.

Link to post
Share on other sites

pandora.js file in the js folder has the settings.

One of the settings is:

var SONG_COUNT_BEFORE_RELOAD = 30;

Pandora after sometime will require user intervention and will not function. This setting ensures that Pandora is reloaded before it requires user intervention. So if you want to rip music all night long (cruise control is on) then this will do it for you. If you're going to sit in front of the computer and rip songs manually (cruise control is off) then you can increase the counter for reload. When pandora stops playing songs because it requires user intevention, you can simply reload the page at that time.

Link to post
Share on other sites

:idea: New version available for download: pandoras-jar-beta.5.zip

Changes:

* All settings such as pandora username, last.fm username/password, and other options can be saved

* Settings are saved to a cookie which expires after 60 days

Now if the page reloads all your settings will be restored and you don't need to retype any info.

Helpful Info:

* To start the app with command window open: java -jar pandora.jar port#

* To start the app without command window open: javaw -jar pandora.jar port#

** You will notice I created a shortcut (Pandorab5) for the second option. Every user would have to modify the path for the shortcut if they want to use it. This is only an example.

Enjoy.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    No registered users viewing this page.


×
×
  • Create New...