Shairport Log Parser

Shairport ist ein kleines Windows-Programm, das eine virtuelle Apple Airplay Station erzeugt. Man kann sich aus iTunes bzw. mit IOS-Geräten dazu verbinden und hat dann einen verlustlosen (je nach Codec des abgespielten Materials) Stream zu der Windows-Kiste.

Eine Anleitung für Shairport gibt es hier: Airplay am PC > Shairport

Erwähnenswert in diesem Zusammenhang ist auch ein Progrämmchen namens Airfoil, welches unter OSX ermöglicht, jegliche Audioausgabe des Systems auf eine Airplay-Station zu streamen (für Videostreaming steht ein spezieller Player zur Verfügung der die Audio-Latenz berücksichtigt und durch ein Videodelay etwaige Verschiebungen kompensiert).

Ich habe ein kleines Skript zusammengehackt (es darf natürlich gerne verbessert werden), das die Logdatei von Shairport (so man sie aktiviert hat) parsen und einige Daten auslesen kann:

[ul]
[li]den Verbindungsstatus (true/false)
[/li][li]die Client-IP
[/li][li]den Client-Namen
[/li][li]den Client-Typen (iTunes/Airfoil/IOS Device)
[/li][/ul]

Das ganze ist ein bisschen zusammengeschustert, aber benutzbar wenn es darum geht festzustellen ob eine Verbindung besteht, und z.B. den Clientnamen und -typ irgendwo anzuzeigen. Leider scheinen bei bestimmten Client-Typen manche Informationen nicht zur Verfügung zu stehen, das bedeutet dass unter Umständen z.B. mal nur der Typ als Name angezeigt wird und nicht der Hostname. Jeder ist herzlich eingeladen, das Skript zu verbessern :wink:

Ich erstelle vor dem Auslesen der Logdatei einen „Snapshot“ indem ich die Logdatei umbenenne. Anschließend wird sie gelöscht, damit sie nicht die Platte vollmüllt.

Zur Integration muss lediglich ein Skript angelegt werden, der unten gezeigte Code hineinkopiert werden und die IDs der Variablen, sowie der Pfad zum Logfile angepasst werden.

Am besten stellt man ein Intervall ein, z.B. 5 Sekunden, damit die Variablenstati hinreichend aktuell sind.


<%
// hier den Pfad des Logfiles eintragen
$logFile = 'C:\Program Files\Shairport4w.log';

// binäre Variable die anzeigen soll, ob ein Client verbunden ist
$clientConnectionId = 14010  /*[Skripte\Shairport Überwachung\Shairport auslesen\Connection]*/;

// String der (falls ermittelbar) den Namen des Client-Hosts anzeigt
$clientNameId = 51180  /*[Skripte\Shairport Überwachung\Shairport auslesen\Client Name]*/;

// String der anzeigt, welche Art von Client verbunden ist (z.B. iTunes, Airfoil etc.)
$clientTypeId = 35466  /*[Skripte\Shairport Überwachung\Client Type]*/;

// String der die Client-IP enthält (falls ermittelbar)
$clientIPId = 33572  /*[Skripte\Shairport Überwachung\Client IP]*/;


// ---

if(file_exists($logFile))
{
	$snapshotFile = $logFile . '.snapshot';
	if(file_exists($snapshotFile)) @unlink($snapshotFile);

	if(@rename($logFile, $snapshotFile))
	{
		$hdl = @fopen($snapshotFile, 'r');

		if($hdl)
		{
			while(!feof($hdl))
			{
				$thisLine = trim(fgets($hdl));

				if(strpos($thisLine, 'Accepted new client') != FALSE)
				{
				   $thisLine = substr($thisLine, 0,
											strpos($thisLine, 'Accepted new client') +
											19) .
									': ' .
									substr($thisLine,
									      strpos($thisLine, 'Accepted new client') +
									      20);
				}
				if((strpos($thisLine, 'Client ') != FALSE) &&
				   (strpos($thisLine, ' disconnected') != FALSE))
				{
				   $thisLine = 'Connection: close';
				}

				if(strpos($thisLine, ': ') != FALSE)
				{
				   $thisEntryName = substr($thisLine, 0, strpos($thisLine, ': '));
				   $thisEntryValue = substr($thisLine, strpos($thisLine, ': ') + 2);

				   if(strpos($thisEntryName, ':') != FALSE)
				   {
				      $thisEntryDate = substr($thisEntryName, 0, 19);
				      $thisEntryName = substr($thisEntryName, 20);
				   }
				   
				   if($thisEntryName == 'Client-computer-name')
				   {
				      SetValue($clientNameId, $thisEntryValue);
				   }
				   else if($thisEntryName == 'Connection')
				   {
				      if($thisEntryValue == 'close')
				      {
				      	SetValue($clientConnectionId, false);
					      SetValue($clientNameId, '');
					      SetValue($clientIPId, '');
					      SetValue($clientTypeId, '');
						}
				   }
				   else if($thisEntryName == 'Http Request')
				   {
				      if(substr($thisEntryValue, 0, 8) == 'ANNOUNCE')
				      {
				      	SetValue($clientConnectionId, true);
				      }
				      else if(substr($thisEntryValue, 0, 8) == 'TEARDOWN')
				      {
					      SetValue($clientNameId, '');
				      	SetValue($clientConnectionId, false);
					      SetValue($clientIPId, '');
					      SetValue($clientTypeId, '');
				      }
				   }
				   else if($thisEntryName == 'User-Agent')
				   {
				         if(substr($thisEntryValue, 0, 6) == 'iTunes')
				         {
					      	SetValue($clientTypeId, 'iTunes');
					      	if(GetValue($clientNameId) == "")
					      	   SetValue($clientNameId,
					      	      'iTunes');
					      }
					      else if(substr($thisEntryValue, 0, 7) == 'Airfoil')
					      {
					      	SetValue($clientTypeId, 'Airfoil');
					      }
					      else
					      {
					         if(strpos($thisEntryValue, '/') != FALSE)
					            $thisEntryValue = substr($thisEntryValue, 0,
					               strpos($thisEntryValue, '/'));

					         if(strpos($thisEntryValue, ' ') != FALSE)
					            $thisEntryValue = substr($thisEntryValue, 0,
					               strpos($thisEntryValue, ' '));
					      	SetValue($clientTypeId, $thisEntryValue);
					      }
				   }
				   else if($thisEntryName == 'X-Apple-Device-ID')
				   {
				      if(GetValue($clientTypeId) == '')
				         SetValue($clientTypeId,
				            'IOS Device');
			      	if(GetValue($clientNameId) == "")
			      	   SetValue($clientNameId,
			      	      'IOS Device');
				   }
				   else if($thisEntryName == 'Accepted new client')
				   {
				      if(substr($thisEntryValue, 0, 1) == '[')
				         $thisEntryValue = substr($thisEntryValue, 1);

						if(strpos($thisEntryValue, ']') != FALSE)
						   $thisEntryValue = substr($thisEntryValue, 0,
						      strpos($thisEntryValue, ']'));

						if(strpos($thisEntryValue, '%') != FALSE)
						   $thisEntryValue = substr($thisEntryValue, 0,
						      strpos($thisEntryValue, '%'));

						$hostName = gethostbyaddr($thisEntryValue);
						if(strpos($hostName, '.') != FALSE)
						   $hostName = substr($hostName, 0, strpos($hostName, '.'));
						
				      SetValue($clientIPId, $thisEntryValue);
				      
						if($hostName != $thisEntryValue)
				      	SetValue($clientNameId,
								$hostName);
				   }

				   //echo($thisEntryDate . ' ' . $thisEntryName . '=' . $thisEntryValue . "\r");
				}
			}

			fclose($hdl);
		}
		else
		   echo 'Warning: Could not open file.' . "\r";
	}
	else
	   echo 'Warning: Unable to create snapshot.' . "\r";
}
//else
   //echo 'No log file to process right now.' . "\r";
%>