Sign in to follow this  
Followers 0
nend

Get meta data (same as the working PHP script) [SOLVED]

9 posts in this topic

#1 ·  Posted (edited)

Hi all,

I'm trying to get a meta data from a audio stream.

I found a PHP script wich works perfectly.

<?php
    $stream = getMp3StreamTitle("http://icecast-qmusic.cdp.triple-it.nl/Qmusic_nl_fouteuur_96.mp3");
    print($stream);

    function getMp3StreamTitle($steam_url)
    {
        $result = false;
        $icy_metaint = -1;
        $needle = 'StreamTitle=';
        $ua = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36';

        $opts = array(
            'http' => array(
                'method' => 'GET',
                'header' => 'Icy-MetaData: 1',
                'user_agent' => $ua
            )
        );

        $default = stream_context_set_default($opts);

        $stream = fopen($steam_url, 'r');

        if($stream && ($meta_data = stream_get_meta_data($stream)) && isset($meta_data['wrapper_data'])){
            foreach ($meta_data['wrapper_data'] as $header){
                if (strpos(strtolower($header), 'icy-metaint') !== false){
                    $tmp = explode(":", $header);
                    $icy_metaint = trim($tmp[1]);
                    break;
                }
            }
        }

        print($icy_metaint);

        if($icy_metaint != -1)
        {
            $buffer = stream_get_contents($stream, 300, $icy_metaint);

            if(strpos($buffer, $needle) !== false)
            {
                $title = explode($needle, $buffer);
                $title = trim($title[1]);
                $result = substr($title, 1, strpos($title, ';') - 2);
            }
        }

        if($stream)
            fclose($stream);

        return $result;
    }
?>

I tryd to make this in autoit with winhttp but I only gets garbage.

I think I made a mistake in they binairy part of the script.

I don't understand that part well.

This is the autoit script so far.

#include "WinHttp.au3"

Opt("MustDeclareVars", 1)

Global $sHost = "http://icecast-qmusic.cdp.triple-it.nl"
Global $sTarget = "Qmusic_nl_fouteuur_96.mp3"

Global $hHttpOpen = _WinHttpOpen()
Global $hHttpConnect = _WinHttpConnect($hHttpOpen, $sHost)
Global $hHttpRequest = _WinHttpOpenRequest($hHttpConnect, Default, $sTarget)
_WinHttpSendRequest($hHttpRequest)
_WinHttpReceiveResponse($hHttpRequest)
Global $bChunk, $bData

If _WinHttpQueryDataAvailable($hHttpRequest) Then
    While 1
        $bChunk = _WinHttpReadData($hHttpRequest, 2) ; read binary
        If @error Then ExitLoop
        $bData = _WinHttpSimpleBinaryConcat($bData, $bChunk) ; concat two binary data
        
        If BinaryLen($bData) > 16000 Then ; if downloaded more than the metaint (metaint for this station is 16000)
            local $B_mid = BinaryMid($bData, 16000, 300); gets the data from 16000 till 16300
            ConsoleWrite(BinaryToString($B_mid) & @CRLF); display data in the console
            ExitLoop
        EndIf
    WEnd
EndIf

; Close handles
_WinHttpCloseHandle($hHttpRequest)
_WinHttpCloseHandle($hHttpConnect)
_WinHttpCloseHandle($hHttpOpen)

I think for some of the wizzkidzz here on the forum it's solved in notime.

If use winhttp found here on the website 

Can some one please help me with this?

Edited by nend

Share this post


Link to post
Share on other sites



Maybe like this:

#include "WinHttp.au3"

$sHost = "http://icecast-qmusic.cdp.triple-it.nl"
$sTarget = "Qmusic_nl_fouteuur_96.mp3"

$hHttpOpen = _WinHttpOpen()
$hHttpConnect = _WinHttpConnect($hHttpOpen, $sHost)
$hHttpRequest = _WinHttpOpenRequest($hHttpConnect, Default, $sTarget)
_WinHttpSendRequest($hHttpRequest, "Icy-MetaData: 1")
_WinHttpReceiveResponse($hHttpRequest)

$sYourData = "???"

If _WinHttpQueryDataAvailable($hHttpRequest) Then
    $sYourData = StringRegExpReplace(BinaryToString(_WinHttpReadData($hHttpRequest, 2, 16300)), "(?Us).*?StreamTitle='(.*?)';.*?", "$1")
EndIf

_WinHttpCloseHandle($hHttpRequest)
_WinHttpCloseHandle($hHttpConnect)
_WinHttpCloseHandle($hHttpOpen)


ConsoleWrite($sYourData & @CRLF)
MsgBox(4096, "Your Data...", $sYourData)

 

1 person likes this

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Thanks for the help trancexx.

I see it works perfectly, I will study it so I can do it my self the next time

THANKS!!

Share this post


Link to post
Share on other sites

Sure, np

Btw, you don't need BinaryToString() if you read it like this

_WinHttpReadData($hHttpRequest, 1, 16300)

 


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

@trancexx Thank for the tip.

I'm progressing with this script and made it that playlist links wil be extracted before getting the meta data.

This goes fine for a lot of streaming links but... not for all and I can't find out why.

This script has two streaminglinks in it 1 is working and the other not.

Do you have got any idea why?

This is the code so far.

#include "WinHttp.au3"
#include <Array.au3>

;$link = "http://www.hitz24.com/streams/listen.pls"; not working
$link = "http://62.138.0.105:8000/listen.pls?sid=1"; working
ConsoleWrite(_Get_meta_data($link) & @CRLF)

Func _Get_meta_data($link)
    Local $hHttpOpen = _WinHttpOpen()

    Local $link_array = _Split_playlist_link($link, $hHttpOpen)
    If Not @error Then
        For $i = 0 To UBound($link_array)-1
            Local $meta = _Get_meta_data_total($link_array[$i], $hHttpOpen)
            If Not @error Then
                ExitLoop
            EndIf
        Next
    Else
        Local $meta = _Get_meta_data_total($link, $hHttpOpen)
    EndIf

    _WinHttpCloseHandle($hHttpOpen)

    Return $meta
EndFunc

Func _Get_meta_data_total($link, $winhttp_handle)
    Local $sYourData
    Local $URL_array = _WinHttpCrackUrl($link)

    ;_ArrayDisplay($URL_array)

    Local $hHttpConnect = _WinHttpConnect($winhttp_handle, $URL_array[2], $URL_array[3])
    If $URL_array[6] = "" Then
        Local $hHttpRequest = _WinHttpOpenRequest($hHttpConnect)
    Else
        Local $hHttpRequest = _WinHttpOpenRequest($hHttpConnect, Default, $URL_array[6])
    EndIf
    _WinHttpSendRequest($hHttpRequest, "Icy-MetaData:1"  & @CRLF & _
                                       "User-Agent: TR" & @CRLF & _
                                       "Connection: Close" & @CRLF & _
                                       "Cache-Control: no-cache",  $URL_array[7])
    _WinHttpReceiveResponse($hHttpRequest)

    Local $sHeader = _WinHttpQueryHeaders($hHttpRequest)
    Local $metaint = StringRegExpReplace($sHeader, "(?Us).*?icy-metaint: (.*?).*?", "$1")
    If Not @error Then
        If _WinHttpQueryDataAvailable($hHttpRequest) Then
            $sYourData = StringRegExpReplace(BinaryToString(_WinHttpReadData($hHttpRequest, 2, $metaint+300)), "(?Us).*?StreamTitle='(.*?)';.*?", "$1")
        EndIf
    EndIf

    _WinHttpCloseHandle($hHttpRequest)
    _WinHttpCloseHandle($hHttpConnect)

    Return $sYourData
EndFunc

Func _Split_playlist_link($link, $winhttp_handle)
    Local $return_array
    Local $URL_array = _WinHttpCrackUrl($link)

    ;_ArrayDisplay($URL_array)

    Local $hHttpConnect = _WinHttpConnect($winhttp_handle, $URL_array[2], $URL_array[3])
    Local $hHttpRequest = _WinHttpOpenRequest($hHttpConnect, Default, $URL_array[6])
    _WinHttpSendRequest($hHttpRequest, "User-Agent: TR" & @CRLF & _
                                       "Connection: Close" & @CRLF & _
                                       "Cache-Control: no-cache", $URL_array[7])
    _WinHttpReceiveResponse($hHttpRequest)

    Local $sHeader = _WinHttpQueryHeaders($hHttpRequest)
    Local $a_content = StringRegExp($sHeader, "(?<=Content-Type:\s).*", 3)
    If Not @error Then
        If StringInStr($a_content[0], "pls+xml") Or StringInStr($a_content[0], "x-scpls") Or StringInStr($a_content[0], "x-mpegurl") Then
            If _WinHttpQueryDataAvailable($hHttpRequest) Then
                Local $data =_WinHttpReadData($hHttpRequest, 1)
                $return_array = StringRegExp($data, "http://.*", 3)
            EndIf
        EndIf
    EndIf

    _WinHttpCloseHandle($hHttpRequest)
    _WinHttpCloseHandle($hHttpConnect)

    If IsArray($return_array) Then
        Return $return_array
    Else
        Return SetError(1)
    EndIf
EndFunc

 

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

I've brought it back to a small piece of code but this won't return any info.

If I try it with a tcp script it returns this header:

cy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
icy-notice2:SHOUTcast Distributed Network Audio Server/Linux v1.9.8<BR>

icy-name:Hitz24 - The Hits Only Station
icy-genre:pop
icy-url:http://www.hitz24.com
content-type:audio/mpeg
icy-pub:1
icy-metaint:32768
icy-br:192

But if I use this script (for this link, many other links works well) it won't return anything.

#include "WinHttp.au3"
#include <Array.au3>

_Get_meta_data_total()

Func _Get_meta_data_total()
    Local $hHttpOpen = _WinHttpOpen()
    Local $sYourData

    Local $hHttpConnect = _WinHttpConnect($hHttpOpen, "37.59.195.28", "8033")
    Local $hHttpRequest = _WinHttpOpenRequest($hHttpConnect, Default, "/")
    _WinHttpSendRequest($hHttpRequest, "Cache-Control: no-cache" & @CRLF & _
                                       "Connection: Close" & @CRLF & _
                                       "Host: 37.59.195.28:8033" & @CRLF & _
                                       "User-Agent: BASS/2.4" & @CRLF & _
                                       "Icy-MetaData: 1" & @CRLF & @CRLF,  ""); same as wireshark return when starting this station with bass.dll


    ConsoleWrite(@error & " error" & @CRLF)
    _WinHttpReceiveResponse($hHttpRequest)
    ConsoleWrite(@error & " error" & @CRLF)
    Local $sHeader = _WinHttpQueryHeaders($hHttpRequest)
    ConsoleWrite(@error & " error" & @CRLF)
    ConsoleWrite($sHeader & @CRLF)
    If Not @error Then
        If _WinHttpQueryDataAvailable($hHttpRequest) Then
            $data = BinaryToString(_WinHttpReadData($hHttpRequest, 2, 1000))
            ConsoleWrite($data & @CRLF)
        EndIf
    EndIf

    _WinHttpCloseHandle($hHttpRequest)
    _WinHttpCloseHandle($hHttpConnect)
    _WinHttpCloseHandle($hHttpOpen)
EndFunc

This is the TCP script which returns the ICY header.

#include <Array.au3>
Local $url_array[3]

TCPStartUp()

$url_array[0] = "37.59.195.28"
$url_array[2] = "8033"

$meta_total = _Get_stream_info($url_array[0], $url_array[1], $url_array[2])
If Not @error Then
    ConsoleWrite($meta_total & @CRLF)

EndIf

TCPShutdown()

Func _Get_stream_info($_Host, $link, $_Port=80, $_TimeOut=1000)
    Local $_Timer = TimerInit()
    Local $socket = TCPConnect($_Host, $_Port)
    If Not @error Then
        If $socket = -1 Then
            Return 0
        EndIf
        TCPSend($socket, "GET /" & $link & " HTTP/1.1" & @CRLF & _
                             "Icy-MetaData:1"  & @CRLF & _
                             "User-Agent: TR" & @CRLF & _
                             "Connection: Close" & @CRLF & _
                             "Cache-Control: no-cache" & @CRLF & @CRLF)

        While 1
            $tcp_recieve = TCPRecv($socket, 1000, 1)
            $_Recv = BinaryToString($tcp_recieve)
            ConsoleWrite($_Recv & @CRLF)
            If StringInStr($_Recv, "icy-metaint:") Then
                TCPCloseSocket($socket)
                ExitLoop
            EndIf
            If TimerDiff($_Timer) > $_TimeOut Then
                TCPCloseSocket($socket)
                ExitLoop
            EndIf
        WEnd
    Else
        SetError(1)
        Return 0
    EndIf
EndFunc

 

Edited by nend

Share this post


Link to post
Share on other sites

That server that you have issues with uses some earlier versions of the software, where the header is malformed and doesn't comply with HTTP protocol rules.

WinHttp refuses to process it for security reasons. "ICY 200 OK" response is wrong here. Sorry.

1 person likes this

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Apart from that, you don't have to read the whole header and parse it using regexp. You can do this:

$metaint = _WinHttpQueryHeaders($hHttpRequest, $WINHTTP_QUERY_CUSTOM, "icy-metaint")

...and this to read content type:

_WinHttpQueryHeaders($hHttpRequest, $WINHTTP_QUERY_CONTENT_TYPE)

 

1 person likes this

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Ok that explained it why I didn't get it to work.

$metaint = _WinHttpQueryHeaders($hHttpRequest, $WINHTTP_QUERY_CUSTOM, "icy-metaint")

I didn't know that, thanks for the explaining and all the help.

So I will learn every time something new.

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0