Quantcast
Channel: AutoIt v3 - General Help and Support
Viewing all articles
Browse latest Browse all 12506

Streaming MP3 Files over LAN

$
0
0

Hello, I recently stumbled on a post using bass.dll to stream an audio file to a client script, which would then use bass.dll to play the audio data.

 

I have been trying to modify it to support a shuffle like feature, where a user can select a folder, and have songs randomly streamed to clients one after another. I attempted to do this by switching the active audio file after the duration of the song has passed, however, the result causes the whole broadcaster to freeze,  after sending just a small amount of the song to the client.

 

 

Could anyone help me out, or point out what I'm doing wrong please? 

 

Broadcaster:

AutoIt         
#cs     Very simple broadcasting script.     Opens connection to unlimited amount of clients and sends binary data to them #ce #include <StaticConstants.au3> #include <Array.au3> #include <WinApi.au3> #include <sound.au3> Opt("GUIOnEventMode", 1) TCPStartup() Global Const $sIP = "0.0.0.0", $iPort = 8000 Global Const $iBufferSize = 2 * 1024 Global Const $hBuffer = DllStructCreate("byte[" & $iBufferSize & "]") Global $sFile, $ListeningSocket, $Connections[1][2], $bBroadCasting = False, $hFile, $FileSize, $iRead $hWnd = GUICreate("Broadcaster++", 400, 150) GUISetBkColor(0) $label1 = GUICtrlCreateLabel("Status:", 10, 10, 380, 30, $SS_CENTER) GUICtrlSetColor(-1, 0xffffff) GUICtrlSetFont(-1, 24) $label2 = GUICtrlCreateLabel("Not broadcasting", 10, 45, 380, 50, $SS_CENTER) GUICtrlSetColor(-1, 0xff0000) GUICtrlSetFont(-1, 24) $button1 = GUICtrlCreateButton("Start Broadcasting", 200 - 75, 90, 150, 40) GUICtrlSetOnEvent(-1, "StartStopBroadcasting") GUISetOnEvent(-3, "close") GUISetState() Do     If $bBroadCasting Then     if IsDeclared($timer) Then         if $timer > $length Then             $rand = Random(1, $files[0], 1)             $sFile = $dir &"\"&$files[$rand]             $sound = _SoundOpen($sFile)             $length = _SoundLength($sound, 2)             _SoundClose($sound)             $timer = TimerInit()             ConsoleWrite("Switching to file "&$sFile&@CRLF)         EndIf     EndIf         $tempsocket = TCPAccept($ListeningSocket)         If $tempsocket <> -1 Then             ReDim $Connections[UBound($Connections) + 1][2]             $Connections[UBound($Connections) - 1][0] = $tempsocket         EndIf         For $i = UBound($Connections) - 1 To 1 Step -1             _WinAPI_SetFilePointer($hFile, $Connections[$i][1])             _WinAPI_ReadFile($hFile, DllStructGetPtr($hBuffer), $iBufferSize, $iRead)             $Connections[$i][1] += $iRead             If $iRead = 0 Then                 ConsoleWrite("All data pushed. Waiting for next song to start." & @CRLF)                 ContinueLoop             EndIf             $tempbuffer = DllStructCreate("byte[" & $iRead & "]", DllStructGetPtr($hBuffer))             ConsoleWrite("Sending " & $iRead & " bytes of data." & @CRLF)             TCPSend($Connections[$i][0], DllStructGetData($tempbuffer, 1))             If @error Then ; Client disconnected                 ConsoleWrite("Client disconnected." & @CRLF)                 TCPCloseSocket($Connections[$i][0])                 _ArrayDelete($Connections, $i)                 ContinueLoop             EndIf         Next     EndIf Until Not Sleep(10) Func StartStopBroadcasting()     If Not $bBroadCasting Then         Global $dir = FileSelectFolder("Please select the directory to play from", -1)             Global $files = _FileListToArray($dir, "*.mp3", 1) Global $rand = Random(1, $files[0], 1)         Global  $sFile = $dir &"\"&$files[$rand]         Global  $sound = _SoundOpen($sFile)         Global  $length = _SoundLength($sound, 2)             _SoundClose($sound)         Global  $timer = TimerInit()         If $sFile = "" Then Return         $ListeningSocket = TCPListen($sIP, $iPort)         $FileSize = FileGetSize($sFile)         $hFile = _WinAPI_CreateFile($sFile, 2, 2)         GUICtrlSetData($label2, "Broadcasting")         GUICtrlSetColor($label2, 0x00ff00)         GUICtrlSetData($button1, "Stop broadcasting")     Else         _WinAPI_CloseHandle($hFile)         $hFile = 0         For $i = UBound($Connections) - 1 To 1 Step -1             TCPCloseSocket($Connections[$i][0])             _ArrayDelete($Connections, $i)         Next         GUICtrlSetData($label2, "Not Broadcasting")         GUICtrlSetColor($label2, 0xFF0000)         GUICtrlSetData($button1, "Start broadcasting")         TCPCloseSocket($ListeningSocket)     EndIf     $bBroadCasting = Not $bBroadCasting EndFunc   ;==>StartStopBroadcasting Func close()     If $hFile <> 0 Then _WinAPI_CloseHandle($hFile)     For $i = UBound($Connections) - 1 To 1 Step -1         TCPCloseSocket($Connections[$i][0])         _ArrayDelete($Connections, $i)     Next     TCPShutdown()     Exit EndFunc   ;==>close

Client:

AutoIt         
#include <StaticConstants.au3> #include <Array.au3> ; Due to a bug in version <=3.3.0.0 the script will notfunction correctly in these warnings If Int(StringReplace(@AutoItVersion, ".", "")) <= 3300 Then     MsgBox(16,"Error!","This script is NOT compatible with this version of AutoIt!"&@CRLF&"Script will now exit!.")     Exit EndIf ; Bass constants Global Const $BASS_STREAM_BLOCK = 0x100000 ;// download/play internet file stream in small blocks Global Const $STREAMFILE_BUFFERPUSH = 2 Global Const $STREAMFILE_BUFFER = 1 Global Const $BASS_FILEDATA_END = 0 Global Const $BASS_FILEPOS_BUFFER = 5 ; Startup bass & create callbacks $bass = DllOpen("bass.dll") DllCall($bass, "int", "BASS_Init", "int", -1, "dword", 44100, "dword", 0, "hwnd", 0, "ptr", 0) $proc = DllStructCreate("ptr;ptr;ptr;ptr") $cb_close = DllCallbackRegister("Bass_Callback_Close", "none", "ptr") $cb_length = DllCallbackRegister("Bass_Callback_Length", "uint64", "ptr") $cb_read = DllCallbackRegister("Bass_Callback_Read", "dword", "ptr;dword;ptr") $cb_seek = DllCallbackRegister("Bass_Callback_Seek", "int", "uint64;ptr") DllStructSetData($proc, 1, DllCallbackGetPtr($cb_close)) DllStructSetData($proc, 2, DllCallbackGetPtr($cb_length)) DllStructSetData($proc, 3, DllCallbackGetPtr($cb_read)) DllStructSetData($proc, 4, DllCallbackGetPtr($cb_seek)) TCPStartup() Global Const $iPort = 8000 Global $bListening = False, $Socket, $DataBuffer, $hStream = 0 Opt("GUIOnEventMode", 1) $hWnd = GUICreate("Radio Client++", 400, 150) GUISetBkColor(0) $label1 = GUICtrlCreateLabel("Status:", 10, 10, 380, 30, $SS_CENTER) GUICtrlSetColor(-1, 0xffffff) GUICtrlSetFont(-1, 24) $label2 = GUICtrlCreateLabel("Not Listening", 10, 45, 380, 50, $SS_CENTER) GUICtrlSetColor(-1, 0xff0000) GUICtrlSetFont(-1, 24) $button1 = GUICtrlCreateButton("Start Listening", 200 - 75, 90, 150, 40) GUICtrlSetOnEvent(-1, "StartStopListening") GUISetOnEvent(-3, "close") GUISetState() Do     If $bListening Then         If $Socket <> -1 Then ; Recieve data             $verytemp = TCPRecv($Socket, 1024 ^ 2, 1)             If @error Then $Socket = -1             $DataBuffer = Binary($DataBuffer) & Binary($verytemp)         ElseIf BinaryLen($DataBuffer) = 0 Then ; End of data             Do                 $call = DllCall($bass, "int64", "BASS_StreamGetFilePosition", "dword", $hStream, "dword", $BASS_FILEPOS_BUFFER)                 Sleep(10)             Until Not $call[0] ; Wait until the playback buffer is empty             DllCall($bass, "dword", "BASS_StreamPutFileData", "dword", $hStream, "ptr", $BASS_FILEDATA_END, "int", 0)             StartStopListening()         EndIf         If $hStream = 0 And BinaryLen($DataBuffer) > 8192 Then ; When we have recieved some initial data lets create the stream             ; Create data buffer             $tempbuffer = DllStructCreate("byte[" & BinaryLen($DataBuffer) & "]")             DllStructSetData($tempbuffer, 1, $DataBuffer)             ; Create stream (here comes the story of bass):             ; Even though I wanted to PUSH the data myself (you know, since we don't know when the data will be coming in),             ; but Bass still wants to call the read callbacks making life, uhm quite  annoying. See the Bass_Callback_Read function.             $hStream = DllCall($bass, "dword", "BASS_StreamCreateFileUser", "dword", $STREAMFILE_BUFFERPUSH, "dword", 0, _                     "ptr", DllStructGetPtr($proc), "ptr", DllStructGetPtr($tempbuffer))             $hStream = $hStream[0]             ; Start the playback             DllCall($bass, "dword", "BASS_ChannelPlay", "dword", $hStream, "int", 0)         ElseIf $hStream <> 0 And (BinaryLen($DataBuffer)>1024*10 Or $Socket=-1) Then             ; No need to copy entire buffer around, 256 kB should be enough.             If BinaryLen($DataBuffer) < 256 * 1024 Then                 $tempbuffer = DllStructCreate("byte[" & BinaryLen($DataBuffer) & "]")             Else                 $tempbuffer = DllStructCreate("byte[" & 256 * 1024 & "]")             EndIf             DllStructSetData($tempbuffer, 1, $DataBuffer)             ; Push some data!             $call = DllCall($bass, "dword", "BASS_StreamPutFileData", "dword", $hStream, "ptr", DllStructGetPtr($tempbuffer), "int", DllStructGetSize($tempbuffer))             ConsoleWrite("Pushed "&$call[0]&" bytes of data (Total buffer size: "&BinaryLen($DataBuffer)&")."& @CRLF)             ; Remove data that already have been pushed.             $DataBuffer = Binary(BinaryMid($DataBuffer, $call[0] + 1))         EndIf     EndIf Until Not Sleep(75) Func StartStopListening()     If Not $bListening Then         $sIP = InputBox("IP of broadcaster", "Please enter the dotted ip address of the broadcaster", @IPAddress1)         $Socket = TCPConnect($sIP, $iPort)         If $Socket = -1 Then             MsgBox(16, "Error", "Failed to connect")             Return         EndIf         GUICtrlSetData($label2, "Listening")         GUICtrlSetColor($label2, 0x00ff00)         GUICtrlSetData($button1, "Stop Listening")         $DataBuffer = ""     Else         DllCall($bass, "dword", "BASS_StreamFree", "dword", $hStream)         $hStream = 0         GUICtrlSetData($label2, "Not Listening")         GUICtrlSetColor($label2, 0xff0000)         GUICtrlSetData($button1, "Start Listening")         TCPCloseSocket($Socket)     EndIf     $bListening = Not $bListening EndFunc   ;==>StartStopListening Func close()     DllCall($bass, "int", "BASS_StreamFree", "dword", $hStream)     TCPShutdown()     Exit EndFunc   ;==>close Func Bass_Callback_Close($pUser)     ConsoleWrite("Bass wants to close the file." & @CRLF) EndFunc   ;==>Bass_Callback_Close Func Bass_Callback_Length($pUser)     ConsoleWrite("Bass wants the length of the file." & @CRLF)     ; Returning 0 means Bass will get the data when bass gets it.     Return 0 EndFunc   ;==>Bass_Callback_Length Func Bass_Callback_Read($pBuffer, $iSize, $pUser)     ; Write data to the buffer pointer Bass supplied us with.     ; Hopefully bass don't want more than 8 kB (the amount of data guarantied to be in the buffer)     $tBuffer = DllStructCreate("byte[" & $iSize & "]", $pBuffer)     DllStructSetData($tBuffer, 1, BinaryMid($DataBuffer, 1, $iSize))     $DataBuffer = BinaryMid($DataBuffer, $iSize)     ConsoleWrite("Bass wants to read " & $iSize & " bytes." & @CRLF)     Return $iSize EndFunc   ;==>Bass_Callback_Read Func Bass_Callback_Seek($iOffset, $pUser)     ConsoleWrite("Bass wants to seek the file." & @CRLF) EndFunc   ;==>Bass_Callback_Seek

requires Attached File  bass.zip   94.29KB   2 downloads


Viewing all articles
Browse latest Browse all 12506

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>