nend Posted December 19, 2016 Posted December 19, 2016 Hi all, The last days I'm busy with trying to understand how a mp3 audio stream works. I needed for a much bigger project the meta data from a streaminglink. I found a lot of problems which I had to solve. But with a bit of help from Trancexx I manage to make it work. This program wil unpack playlist streams automaticly and shows the Artist - Title information (now playing) and al the icy headers. Ontop there is a small example and 4 streaminglinks (link 2,3 are playlist links). Please let me know what you think of it. expandcollapse popup#include <Array.au3> Local $link[4] $link[0] = "http://icecast-qmusic.cdp.triple-it.nl/Qmusic_nl_fouteuur_96.mp3" $link[1] = "http://www.radiostaddenhaag.com/stad.pls" $link[2] = "http://www.hitz24.com/streams/listen.pls" $link[3] = "http://candlelight.live-streams.nl/candlelight" TCPStartUp() Local $icy_array = _Get_ICY_data($link[0]); choose one of the link above If @error Then ConsoleWrite("Nothing found!"); not a streaminglink or the streaminglink is not providing the data Else _ArrayDisplay($icy_array) ; display the information EndIf TCPShutdown() ; #FUNCTION# ==================================================================================================================== ; Name ..........: Get Meta data ; Description ...: Gets a array with icy header ; Syntax ........: _Get_ICY_data(streaming mp3 audio link) ; Return values .: Success - 0 artist - title, rest are icy headers ; Failure - Returns @ERROR ; Author ........: Nend ; Remarks .......: ; Related .......: ; Link ..........: ; Thanks to......: Trancexx for pointing me in the right direction ; =============================================================================================================================== Func _Get_ICY_data($link) Local $meta_total Local $url_array = _Crack_URL($link); split link 0)domain 1)target 2)portnumber If Not @error Then Local $station_link_array = _Split_playlist_link($url_array[0], $url_array[1], $url_array[2]); if link is playlist return array with streaminglinks If Not @error Then For $i = 0 To UBound($station_link_array)-1 $url_array = _Crack_URL($station_link_array[$i]); split link 0)domain 1)target 2)portnumber If Not @error Then $meta_total = _Get_stream_info($url_array[0], $url_array[1], $url_array[2]) If Not @error Then Return $meta_total EndIf Else Return SetError(1) EndIf Next Else $meta_total = _Get_stream_info($url_array[0], $url_array[1], $url_array[2]); if not playlist then get info from link If @error Then Return SetError(2) Else Return $meta_total EndIf EndIf Else Return SetError(1) EndIf EndFunc Func _Get_stream_info($_Host, $link, $_Port=80) Local $Total_header, $metaint, $icy_array[1] Local $_Timer = TimerInit() For $i = 0 To 4; try 5 times to connect to host Local $socket = TCPConnect(TCPNameToIP($_Host), $_Port) If Not @error Then ExitLoop EndIf Sleep(200) next If $socket <> -1 Then TCPSend($socket, "GET /" & $link & " HTTP/1.1" & @CRLF & _ "Icy-MetaData:1" & @CRLF & _ "User-Agent: TR" & @CRLF & _ "Host: " & $_Host & @CRLF & _ "Connection: Close" & @CRLF & _ "Cache-Control: no-cache" & @CRLF & @CRLF); send options While 1 $tcp_recieve = TCPRecv($socket, 800, 1) $Total_header = Binary($Total_header) & $tcp_recieve If StringInStr($tcp_recieve, "0d0a0d") Then; if end header then Local $Header_length = StringInStr(BinaryToString($Total_header), @CRLF & @CRLF) Local $header = BinaryToString(BinaryMid($Total_header, 1, $Header_length-1)) Local $metaint_array = StringRegExp($header, "(?<=icy-metaint:).*",3) If Not @error Then $metaint = $metaint_array[0]; icy meta int to know where the meta data is in the binary code EndIf EndIf If $metaint <> "" Then; If Meta int is known If BinaryLen($Total_header) > $metaint + 500 Then Local $strip_binary = BinaryToString(BinaryMid($Total_header, $Header_length + 5 + $metaint, 500), 4); strip the binary data from meta int Local $split_meta_array = StringRegExp($strip_binary, "(?<=StreamTitle=').*?(?=';)", 3); strip Streamtitle from binary data If Not @error Then; if found TCPCloseSocket($socket); close socket $icy_array[0] = $split_meta_array[0] $icy_header_array = StringRegExp($header, "icy-.*", 3) ReDim $icy_array[UBound($icy_header_array) + 1] For $i = 1 To UBound($icy_header_array); put al the icy info in a array $icy_array[$i] = $icy_header_array[$i-1] Next Return $icy_array; return 0 artist - title the rest of the array is the icy data ExitLoop EndIf EndIf EndIf If TimerDiff($_Timer) > 1000 Then; timeout if more then 1000 milsec TCPCloseSocket($socket) Return SetError(2) ExitLoop EndIf WEnd Else Return SetError(1) EndIf EndFunc Func _Split_playlist_link($_Host, $link, $_Port=80) Local $total_string Local $_Timer = TimerInit() For $i = 0 To 4; try 5 times to connect to host Local $socket = TCPConnect(TCPNameToIP($_Host), $_Port) If Not @error Then ExitLoop EndIf Sleep(200) next If $socket <> -1 Then TCPSend($socket, "GET " & $link & " HTTP/1.1" & @CRLF & _ "User-Agent: TR" & @CRLF & _ "Host: " & $_Host & @CRLF & _ "Connection: keep-alive" & @CRLF & _ "Cache-Control: no-cache" & @CRLF & @CRLF); send options While 1 $tcp_recieve = TCPRecv($socket, 4000, 1) $total_string = Binary($total_string) & $tcp_recieve If BinaryLen($tcp_recieve) = 0 Then TCPCloseSocket($socket) ExitLoop EndIf $_Recv = BinaryToString($tcp_recieve); concat binary string If TimerDiff($_Timer) > 1000 Then; timeout if more then 1000 milsec TCPCloseSocket($socket) ExitLoop EndIf WEnd $total_string = BinaryToString($total_string) If StringInStr($total_string, "pls+xml") Or StringInStr($total_string, "x-scpls") Or StringInStr($total_string, "x-mpegurl") Then; Check for Content-Type Return StringRegExp($total_string, "http://.*", 3); return array with all links Else Return SetError(1) EndIf Else SetError(1) Return 0 EndIf EndFunc Func _Crack_URL($Domain_total); Crack URL and return array 0)domain 1)target 2)pornumber Local $aResult, $splitarray, $return[3], $port, $Domain, $link StringRegExpReplace($Domain_total, "/", "/", 0) If @extended > 2 Then $Domain = StringLeft($Domain_total, StringInStr($Domain_total, "/", Default, 3)-1) $link = StringReplace($Domain_total, $Domain, "") Else $Domain = $Domain_total EndIf $Domain = StringReplace($Domain, "http://", "") $Domain = StringReplace($Domain, "www.", "") If StringInStr($Domain, ":") Then $splitarray = StringSplit($Domain, ":", 2) If Not @error Then $Domain = $splitarray[0] $port = $splitarray[1] EndIf EndIf If $port = "" Then $port = 80 EndIf $return[0] = $Domain $return[1] = $link $return[2] = $port Return $return EndFunc
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now