@@ -104,15 +104,15 @@ def __init__(
104104
105105 def disconnect (self ) -> None :
106106 """Disconnect and/or cleanup socket client."""
107+ self ._connected = False
107108 if self ._reader_task and not self ._reader_task .done ():
108109 self ._reader_task .cancel ()
109110 if self ._heartbeat_task and not self ._heartbeat_task .done ():
110111 self ._heartbeat_task .cancel ()
111112
112- if self ._connected :
113- self ._connected = False
114- if self ._writer .can_write_eof ():
115- self ._writer .write_eof ()
113+ if self ._writer .can_write_eof ():
114+ self ._writer .write_eof ()
115+ if not self ._writer .is_closing ():
116116 self ._writer .close ()
117117
118118 async def configure_display (
@@ -388,7 +388,7 @@ async def play_url(
388388 but wait for the buffer to be full.
389389 - send_flush: advanced option to flush the buffer before playback.
390390 """
391- self .logger .debug ("play url: %s" , url )
391+ self .logger .debug ("play url (enqueue : %s): %s" , enqueue , url )
392392 if not url .startswith ("http" ):
393393 raise UnsupportedContentType (f"Invalid URL: { url } " ) # noqa: TRY003
394394
@@ -559,7 +559,7 @@ async def _send_heartbeat(self) -> None:
559559 replay_gain = heartbeat_id ,
560560 )
561561 await self ._render_display ()
562- await asyncio .sleep (5 )
562+ await asyncio .sleep (HEARTBEAT_INTERVAL )
563563
564564 async def _socket_reader (self ) -> None :
565565 """Handle incoming data from socket."""
@@ -569,7 +569,7 @@ async def _socket_reader(self) -> None:
569569 try :
570570 async with timeout (HEARTBEAT_INTERVAL * 2 ):
571571 data = await self ._reader .read (64 )
572- except TimeoutError :
572+ except ( TimeoutError , ConnectionResetError ) :
573573 break
574574 # handle incoming data from socket
575575 buffer = buffer + data
@@ -581,6 +581,8 @@ async def _socket_reader(self) -> None:
581581 if len (buffer ) >= plen :
582582 packet , buffer = buffer [8 :plen ], buffer [plen :]
583583 operation = operation .strip (b"!" ).strip ().decode ().lower ()
584+ if operation == "bye!" :
585+ break
584586 handler = getattr (self , f"_process_{ operation } " , None )
585587 if handler is None :
586588 self .logger .debug ("No handler for %s" , operation )
@@ -589,6 +591,7 @@ async def _socket_reader(self) -> None:
589591 else :
590592 asyncio .get_running_loop ().call_soon (handler , packet )
591593 # EOF reached: socket is disconnected
594+ self ._connected = False
592595 self .logger .debug (
593596 "Socket disconnected: %s" ,
594597 self ._writer .get_extra_info ("peername" ),
@@ -775,6 +778,10 @@ def _process_stat_stmc(self, data: bytes) -> None:
775778 self .logger .debug ("STMc received - connected." )
776779 # srtm-s command received. Guaranteed to be the first response to an strm-s.
777780 self ._state = PlayerState .BUFFERING
781+ self ._current_media = self ._next_media
782+ self ._next_media = None
783+ self .extra_data ["playlist_timestamp" ] = int (time .time ())
784+ self .signal_update ()
778785
779786 def _process_stat_stmd (self , data : bytes ) -> None :
780787 """Process incoming stat STMd message (decoder ready)."""
@@ -833,9 +840,6 @@ async def _process_stat_stms(self, data: bytes) -> None:
833840 """Process incoming stat STMs message: Playback of new track has started."""
834841 self .logger .debug ("STMs received - playback of new track has started" )
835842 self ._state = PlayerState .PLAYING
836- self ._current_media = self ._next_media
837- self ._next_media = None
838- self .extra_data ["playlist_timestamp" ] = int (time .time ())
839843 self .signal_update ()
840844 await self ._render_display ("playback_start" )
841845
@@ -925,7 +929,11 @@ async def _process_resp(self, data: bytes) -> None:
925929 await self .send_frame (b"codc" , codc_msg )
926930
927931 # parse ICY metadata
928- if "icy-name" in headers and not self .next_media .metadata .get ("title" ):
932+ if (
933+ "icy-name" in headers
934+ and self ._next_media
935+ and not self ._next_media .metadata .get ("title" )
936+ ):
929937 self ._next_media .metadata ["title" ] = headers ["icy-name" ]
930938
931939 # send continue (used when autoplay 1 or 3)
0 commit comments