ratmalwer
ratmalwer

Reputation: 735

How to correctly read an endless stream from InternetRadio using Indy TIdHTTP?

I am writing a UPNP-Controller.

To supply the Artist and Title, it's necessary that I can get the metadata, probably supplied as XML somewhere in the Stream.

For that, I want to read the (endless) stream from InternetRadio and detect the XML. I am not sure what it contains exactly, but I struggle with receiving the Stream as TMemoryStream. The program gets stuck after the Get command.

procedure TformMain.GetUrlStream(url: string; var m: Tmemorystream); 
var
  IdHTTP1: TIdHTTP;
  XMLStr: string;
  IO : TIdSSLIOHandlerSocketOpenSSL;
begin
  IdHTTP1 := TIdHTTP.Create;
  try
    IO := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
    IO.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
    IdHttp1.IOHandler := IO;
    IdHttp1.ConnectTimeout := 5000;
    IdHttp1.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36';
    IdHttp1.Request.Connection := 'close'; // Close connection after each request

    IdHTTP1.Get(url,m);           // --> here the program stops

  finally
    IdHTTP1.Free;
  end;
end;

Upvotes: 1

Views: 146

Answers (1)

ratmalwer
ratmalwer

Reputation: 735

I found a completly different way to get hold on the Metadata of the radiostream with the help of wget.exe. Here an exerpt of the code:

function TformMain.GetMetaTitle(url: string) : string;
var
  cmd: string;
  search,search2: string;
  p,p2 : integer;
  res : string;
  str :string;

begin
    //Get ici-MetaData
    result := '';
    StringReplace(url,'https://','http://',[rfReplaceAll, rfIgnoreCase]);

    cmd := 'wget --header="Icy-MetaData:1" -S -O reply.txt '+url;
    Memodummy.Clear;
    GetDosOutput(cmd,'',Memodummy,15); //15 erwartete metatags + 1 stream
    if processExists('wget.exe') then begin
        WinExec('taskkill /IM wget.exe /F', SW_HIDE);
    end;
    sleep(1000);  //Wait for Taskkill

    //Locate begin of title
    search := 'icy-metaint:';
    search2 := char(13);
    p := pos(search,Memodummy.Text,1);
    p2 := pos(search2,Memodummy.Text,p);
    res := Trim(copy(Memodummy.Text,p+length(search)+1,p2 - p - (length(search)+1)));

    //extract title if possible
    try
      str := TFile.ReadAllText('reply.txt');
      search := 'StreamTitle=';
      search2 := ';';
      p := pos(search,str,strtoint(res));
      p2 := pos(search2,str,p);
      result := Trim(copy(str,p+length(search)+1,p2 - p - (length(search)+1)-1));
      result := THTMLEncoding.HTML.Encode(result);
    except
      on e:exception do begin
        memo1.lines.Append('Fehler in GetMetatitle: ' +e.Message);
      end;
    end;
end;

The part of Locate begin of title could even be skipped and the outputfile (reply.txt) directly searched for StreamTitle=. So no output of the Dos-Window (here Memodummy) has to be analyzed. But so the structure is more clear I think.

So the short version would be: (untested)

function TformMain.GetMetaTitle(url: string) : string;
var
    cmd: string;
    search,search2: string;
    p,p2 : integer;
    str :string;
    begin
        //Get ici-MetaData
        result := '';
        StringReplace(url,'https://','http://',[rfReplaceAll, rfIgnoreCase]);
    
        cmd := 'wget --header="Icy-MetaData:1" -S -O reply.txt '+url;
        Shellexecute(cmd,........);
        if processExists('wget.exe') then begin
            WinExec('taskkill /IM wget.exe /F', SW_HIDE);
        end;
        sleep(1000);  //Wait for Taskkill
    
        //extract title if possible
        try
          str := TFile.ReadAllText('reply.txt');
          search := 'StreamTitle=';
          search2 := ';';
          p := pos(search,str,strtoint(res));
          p2 := pos(search2,str,p);
          result := Trim(copy(str,p+length(search)+1,p2 - p - (length(search)+1)-1));
          result := THTMLEncoding.HTML.Encode(result);
        except
          on e:exception do begin
            memo1.lines.Append('Fehler in GetMetatitle: ' +e.Message);
          end;
        end;
    end;

Upvotes: 1

Related Questions