Go Down

Topic: iTunes to Arduino (Read 2711 times) previous topic - next topic

wootwootman

I was wondering if someone could help me find a way to display the name of a song currently playing on itunes with a scrolling 24x6 led display.

im thinking of using the display from this instructable
http://www.instructables.com/id/Make-a-24X6-LED-matrix/

it is coded to accept serial text input and display it on the matrix.

my question is: how can i retrieve currently playing song's name and output it via serial to the arduino.

btw, i know oe or two people have asked this before, but they were on macs and used AppleScript, which i cannot use because im on a windows pc
     

PaulS

iTunes is an application, not a device. It can play files of various types. So can other applications, like Processing.

Processing can also write to the serial port. It could write something like the title of the song that it is playing. The Arduino can read the serial port. What a coincidence...

It could read the name of the song being played. With just a little effort, that title could be made to appear on the led display.

wootwootman

#2
Oct 16, 2010, 04:53 am Last Edit: Oct 16, 2010, 04:54 am by wootwootman Reason: 1
so i'd need a processing sketch then?

any tips on how i can get the name of the song playing in itunes to processing? i tried googling it, but process is too general of a name for a program.

PaulS

Processing.org is where to start. Like I said, processing can play songs. I don't know if there is any way to get data FROM iTunes.

wootwootman

#4
Oct 16, 2010, 05:57 am Last Edit: Oct 16, 2010, 08:34 am by wootwootman Reason: 1
i found an itunes plugin which can, among other things, write the songs info to a text file. now im trying to write a c program to read the file name and output it to serial character by character, because thats how the matrix's program works, i think.

its going to be a challenge though, because im a freshman ee major taking my first programming class

EDIT: im trying it in Processing now

EDIT 2: anyone have their own method for retrieving the song name from itunes or winamp?

EDIT 3: found a plugin for winamp that outputs song info into a file of your choice called "what's playing", now i just need to make the processing sketch to output the text in the file to serial

PaulS

There are examples included with processing for playing music, for writing serial data, and for reading from files. It should be simple to combine the relevant bits (if you can recognize what IS relevant) from each example to create your own sketch.

wootwootman

#6
Oct 16, 2010, 10:41 pm Last Edit: Oct 16, 2010, 10:47 pm by wootwootman Reason: 1
i can now successfully read the text file and show the current song in the terminal, but now im not sure about the serial i/o.

this is the only snippet of code from the matrix which deals with serial (other than Serial.begin(9600); )
Code: [Select]
void loop() {

   // send data only when you receive data:
   if(Serial.available() > 0){
       delay(100);
       incomingByte[array_turn] = Serial.read();
               array_turn++;
   }
          else{


im not sure if it asks for a "handshake" or if it just starts receiving the data immediately. the entire matrix code ca be found herehttp://www.instructables.com/files/orig/F2V/QNQF/GBVJBS35/F2VQNQFGBVJBS35.txt

this is what i have so far
Code: [Select]
import processing.serial.*;


Serial myPort;

void setup()
{
 String portName = Serial.list()[0];
 myPort = new Serial(this,portName,9600);
 
 String[] load = loadStrings("nowplaying.txt");
 print(load[0] + "\n");

 myPort.write(load[0] + "\n");
}


i have the "\n" to signify the carriage return, which i think is what the matrix code is watching for before it starts showing it on the matrix. if necessary i can remove the "\n" and change the print to println

when i try to run it, it  gives me the error "ArrayIndexOutOfBoundsException: 0"    but i think that's just because i don't have the arduino hooked up to it yet. in fact, i don't have my arduino with me at the moment, so it'll be about a week before i can actually test this

PaulS

Quote
im not sure if it asks for a "handshake

Handshaking involves one end of the serial port sending some throwaway data to the other, signaling that the sender is ready to receive data. The Arduino sketch that you linked to never writes anything to the serial port, so there is no handshaking going on.

If you comment out the 1st two lines and the last line in setup(), and the name of the song being played is printed, then when you are able to uncomment those lines, because you actually have an Arduino connected, the song title will be sent to the Arduino.

Notice though, that when that song ends, and another song begins, the title being displayed will not refresh.

This is because the setup() function in a Processing sketch is like the setup() function in an Arduino sketch, in that both only run once.

If you want something to happen more than once, in the Processing sketch, like detecting that the song that is being played has changed, you need to put that code in the draw() function.

It would be useful to keep track of what has been sent to the Arduino, so that you can send new data only when a change occurs, rather than every pass through the draw() method.

The println function actually sends two characters, in addition to the specified series of characters - a carriage return and a line feed. Not that it makes any difference, since the characters that the sketch doesn't recognize, like carriage return and line feed, are ignored. It appears that you don't need to use println or add the \n to the serial stream.

wootwootman

#8
Oct 17, 2010, 02:57 am Last Edit: Oct 17, 2010, 08:35 am by wootwootman Reason: 1
i knew i would have needed some sort of loop to figure out when the song changed, but when i tried void loop() it wouldnt work, so now i guess its void draw(). i can have two strings: essentially an "old" and "new" string, then when it detects a difference in the two, it outputs the new string to serial and replaces the "old" with the "new".

ill try that later tonight.

thanks so much for all your help by the way! :D

wootwootman

#9
Oct 17, 2010, 07:12 pm Last Edit: Oct 17, 2010, 07:15 pm by wootwootman Reason: 1
i tried using an "if" condition, but it seems to be ignoring it and loops everything in draw()

Code: [Select]

String original;
String current;
PFont font;

void setup() {
 font = loadFont("CourierNew36.vlw");
 size(400,400);
 String[] original = loadStrings("data\\original.txt");
}

void draw() {
 String[] current = loadStrings("nowplaying.txt");

 if (!current.equals(original)) {
   saveStrings("data\\original.txt",current);
   String[] original=loadStrings("data\\original.txt");
   print(original[0]);
   textFont(font);
   text(original[0],20,200);
 }
}


if i were to write "cake" into original.txt and "pie" into nowplaying.txt, the word pie is successfully copied over into original.txt, and it is successfully displayed in the pop-up window, but it is repeatedly printed to the terminal non-stop, which would eventually have it being sent to the arduino a couple of times a second, instead of ONLY when the song changes.

ive tested it with winamp, and it does seem to be responding to the song change, and it prints the text() command, but it writes it over the old song name, so it becomes unreadable, but thats not a problem, seeing as how i wont be reading it from there  

PaulS

Code: [Select]
String original;
String current;

These are scalar global variables.

Code: [Select]
 String[] original = loadStrings("data\\original.txt");

This is a local array variable.
Code: [Select]
 String[] current = loadStrings("nowplaying.txt");

This is a local array variable, too.

Code: [Select]
 if (!current.equals(original)) {

Since there are no array index operators ([]), the global scalar variables are being referenced. But, they have never been valued.

Code: [Select]
   saveStrings("data\\original.txt",current);
   String[] original=loadStrings("data\\original.txt");

Why not just copy the value of current into original? Why declare another local array variable that immediately goes out of scope?

wootwootman

i tried something lie that earlier and i couldnt get it to copy, thats why i had two use two files

PaulS

Quote
i tried something lie that earlier and i couldnt get it to copy, thats why i had two use two files

Show the code you used to copy one string to another. Using the string class, it's really pretty simple:

Code: [Select]
original = current;

wootwootman

i did what i think you  suggested
Code: [Select]
String original;
String current;
PFont font;


void setup() {
 font = loadFont("CourierNew36.vlw");

 size(400,400);
 String[] original = loadStrings("nowplaying.txt");


}
void draw() {
 String[] current = loadStrings("nowplaying.txt");

 if (!current[0].equals(original[0])) {
   original = current;
   print(original[0]);
   textFont(font);
   text(original[0],20,200);
 }
}


but now i get the error on the "if" line :  The type of the expression must be an array type but it resolved to String

PaulS

Go back and look at my earlier responses. You have a local array named original and a global variable named original. These do not refer to the same block of memory.

You should change the name of one of the variables. For instance, change the global variables to originalFile and currentFile.

Then, in setup, after populating original, add this line:
Code: [Select]
originalFile = original[0];

Next, in loop, after populating the current array, add:
Code: [Select]
currentFile = current[0];

Then, the if test should refer to originalFile and currentFile (which are not arrays).

Go Up