Autor Beitrag
mtm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64

Windows 10 Pro 64 Bit
Delphi XE 6
BeitragVerfasst: Di 10.04.12 15:36 
Hallo zusammen.

Ich versuche gerade eine NetRadio-Komponente zu erstellen, die auf bass.dll basiert. Ich habe mich dabei stark an dem Netradio-Beispiel gehalten, das bei BASS dabei war. Soweit funktioniert das auch ganz gut, ich habe aber ein Problem. In der Komponente sind selbstverständlich auch Events eingebaut.

ausblenden volle Höhe Delphi-Quelltext
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: Stringof Object;
  TonStatusChg = procedure(Sender: TObject; Status: Stringof 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..99of AnsiChar; //proxy server
  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 <> nilthen
  begin
    p := Pos('StreamTitle='String(AnsiString(meta)));
    if (p = 0then
      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 <> niland (len = 0then 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); // close old stream
  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 = 0then
  begin
    //lets catch the error here inside the Thread
    // and send it to the WndProc
    en := BASS_ErrorGetCode;
    txt := 'Can''t play the stream' + #13#10 + '(error code: ' + IntToStr(en) + ')';
    mr.ErrorMsg(en,txt);
  end
  else
  begin
    // Progress
    repeat
      len := BASS_StreamGetFilePosition(chan, BASS_FILEPOS_END);
      if (len = DW_Error) then
        break; // something's gone wrong! (eg. BASS_Free called)
      progress := (BASS_StreamGetFilePosition(chan, BASS_FILEPOS_DOWNLOAD) -
        BASS_StreamGetFilePosition(chan, BASS_FILEPOS_CURRENT)) * 100 div len;
      // percentage of buffer filled
      txt := Format('buffering... %d%%', [progress]);
      mr.FStatus := txt;
      mr.StatusMsg(txt);
    until
      progress > 75;
    // get the broadcast name and bitrate
    chg := False;
    icy := BASS_ChannelGetTags(chan, BASS_TAG_ICY);
    if (icy = nilthen
      icy := BASS_ChannelGetTags(chan, BASS_TAG_HTTP); // no ICY tags, try HTTP
    if (icy <> nilthen
      while (icy^ <> #0do
      begin
        if (Copy(icy, 19) = 'icy-name:'then begin
          mr.FSender :=  Copy(icy, 10, MaxInt);
          chg := True;
        end else if (Copy(icy, 17) = '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;
    // get the stream title and set sync for subsequent titles
    DoMeta(pt);
    BASS_ChannelSetSync(chan, BASS_SYNC_META, 0, @MetaSync, pt);
    // play it!
    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(-14410000nil)) then
  begin
    if Assigned(FonError) then
      FonError(Self,1,'Kann das Gerät nicht initialisieren');
    Halt;
  end;
  BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST, 1); // enable playlist processing
  BASS_SetConfig(BASS_CONFIG_NET_PREBUF, 0); // minimize automatic pre-buffering, so we can do it (and display it) instead
  BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY, @proxy[0]); // setup proxy server location
end;

procedure TRadio.Connect;
begin
  OpenURL(FUrl,@Self);
end;

procedure TRadio.ErrorMsg(nr: Integer; msg: string);
begin
  if Assigned(FonError) then  // Ist nicht assigned
    FonError(Self,nr,msg);
end;

procedure TRadio.StatusMsg(msg: string);
begin
  if Assigned(FonStatusChg) then  // Ist nicht assigned
    FonStatusChg(Self,msg);
end;

procedure TRadio.InfoMsg;
begin
  if Assigned(FonInfoChg) then  // Ist nicht assigned
    FonInfoChg(Self);
end;

end.


Wenn eines der Ereignisse ausgelöst werden soll wird die entsprechende Prozedur aufgerufen (ErrorMsg, StatusMsg, InfoMsg). Das klappt auch. Wenn ich das Programm mit dem Debugger durchgehe sind aber die Event-Variablen (FonError, FonStatusChg, FonInfoChg) immer auf nil.

Hat einer eine Idee, woran das liegen kann ? Ich bin da irgendwie mit meinem Latein am Ende.

Danke im Voraus
mtm
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Di 10.04.12 15:53 
Hast Du die Porperties denn versorgt, im OI oder per Code ...

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
mtm Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64

Windows 10 Pro 64 Bit
Delphi XE 6
BeitragVerfasst: Di 10.04.12 15:59 
:oops: Gott, bin ich ein Depp !!!
Habe sie zwar schon per Code zugeordnet, aber natürlich erst nach dem Aufruf von Connect.

Danke Dir