Okay so I have been getting lots of E-mails from people wanting to know how Music Logger Plus work and with feature requests / bug reports etc. I'm sorry I can't fix the bugs as fast as I would like but my new job takes up all my time at the moment.
For the people that wanted to know how to get the Contact Song Information, all you have to do is packet sniff for any "UBX" packets and then you can process the data payload of the UBX packet to extract PSM and Current Media information.
For the people that wanted to know how to process the data payload of a UBX command, well I'm feeling generous. Here is my UBX class, you create a new instance of it, supply it with the data payload (I.e. everything within <DATA> and </DATA>) and it does the rest for you:
code:
/*
* UBX.cs - Coded by Mark Rylander - 2005
* Takes Raw UBX packet and processes it to find out contact PSM information
* specifically the current media (CM) they are playing.
* http://www.jedimark.co.uk/
*
* Written for use with "Music Logger Plus!"
* http://mlp.jedimark.co.uk/
*
* VERSION 2.0
* Updated on 04th August 2005
* */
using System;
namespace MLP
{
public class UBX
{
private static string information;
private int startOfPSM;
private int endOfPSM;
private int startOfCM;
private int endOfCM;
private bool songChange = false;
public string type;
public string contact;
public int code;
public string PSM;
public string CM;
public string song;
public string artist;
public bool aOK;
public UBX()
{
type = "";
contact = "";
code = 0;
PSM = "";
CM = "";
song = "";
artist = "";
aOK = false;
}
/// <summary>
/// Processes a UBX packet to get and set the various variables
/// (I.e. PSM / Current Media)
/// </summary>
/// <param name="payload">The Raw UBX Packet</param>
public UBX(string payload)
{
try
{
Console.WriteLine("We are in the UBX method now: " + payload);
Array header = getHeader(payload);
information = getInformation(payload);
type = header.GetValue(0).ToString();
contact = header.GetValue(1).ToString();
code = Convert.ToInt32(header.GetValue(2).ToString());
PSM = processPSM(information);
CM = getFullCM(information);
Console.WriteLine("The CM is: " + CM);
if (!CM.Equals(""))
{
songChange = true;
if (processCM(CM))
{
aOK = true;
}
else
{
aOK = false;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
/// <summary>
/// Get Method for aOK Variable
/// </summary>
/// <returns></returns>
public bool isAOK()
{
return aOK;
}
/// <summary>
/// Get Method for Artist Variable
/// </summary>
/// <returns></returns>
public string getArtist()
{
return artist;
}
/// <summary>
/// Get Method for songChange Variable
/// </summary>
/// <returns></returns>
public bool getSongChange()
{
return songChange;
}
/// <summary>
/// Get Method for type Variable
/// </summary>
/// <returns></returns>
public string getType()
{
return type;
}
/// <summary>
/// Get Method for contact Variable
/// </summary>
/// <returns></returns>
public string getContact()
{
return contact;
}
/// <summary>
/// Get Method for code Variable
/// </summary>
/// <returns></returns>
public int getCode()
{
return code;
}
/// <summary>
/// Get Method for PSM Variable
/// </summary>
/// <returns></returns>
public string getPSM()
{
return PSM;
}
/// <summary>
/// Get Method for CM Variable
/// </summary>
/// <returns></returns>
public string getCM()
{
return CM;
}
/// <summary>
/// Get Method for song Variable
/// </summary>
/// <returns></returns>
public string getSong()
{
return song;
}
/// <summary>
/// Strips the header of a UBX packet
/// </summary>
/// <param name="data">The raw UBX packet</param>
/// <returns>The data section of the UBX packet</returns>
private string getInformation(string data)
{
Console.WriteLine("I am in the getInformation method");
char[] myArray = data.ToCharArray();
for (int i=0; i<myArray.Length; i++)
{
if (myArray[i] == '<')
{
char[] myNewArray = new char [myArray.Length - i];
for (int j=0; j<(myArray.Length - i); j++)
{
myNewArray[j] = myArray[j + i];
}
return new String(myNewArray);
}
}
return null;
}
/// <summary>
/// Strips the data of a UBX packet
/// </summary>
/// <param name="data">The raw UBX packet</param>
/// <returns>The header section of a UBX packet</returns>
private Array getHeader(string data)
{
Console.WriteLine("I am in the getHeader method");
char[] myArray = data.ToCharArray();
for (int i=0; i<myArray.Length; i++)
{
if (myArray[i] == '<')
{
char[] myNewArray = new char [i-2];
for (int j=0; j<(i-2); j++)
{
myNewArray[j] = myArray[j];
}
Array a = processHeader(new String(myNewArray));
return a;
}
}
return null;
}
/// <summary>
/// Splits a given string based on supplied separator
/// </summary>
/// <param name="stringToSplit">The string to the split</param>
/// <param name="sep">Array of characters to base split on</param>
/// <returns>The first split</returns>
private Array SplitString(string stringToSplit, char[] sep)
{
Console.WriteLine("I am in the SplitString method");
return stringToSplit.Split(sep);
}
/// <summary>
/// Places the UBX header into an array
/// </summary>
/// <param name="header">The full header</param>
/// <returns>An array containing the header</returns>
private Array processHeader(string header)
{
Console.WriteLine("I am in the processHeader method");
char[] sep = {' '};
return SplitString(header, sep);
}
/// <summary>
/// Processes an array to find data within given start / end
/// </summary>
/// <param name="start">Start pos in array</param>
/// <param name="end">End pos in array</param>
/// <param name="array">The data array</param>
/// <returns></returns>
static string getString(int start, int end, char[] array)
{
Console.WriteLine("I am in the getString method");
Console.WriteLine("I have: " + start + " " + end);
try
{
if (end-start < 0)
{
return "";
}
else
{
char[] buffer = new char[end-start];
for (int i=0; i< (end-start); i++)
{
buffer[i] = array[start+i];
}
return new string(buffer);
}
}
catch(Exception ex)
{
Console.WriteLine(ex.StackTrace);
return null;
}
}
/// <summary>
/// Method to place the CurrentMedia message into a string
/// </summary>
/// <param name="info">The full message</param>
/// <returns>The CurrentMedia message</returns>
private string getFullCM(string info)
{
Console.WriteLine("I am in the getFullCM method");
char[] myArray = info.ToCharArray();
for (int i=0; i< myArray.Length; i++)
{
if ((myArray[i] == '<') &
(myArray[i+1] == 'C') &
(myArray[i+2] == 'u') &
(myArray[i+3] == 'r') &
(myArray[i+4] == 'r') &
(myArray[i+5] == 'e') &
(myArray[i+6] == 'n') &
(myArray[i+7] == 't') &
(myArray[i+8] == 'M') &
(myArray[i+9] == 'e') &
(myArray[i+10] == 'd') &
(myArray[i+11] == 'i') &
(myArray[i+12] == 'a') &
(myArray[i+13] == '>'))
{
startOfCM = i+14;
for (int j=(i+14); j< myArray.Length; j++)
{
if ((myArray[j] == '<') &
(myArray[j+1] == '/') &
(myArray[j+2] == 'C') &
(myArray[j+3] == 'u') &
(myArray[j+4] == 'r') &
(myArray[j+5] == 'r') &
(myArray[j+6] == 'e') &
(myArray[j+7] == 'n') &
(myArray[j+8] == 't') &
(myArray[j+9] == 'M') &
(myArray[j+10] == 'e') &
(myArray[j+11] == 'd') &
(myArray[j+12] == 'i') &
(myArray[j+13] == 'a') &
(myArray[j+14] == '>'))
{
endOfCM = j-1;
break;
}
}
break;
}
}
return getString(startOfCM, endOfCM, myArray);
}
/// <summary>
/// Method to place the PSM into a string
/// </summary>
/// <param name="info">The full message</param>
/// <returns>The PSM</returns>
private string processPSM(string info)
{
Console.WriteLine("I am in the processPSM method");
char[] myArray = info.ToCharArray();
for (int i=0; i< myArray.Length; i++)
{
if ((myArray[i] == '<') &
(myArray[i+1] == 'P') &
(myArray[i+2] == 'S') &
(myArray[i+3] == 'M') &
(myArray[i+4] == '>'))
{
startOfPSM = i+5;
for (int j=(i+5); j< myArray.Length; j++)
{
if ((myArray[j] == '<') &
(myArray[j+1] == '/') &
(myArray[j+2] == 'P') &
(myArray[j+3] == 'S') &
(myArray[j+4] == 'M') &
(myArray[j+5] == '>'))
{
endOfPSM = j-1;
break;
}
}
break;
}
}
return getString(startOfPSM, endOfPSM, myArray);
}
/// <summary>
/// Takes the CM Message and finds out the specific parameters of it
/// </summary>
/// <param name="CM">The CM Message</param>
/// <returns>Boolean reporting either success of failure of method</returns>
private bool processCM(string CM)
{
try
{
CM = CM.Replace("'", "'");
CM = CM.Replace("&", "&");
char[] myArray = CM.ToCharArray();
int player = 0;
int start;
int end;
//First find out if we are dealing with ITunes or WMP
player = setPlayerType(myArray);
if (player == 0)
{
start = 29;
}
else
{
start = 23;
}
end = findEnd(start, myArray);
song = getData(start, end, myArray);
start = end + 2;
end = findEnd(start, myArray);
artist = getData(start, end, myArray);
return true;
}
catch(Exception ex)
{
Console.WriteLine(ex.Message + ex.StackTrace);
return false;
}
}
/// <summary>
/// Determines what Media Player a contact is using
/// </summary>
/// <param name="myArray">UBX Data Array</param>
/// <returns>Integer representing player type (0 = ITunes, 1 = WMP)</returns>
private int setPlayerType(char[] myArray)
{
if ((myArray[0] == 'I') &
(myArray[1] == 'T') &
(myArray[2] == 'u') &
(myArray[3] == 'n') &
(myArray[4] == 'e') &
(myArray[5] == 's'))
{
return 0;
}
else
{
return 1;
}
}
/// <summary>
/// Finds the end of the next piece of data
/// </summary>
/// <param name="start">The position in the array to start from</param>
/// <param name="array">UBX data array</param>
/// <returns>Integer representing where the end of the next piece of data is</returns>
private int findEnd(int start, char[] array)
{
for (int i=start; i<array.Length; i++)
{
if ((array[i] == '\\') &
(array[i+1] == '0'))
{
return i;
}
}
return 0;
}
/// <summary>
/// Finds out specific data from UBX packet
/// </summary>
/// <param name="start">Position in array of where the data starts</param>
/// <param name="end">Position in array of where the data ends</param>
/// <param name="array">UBX data array</param>
private string getData(int start, int end, char[] array)
{
try
{
char[] buffer = new char[end-start];
for (int i=0; i< (end-start); i++)
{
buffer[i] = array[start+i];
}
return new string(buffer);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message + ex.StackTrace);
return "<NO DATA>";
}
}
}
}