update 1.6.2

this update is update on server side
new
Buffer

client side
fix buffer
This commit is contained in:
dharm pimsen 2024-02-27 20:48:19 +07:00
parent d5e6b8e1ea
commit 1e77eae2d8
9 changed files with 170 additions and 93 deletions

View File

@ -1,3 +1,20 @@
"""
This file is part of IDRB Project.
IDRB Project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IDRB Project is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with IDRB Project. If not, see <https://www.gnu.org/licenses/>.
"""
import dearpygui.dearpygui as dpg
from utils import *
@ -60,7 +77,7 @@ def window(self):
dpg.add_spacer()
dpg.add_text("IDRB (Internet Digital Radio Broadcasting System) Client")
dpg.add_spacer()
dpg.add_text(f"IDRB Client v1.6.1 Beta")
dpg.add_text(f"IDRB Client v1.6.2 Beta")
dpg.add_spacer()
desc = "IDRB is a novel internet radio broadcasting alternative that uses HLS/DASH/HTTP streams, transferring over TCP/IP. This system supports images and RDS (Dynamic update) capabilities, enabling the transmission of station information. Additionally, it allows for setting station logos and images. IDRB offers multi-broadcasting functionalities and currently supports the Opus codec, with plans to incorporate PCM, MP2/3, AAC/AAC+, and more in the future, ensuring low delay. If you find this project intriguing, you can support it at damp11113.xyz/support."
@ -148,8 +165,10 @@ def window(self):
dpg.add_text("Please restart software when configured")
with dpg.tab_bar():
with dpg.tab(label="Audio"):
dpg.add_combo([], label="Output Device", tag="selectaudiooutputdevicecombo",
callback=self.changeaudiodevice)
dpg.add_combo([], label="Output Device", tag="selectaudiooutputdevicecombo", callback=self.changeaudiodevice)
with dpg.tab(label="Network"):
dpg.add_input_int(label="Buffer Size", tag="buffersizeintinput", callback=self.changebuffersize)
def menubar(self):
with dpg.viewport_menu_bar():

View File

@ -40,8 +40,7 @@ class App:
self.config = configparser.ConfigParser()
self.config.read("config.ini")
self.device_name_output = self.config["audio"]["device"]
self.buffersize = 64 # can configable
self.buffersize = self.config["network"]["buffersize"]
self.working = False
self.readchannel = 1
@ -60,8 +59,6 @@ class App:
self.lsitem = None
self.ccconwithpubselect = False
self.buffer = queue.Queue(maxsize=self.buffersize)
self.okbuffer = False
self.firstrunbuffer = True
def connecttoserverwithpubselect(self, sender, data):
self.ccconwithpubselect = True
@ -125,8 +122,6 @@ class App:
dpg.configure_item("station_logo_config", show=False)
dpg.configure_item("RDSinfo", show=False)
dpg.configure_item("disconnectbutton", show=False)
dpg.configure_item("connectservergroup", show=True)
dpg.configure_item("serverstatus", default_value='disconnected', color=(255, 0, 0))
dpg.configure_item("logostatus", show=False)
self.firstrun = True
self.firststart = True
@ -136,9 +131,7 @@ class App:
self.ccisdecryptpassword = None
self.cciswaitlogoim = True
self.ccthreadlogorecisworking = False
self.buffer = queue.Queue(maxsize=self.buffersize)
self.okbuffer = False
self.firstrunbuffer = True
# clear buffer
def RDSshow(self):
try:
@ -231,6 +224,11 @@ class App:
self.config["audio"]["device"] = dpg.get_value(sender)
self.config.write(open('config.ini', 'w'))
def changebuffersize(self, sender, data):
self.buffersize = int(dpg.get_value(sender))
self.config["network"]["buffersize"] = str(dpg.get_value(sender))
self.config.write(open('config.ini', 'w'))
def pubserverselectone(self, sender, data):
if data == False:
dpg.configure_item("connectbuttonpubserverselect", show=False)
@ -295,9 +293,8 @@ class App:
self.pubserverselectsearch()
def streambuffer(self, socket):
consecutive_above_threshold = 0 # Counter to track consecutive iterations above threshold
tolerance_iterations = 5 # Number of consecutive iterations required above threshold
while self.working:
try:
if self.cprotocol == "TCP":
tempdata = b''
# data = socket.recv(1580152)
@ -307,13 +304,22 @@ class App:
if len(part) < 1024:
# either 0 or end of data
break
self.buffer.put(tempdata)
self.buffer.put(tempdata, timeout=0.1)
elif self.cprotocol == "ZeroMQ":
self.buffer.put(socket.recv())
self.buffer.put(socket.recv(), timeout=0.1)
else:
self.buffer.put(b"")
dpg.configure_item("bufferstatus", default_value=f'Buffer: {self.buffer.qsize()}/{self.buffersize}')
dpg.configure_item("bufferstatus", default_value=f'Buffer: {self.buffer.qsize()}/{self.buffersize}', color=(0, 255, 0))
except queue.Full:
dpg.configure_item("bufferstatus", default_value=f'Buffer: {self.buffer.qsize()}/{self.buffersize}', color=(255, 0, 0))
while not self.buffer.empty():
self.buffer.get()
dpg.configure_item("bufferstatus", default_value=f'Buffer: {self.buffer.qsize()}/{self.buffersize}', color=(255, 255, 0))
dpg.configure_item("serverstatus", default_value='disconnected', color=(255, 0, 0))
dpg.configure_item("connectservergroup", show=True)
def stream(self, socket):
opus_decoder = None
@ -339,6 +345,7 @@ class App:
if self.buffer.not_empty:
data = self.buffer.get()
else:
dpg.configure_item("serverstatus", default_value='Buffering...', color=(255, 255, 0))
continue
bytesconunt += len(data)
@ -589,7 +596,7 @@ class App:
ctypes.CDLL("opus.dll")
dpg.create_context()
dpg.create_viewport(title=f'IDRB Client v1.6.1 Beta', width=1280, height=720, large_icon="IDRBfavicon.ico", clear_color=(43, 45, 48)) # set viewport window
dpg.create_viewport(title=f'IDRB Client v1.6.2 Beta', width=1280, height=720, large_icon="IDRBfavicon.ico", clear_color=(43, 45, 48)) # set viewport window
dpg.setup_dearpygui()
# -------------- add code here --------------
noimage_texture_data = []
@ -621,6 +628,7 @@ class App:
output_devices.append(device_info['name'])
dpg.configure_item("selectaudiooutputdevicecombo", items=output_devices, default_value=self.config["audio"]["device"])
dpg.configure_item("buffersizeintinput", default_value=int(self.config["network"]["buffersize"]))
# -------------------------------------------
dpg.show_viewport()

View File

@ -1,6 +1,9 @@
[audio]
device = Speakers (2- USB Audio DAC )
[network]
buffersize = 128
[debug]
hideconsole = true

View File

@ -1,3 +1,20 @@
"""
This file is part of IDRB Project.
IDRB Project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IDRB Project is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with IDRB Project. If not, see <https://www.gnu.org/licenses/>.
"""
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import scrypt
import numpy as np

View File

@ -15,10 +15,17 @@ You should have received a copy of the GNU General Public License
along with IDRB Project. If not, see <https://www.gnu.org/licenses/>.
"""
# To config Muxer you need to goto server.py and find "Config Muxer"
# To config RDS you need to goto RDS.py
# To config Encoder you need to goto Encoder.py
# Do not goto ThaiSDRDir.py and utils.py
# Server Settings
protocol = "ZMQ_WS" # TCP ZMQ ZMQ_WS
server_port = ('*', 6980) # if use other protocol ZMQ please use 0.0.0.0
compression_level = 9 # 0-9
buffersize = 32 # must be int (on working it use buffersize + (buffersize/2) to standby)
# low buffersize = low delay
# Server Info
ServerName = "DPCloudev"
@ -40,4 +47,4 @@ public = True
ServerIP = "localhost"
#ServerPort = server_port[1]
ServerPort = 6980
ThaiSDRkey = "1N5LURICLIN1U9QNYZ4MHJ6FNXISFXFELZAX135CFM0HSD17O2.63E60BE9EEA2339C113A15EB"
ThaiSDRkey = ""

View File

@ -22,6 +22,8 @@ import threading
import zmq
import logging
import zlib
import queue
import math
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
ServerLog = logging.getLogger("IDRBServer")
@ -61,7 +63,6 @@ _RDS.startRDSThread()
ServerLog.info('starting audio encoding')
Encoder.StartEncoder()
if protocol == "TCP":
connected_users = 0
elif protocol == "ZMQ":
@ -74,9 +75,11 @@ timestart = time.time()
connectionlist = []
first = True
def handle_client():
global connected_users, first
try:
Buffer = queue.Queue(maxsize=math.trunc(Settings.buffersize + (Settings.buffersize/2)))
# ---------------------------------- Config Muxer ---------------------------------------
def Muxer():
while True:
# Get the encoded audio from the buffer
ENchannel1 = Encoder.channel1.get()
@ -118,34 +121,52 @@ def handle_client():
compressedcontent = zlib.compress(pickle.dumps(content), level=Settings.compression_level)
#connection.sendall(pickle.dumps(content))
Buffer.put(compressedcontent)
# -----------------------------------------------------------------------------------------------
def handle_client():
global connected_users, first
try:
while True:
# Check if the buffer queue has enough data to send
if Buffer.qsize() >= Settings.buffersize: # Adjust the threshold as needed
if protocol == "TCP":
for i in connectionlist:
try:
i.sendall(compressedcontent)
# Send data from the buffer queue to connected clients
for _ in range(Settings.buffersize):
i.sendall(Buffer.get())
except Exception as e:
#print(f'Error sending data to {i.getpeername()}: {e}')
# Remove disconnected client from the list
if i in connectionlist:
i.close()
connectionlist.remove(i)
connected_users -= 1
# check if no user
if not connectionlist:
first = True
ServerLog.info('server is standby now')
break
elif protocol == "ZMQ":
s.send(compressedcontent)
# Send data from the buffer queue to ZMQ socket
for _ in range(Settings.buffersize):
s.send(Buffer.get())
except Exception as e:
print(f'Error: {e}')
# Your main server logic using threading for handling connections
if __name__ == "__main__":
if public:
ServerLog.info('starting ThaiSDR Directory')
ThaiSDRDir.run()
ServerLog.info('server is running')
ServerLog.info('starting Muxer')
muxerthread = threading.Thread(target=Muxer)
muxerthread.start()
ServerLog.info('starting server')
if protocol == "TCP":
while True:
connection, client_address = s.accept()
@ -163,3 +184,5 @@ if __name__ == "__main__":
client_thread = threading.Thread(target=handle_client)
# client_thread.daemon = True # Set the thread as a daemon so it exits when the main thread exits
client_thread.start()
ServerLog.info('server is running')