And btw, it can't play the AAC+ streams.
Of course I can make it much nicer and also make it use FMOD to stream and such, but what is the point when it's a "illegal" program?

Code: Select all
; ------------------------------------------------
; Title: Shoutcast Radio Player
; Version: 1.0
; PB Ver: 4.02
;
; Author: Joakim L. Christiansen
; Homepage: http://www.myhome.no/jlc_software
;
; About:
; Little example on how to get shoutcast streams,
; but beware; it's against shoutcasts copyright laws.
; ------------------------------------------------
;- Enumeration
Enumeration ;Windows
#Main
EndEnumeration
Enumeration ;Gadgets
#Main_Genre
#Main_Channels
#Main_Find
#Main_Player
#Main_Pages
EndEnumeration
;_
;- Data
DataSection
IID_IHTMLDocument2: ;{332C4425-26CB-11D0-B483-00C04FD90119}
Data.l $332C4425
Data.w $26CB, $11D0
Data.b $B4, $83, $00, $C0, $4F, $D9, $01, $19
EndDataSection
;_
;- Structures
Structure Channel
Name.s
URL.s
WebPage.s
Listeners.s
BitRate.l
Type.s
NowPlaying.s
EndStructure
;_
;- Variables
Global NewList Channel.Channel()
Define WindowEvent.l, SelectedChannel.l, i.l
;_
;- Procedures
Procedure.s DownloadToMemory(Url.s)
Protected hURL.l, Bytes.l, File.s, hInet.l
Protected BufferLength.l = 2048, Buffer.s = Space(BufferLength)
hInet = InternetOpen_("PB",1,0,0,0)
hURL = InternetOpenUrl_(hInet,Url,0,0,$80000000,0)
If hURL
While InternetReadFile_(hURL,@Buffer,BufferLength,@Bytes) And Bytes > 0
File + PeekS(@Buffer,Bytes)
Wend
Else
Debug "No such URL"
EndIf
InternetCloseHandle_(hURL)
InternetCloseHandle_(hInet)
ProcedureReturn File
EndProcedure
Procedure GetStreams(Genre.s,Page.l) ;page.l
Protected Line.l
Protected File.s, FileLength.l, FilePosition.l, FileString.s = ""
File = DownloadToMemory("http://www.shoutcast.com/directory/index.phtml?sgenre="+Genre+"&startat="+Str(Page*20))
If File
FileLength = MemoryStringLength(@File) ;MemorySize(@File) StringByteLength(File)
While FilePosition < FileLength
Byte = PeekB(@File+FilePosition): FilePosition + 1
If Byte = #LF
;- Scan
If Line > 0
Line + 1
EndIf
If Mid(FileString,52,6) = "a href" ;Get stream URL
AddElement(Channel())
Channel()\URL = "http://www.shoutcast.com"+StringField(FileString,6,#DQUOTE$)
Line = 1
EndIf
Select Line
Case 3 ;Get channel name and webpage
Channel()\WebPage = StringField(FileString,20,#DQUOTE$)
If StringField(FileString,8,">") = "CLUSTER </font"
Channel()\Name = StringField(FileString,10,">")
Else
Channel()\Name = StringField(FileString,8,">")
EndIf
Channel()\Name = RemoveString(Channel()\Name,"</a")
Case 5 ;Get now playing status ;if it's not found line++
If CountString(FileString,"nbsp;") = 2
Channel()\NowPlaying = StringField(FileString,8,">")
ElseIf CountString(FileString,"nbsp;")
Channel()\NowPlaying = StringField(FileString,6,">")
If Channel()\NowPlaying = ""
Line + 1
Beep_(1000,2)
EndIf
Else
Channel()\NowPlaying = StringField(FileString,4,">")
EndIf
Channel()\NowPlaying = LTrim(RemoveString(Channel()\NowPlaying,"</font"))
Case 7 ;Get listners
Channel()\Listeners = StringField(FileString,3,">")
Channel()\Listeners = RemoveString(Channel()\Listeners,"</font")
Case 9 ;Get bitrate
Channel()\BitRate = Val(StringField(FileString,3,">"))
Case 14 ;Get type
Channel()\Type = StringField(FileString,3,">")
Channel()\Type = LTrim(RemoveString(Channel()\Type,"</font"))
With Channel()
AddGadgetItem(#Main_Channels,-1,\Name+#LF$+\NowPlaying+#LF$+\Listeners+#LF$+Str(\BitRate)+#LF$+\Type)
EndWith
EndSelect
;_
FileString = ""
ElseIf Not Byte = #CR
FileString + Chr(Byte)
EndIf
Wend
FilePosition = 0
EndIf
EndProcedure
Procedure.l WebGadget_Write(Gadget.l,Html.s)
Protected Browser.IWebBrowser2 = GetWindowLong_(GadgetID(Gadget),#GWL_USERDATA)
Protected Document.IHTMLDocument2
Protected DocumentDispatch.IDispatch
Protected Result.l, Busy.l, Unicode.s, bstr_string.l, *sfArray, *varParam.VARIANT
If GetGadgetText(Gadget) = ""
SetGadgetText(Gadget,"about:blank")
EndIf
Repeat
While WindowEvent(): Wend
Browser\get_Busy(@Busy)
If Busy = #VARIANT_TRUE
Delay(10)
EndIf
Until Busy = #VARIANT_FALSE
If Browser
If Browser\get_document(@DocumentDispatch) = #S_OK And DocumentDispatch
If DocumentDispatch\QueryInterface(?IID_IHTMLDocument2,@Document) = #S_OK
If Document
Unicode = Space(Len(Html)*2+2)
PokeS(@Unicode, Html, -1, #PB_Unicode)
bstr_string = SysAllocString_(@Unicode)
*sfArray = SafeArrayCreateVector_(#VT_VARIANT, 0, 1)
If *sfArray
If SafeArrayAccessData_(*sfArray, @*varParam) = #S_OK
*varParam\vt = #VT_BSTR
*varParam\bstrVal = bstr_string
If SafeArrayUnaccessData_(*sfArray) = #S_OK
Document\write(*sfArray)
Result = #True ;Document written
EndIf
EndIf
SafeArrayDestroy_(*sfArray)
EndIf
SysFreeString_(bstr_string)
EndIf
Document\close()
Document\Release()
EndIf
DocumentDispatch\Release()
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure PlayChannel(URL.s)
Protected Html.s
Html + "<object id='VIDEO' width='100%' height='100%'"
Html + "style='position:absolute; left:0; top:0;'"
Html + "classid='clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6'" ;normal
Html + "type='application/x-oleobject'>"
Html + "<param name='URL' value='"+URL+"'>"
Html + "<param name='StretchToFit' value='true'>"
Html + "<param name='UiMode' value='mini'>"
Html + "<param name='EnableContextMenu' value='false'>"
Html + "</object>"
If Not WebGadget_Write(#Main_Player,Html)
MessageRequester("Error!","Error changing webgadget content")
EndIf
EndProcedure
Procedure.s GetStreamAddress(URL.s)
ProcedureReturn StringField(StringField(DownloadToMemory(URL),3,Chr(10)),2,"=")
EndProcedure
;_
;- Open window
If OpenWindow(#Main,0,0,500,300,"Shoutcast Radio Player",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget) And CreateGadgetList(WindowID(0))
WebGadget(#Main_Player,260,5,50,20,""): HideGadget(#Main_Player,#True)
TextGadget(#PB_Any,260,8,80,20,"Pages to scan:")
SpinGadget(#Main_Pages,340,5,30,20,1,4,#PB_Spin_Numeric)
SetGadgetState(#Main_Pages,1): SetGadgetText(#Main_Pages,"1")
ComboBoxGadget(#Main_Genre,5,5,200,160): ButtonGadget(#Main_Find,210,5,40,20,"Find")
AddGadgetItem(#Main_Genre,-1,"TopTen")
AddGadgetItem(#Main_Genre,-1,"Alternative")
AddGadgetItem(#Main_Genre,-1,"Classical")
AddGadgetItem(#Main_Genre,-1,"Comedy")
AddGadgetItem(#Main_Genre,-1,"Country")
AddGadgetItem(#Main_Genre,-1,"Dance")
AddGadgetItem(#Main_Genre,-1,"Funk")
AddGadgetItem(#Main_Genre,-1,"Jazz")
AddGadgetItem(#Main_Genre,-1,"Metal")
AddGadgetItem(#Main_Genre,-1,"Mixed")
AddGadgetItem(#Main_Genre,-1,"Rock")
AddGadgetItem(#Main_Genre,-1,"Talk")
AddGadgetItem(#Main_Genre,-1,"Techno")
AddGadgetItem(#Main_Genre,-1,"World")
SetGadgetState(#Main_Genre,8)
ListIconGadget(#Main_Channels,5,30,490,265,"Channel",150,#PB_ListIcon_FullRowSelect)
AddGadgetColumn(#Main_Channels,1,"Now playing",140)
AddGadgetColumn(#Main_Channels,2,"Listeners/Max",85)
AddGadgetColumn(#Main_Channels,3,"BitRate",50)
AddGadgetColumn(#Main_Channels,4,"Type",40)
Else
MessageRequester("Error","Error opening window!",#MB_ICONERROR)
EndIf
;_
Repeat ;-Main loop
WindowEvent = WaitWindowEvent()
Select WindowEvent
Case #PB_Event_CloseWindow
Break
Case #PB_Event_SizeWindow
ResizeGadget(#Main_Channels,#PB_Ignore,#PB_Ignore,WindowWidth(#Main)-10,WindowHeight(#Main)-35)
Case #PB_Event_Gadget
Select EventGadget()
Case #Main_Find
ClearList(Channel())
ClearGadgetItemList(#Main_Channels)
For i=0 To GetGadgetState(#Main_Pages)-1
GetStreams(GetGadgetText(#Main_Genre),i)
Next
Case #Main_Channels
Select EventType()
Case #PB_EventType_LeftDoubleClick
If GetGadgetState(#Main_Channels) > -1
SelectElement(Channel(),GetGadgetState(#Main_Channels))
PlayChannel(GetStreamAddress(Channel()\URL))
SetGadgetItemColor(#Main_Channels,SelectedChannel,#PB_Gadget_BackColor,-1)
SelectedChannel = GetGadgetState(#Main_Channels)
SetGadgetItemColor(#Main_Channels,SelectedChannel,#PB_Gadget_BackColor,#Green)
EndIf
EndSelect
EndSelect
EndSelect
ForEver