11use std:: {
2- net:: { Ipv4Addr , SocketAddrV4 } ,
3- str:: FromStr ,
2+ net:: { Ipv4Addr , SocketAddrV4 , ToSocketAddrs } ,
43 sync:: { Arc , Mutex , RwLock } ,
54 time:: { Duration , Instant } ,
65} ;
@@ -38,22 +37,24 @@ mod rodio_out;
3837struct Cli {
3938 #[ arg(
4039 short,
40+ long,
4141 name = "SERVER[:PORT]" ,
4242 value_parser = cli_server_parser,
4343 help = "Connect to the specified server, otherwise use autodiscovery" ) ]
4444 server : Option < SocketAddrV4 > ,
4545
4646 #[ arg(
4747 short = 'o' ,
48+ long,
4849 name = "OUTPUT_DEVICE" ,
4950 help = "Output device [default: System default device]"
5051 ) ]
5152 device : Option < String > ,
5253
53- #[ arg( short, help = "List output devices" ) ]
54+ #[ arg( short, long , help = "List output devices" ) ]
5455 list : bool ,
5556
56- #[ arg( short, default_value = "Vibe" , help = "Set the player name" ) ]
57+ #[ arg( short, long , default_value = "Vibe" , help = "Set the player name" ) ]
5758 name : String ,
5859
5960 #[ cfg( all( feature = "pulse" , feature = "rodio" ) ) ]
@@ -76,13 +77,40 @@ struct Cli {
7677}
7778
7879fn cli_server_parser ( value : & str ) -> anyhow:: Result < SocketAddrV4 > {
79- match value. split_once ( ':' ) {
80- Some ( ( ip_str, port_str) ) if port_str. len ( ) == 0 => {
81- Ok ( SocketAddrV4 :: new ( Ipv4Addr :: from_str ( ip_str) ?, SLIM_PORT ) )
80+ // Try parsing as SocketAddrV4 directly (ip:port or host:port)
81+ if let Ok ( addr) = value. parse :: < SocketAddrV4 > ( ) {
82+ return Ok ( addr) ;
83+ }
84+
85+ // Try parsing as Ipv4Addr (ip only, no port)
86+ if let Ok ( ip) = value. parse :: < Ipv4Addr > ( ) {
87+ return Ok ( SocketAddrV4 :: new ( ip, SLIM_PORT ) ) ;
88+ }
89+
90+ // Try parsing as host[:port]
91+ let mut parts = value. rsplitn ( 2 , ':' ) ;
92+ let last = parts. next ( ) ;
93+ let first = parts. next ( ) ;
94+
95+ let ( host, port) = match ( first, last) {
96+ ( Some ( host) , Some ( port_str) ) if port_str. chars ( ) . all ( |c| c. is_ascii_digit ( ) ) => {
97+ let port = port_str. parse :: < u16 > ( ) . unwrap_or ( SLIM_PORT ) ;
98+ ( host, port)
99+ }
100+ ( Some ( _) , Some ( _) ) => ( value, SLIM_PORT ) ,
101+ ( None , Some ( host) ) => ( host, SLIM_PORT ) ,
102+ _ => ( value, SLIM_PORT ) ,
103+ } ;
104+
105+ // Use ToSocketAddrs to resolve host
106+ let addrs = ( host, port) . to_socket_addrs ( ) ?;
107+ for addr in addrs {
108+ if let std:: net:: SocketAddr :: V4 ( addr_v4) = addr {
109+ return Ok ( addr_v4) ;
82110 }
83- Some ( _) => Ok ( value. parse ( ) ?) ,
84- None => Ok ( SocketAddrV4 :: new ( Ipv4Addr :: from_str ( value) ?, SLIM_PORT ) ) ,
85111 }
112+
113+ Err ( anyhow:: anyhow!( "Could not resolve server address" ) )
86114}
87115
88116pub struct StreamParams {
0 commit comments