1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215:
| unit Radio;
interface uses Types, Classes, bass, Windows, SysUtils;
type TonError = procedure (Sender: TObject;Errnr: Integer;ErrMsg: String) of Object; TonStatusChg = procedure(Sender: TObject; Status: String) of Object; TonInfoChg = procedure(Sender: TObject) of Object;
TRadio = class(TComponent) private FUrl: String; FStatus: String; FTitel: String; FSender: String; FBitrate: Integer;
FonError : TonError; FonStatusChg : TonStatusChg; FonInfoChg: TonInfoChg;
procedure ErrorMsg(nr:Integer;msg:String); procedure StatusMsg(msg:String); procedure InfoMsg(); protected public Constructor Create(AOwner:TComponent);override;
procedure Connect; published property URL:String Read FUrl Write FUrl; property Status:String read FStatus; property Sender:String read FSender; property Titel:String read FTitel;
property onError:TonError read FonError write FonError; property onStatusChg:TonStatusChg read FonStatusChg write FonStatusChg; property onInfoChg:TonInfoChg read FonInfoChg write FonInfoChg; end;
PRadio = ^TRadio;
var Proxy: array [0..99] of AnsiChar; cthread: DWORD = 0; chan: HSTREAM = 0; win: hwnd;
implementation
procedure DoMeta(user: Pointer); var meta: PAnsiChar; p: Integer; mp: PRadio; mr: TRadio; begin mp := PRadio(user); mr := mp^; meta := BASS_ChannelGetTags(chan, BASS_TAG_META); if (meta <> nil) then begin p := Pos('StreamTitle=', String(AnsiString(meta))); if (p = 0) then Exit; p := p + 13; mr.FTitel := Copy(meta, p, Pos(';', String(meta)) - p - 1); mr.InfoMsg; end; end;
procedure MetaSync(handle: HSYNC; channel, data, user: DWORD); stdcall; var pt: Pointer; begin pt := Pointer(user); DoMeta(pt); end;
procedure StatusProc(buffer: Pointer; len, user: DWORD); stdcall; var txt: String; mr: TRadio; p: PRadio; begin p := PRadio(user); if (buffer <> nil) and (len = 0) then begin if Assigned(p) then begin mr := p^; txt := IntToStr(DWORD(PAnsiChar(buffer))); mr.FStatus := txt; mr.StatusMsg(txt); end; end; end;
function OpenURL(url: String; pt: Pointer): Integer; var icy: PAnsiChar; Len, Progress: DWORD; txt: String; chg: Boolean; en: Integer; mp: PMMRadio; mr: TMMRadio; begin Result := 0; BASS_StreamFree(chan); progress := 0; mp := PRadio(pt); mr := mp^; mr.FSender := ''; mr.FStatus := 'connecting...'; mr.FUrl := url; mr.FTitel := ''; mr.StatusMsg(mr.FStatus);
chan := BASS_StreamCreateURL(PAnsiChar(AnsiString(url)), 0, BASS_STREAM_STATUS, @StatusProc,pt); if (chan = 0) then begin en := BASS_ErrorGetCode; txt := 'Can''t play the stream' + #13#10 + '(error code: ' + IntToStr(en) + ')'; mr.ErrorMsg(en,txt); end else begin repeat len := BASS_StreamGetFilePosition(chan, BASS_FILEPOS_END); if (len = DW_Error) then break; progress := (BASS_StreamGetFilePosition(chan, BASS_FILEPOS_DOWNLOAD) - BASS_StreamGetFilePosition(chan, BASS_FILEPOS_CURRENT)) * 100 div len; txt := Format('buffering... %d%%', [progress]); mr.FStatus := txt; mr.StatusMsg(txt); until progress > 75; chg := False; icy := BASS_ChannelGetTags(chan, BASS_TAG_ICY); if (icy = nil) then icy := BASS_ChannelGetTags(chan, BASS_TAG_HTTP); if (icy <> nil) then while (icy^ <> #0) do begin if (Copy(icy, 1, 9) = 'icy-name:') then begin mr.FSender := Copy(icy, 10, MaxInt); chg := True; end else if (Copy(icy, 1, 7) = 'icy-br:') then begin mr.FBitrate := StrToInt(Copy(icy, 8, MaxInt)); chg := True; end; if chg then mr.InfoMsg;
icy := icy + Length(icy) + 1; end; DoMeta(pt); BASS_ChannelSetSync(chan, BASS_SYNC_META, 0, @MetaSync, pt); BASS_ChannelPlay(chan, FALSE); end; cthread := 0; end;
Constructor TRadio.Create(AOwner: TComponent); begin if (HIWORD(BASS_GetVersion) <> BASSVERSION) then begin if Assigned(FonError) then FonError(Self,1,'Eine inkorrekte Version von BASS.DLL wurde geladen'); Halt; end; if (not BASS_Init(-1, 44100, 0, 0, nil)) then begin if Assigned(FonError) then FonError(Self,1,'Kann das Gerät nicht initialisieren'); Halt; end; BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST, 1); BASS_SetConfig(BASS_CONFIG_NET_PREBUF, 0); BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY, @proxy[0]); end;
procedure TRadio.Connect; begin OpenURL(FUrl,@Self); end;
procedure TRadio.ErrorMsg(nr: Integer; msg: string); begin if Assigned(FonError) then FonError(Self,nr,msg); end;
procedure TRadio.StatusMsg(msg: string); begin if Assigned(FonStatusChg) then FonStatusChg(Self,msg); end;
procedure TRadio.InfoMsg; begin if Assigned(FonInfoChg) then FonInfoChg(Self); end;
end. |