diff --git a/clients/terminal/src/fcastsession.rs b/clients/terminal/src/fcastsession.rs index 9680568..293d6de 100644 --- a/clients/terminal/src/fcastsession.rs +++ b/clients/terminal/src/fcastsession.rs @@ -1,6 +1,6 @@ use std::sync::{atomic::{AtomicBool, Ordering}, Arc}; -use crate::{models::{PlaybackUpdateMessage, VolumeUpdateMessage, PlaybackErrorMessage}, transport::Transport}; +use crate::{models::{PlaybackUpdateMessage, VolumeUpdateMessage, PlaybackErrorMessage, VersionMessage}, transport::Transport}; use serde::Serialize; #[derive(Debug)] @@ -23,7 +23,8 @@ pub enum Opcode { VolumeUpdate = 7, SetVolume = 8, PlaybackError = 9, - SetSpeed = 10 + SetSpeed = 10, + Version = 11 } impl Opcode { @@ -40,6 +41,7 @@ impl Opcode { 8 => Opcode::SetVolume, 9 => Opcode::PlaybackError, 10 => Opcode::SetSpeed, + 11 => Opcode::Version, _ => panic!("Unknown value: {}", value), } } @@ -219,6 +221,13 @@ impl FCastSession<'_> { } } } + Opcode::Version => { + if let Some(body_str) = body { + if let Ok(version_msg) = serde_json::from_str::(body_str) { + println!("Received version {:?}", version_msg); + } + } + } _ => { println!("Error handling packet"); } diff --git a/clients/terminal/src/models.rs b/clients/terminal/src/models.rs index b048516..8c60bbe 100644 --- a/clients/terminal/src/models.rs +++ b/clients/terminal/src/models.rs @@ -64,4 +64,9 @@ impl SetSpeedMessage { #[derive(Deserialize, Debug)] pub struct PlaybackErrorMessage { pub message: String, +} + +#[derive(Deserialize, Debug)] +pub struct VersionMessage { + pub version: u64, } \ No newline at end of file diff --git a/receivers/android/app/src/main/java/com/futo/fcast/receiver/FCastSession.kt b/receivers/android/app/src/main/java/com/futo/fcast/receiver/FCastSession.kt index bb3f6e1..c68bf02 100644 --- a/receivers/android/app/src/main/java/com/futo/fcast/receiver/FCastSession.kt +++ b/receivers/android/app/src/main/java/com/futo/fcast/receiver/FCastSession.kt @@ -28,7 +28,8 @@ enum class Opcode(val value: Byte) { VolumeUpdate(7), SetVolume(8), PlaybackError(9), - SetSpeed(10) + SetSpeed(10), + Version(11) } const val LENGTH_BYTES = 4 @@ -42,6 +43,10 @@ class FCastSession(outputStream: OutputStream, private val _remoteSocketAddress: private var _outputStream: DataOutputStream? = DataOutputStream(outputStream) val id = UUID.randomUUID() + fun sendVersion(value: VersionMessage) { + send(Opcode.Version, value) + } + fun sendPlaybackError(value: PlaybackErrorMessage) { send(Opcode.PlaybackError, value) } @@ -190,13 +195,13 @@ class FCastSession(outputStream: OutputStream, private val _remoteSocketAddress: try { when (opcode) { - Opcode.Play -> _service.onCastPlay(Json.decodeFromString(body!!)) + Opcode.Play -> _service.onCastPlay(json.decodeFromString(body!!)) Opcode.Pause -> _service.onCastPause() Opcode.Resume -> _service.onCastResume() Opcode.Stop -> _service.onCastStop() - Opcode.Seek -> _service.onCastSeek(Json.decodeFromString(body!!)) - Opcode.SetVolume -> _service.onSetVolume(Json.decodeFromString(body!!)) - Opcode.SetSpeed -> _service.onSetSpeed(Json.decodeFromString(body!!)) + Opcode.Seek -> _service.onCastSeek(json.decodeFromString(body!!)) + Opcode.SetVolume -> _service.onSetVolume(json.decodeFromString(body!!)) + Opcode.SetSpeed -> _service.onSetSpeed(json.decodeFromString(body!!)) else -> { } } } catch (e: Throwable) { @@ -206,5 +211,6 @@ class FCastSession(outputStream: OutputStream, private val _remoteSocketAddress: companion object { const val TAG = "FCastSession" + private val json = Json { ignoreUnknownKeys = true } } } \ No newline at end of file diff --git a/receivers/android/app/src/main/java/com/futo/fcast/receiver/NetworkService.kt b/receivers/android/app/src/main/java/com/futo/fcast/receiver/NetworkService.kt index b53cb2c..7c27837 100644 --- a/receivers/android/app/src/main/java/com/futo/fcast/receiver/NetworkService.kt +++ b/receivers/android/app/src/main/java/com/futo/fcast/receiver/NetworkService.kt @@ -60,6 +60,15 @@ class NetworkService : Service() { _scope?.launch(Dispatchers.Main) { Log.i(TAG, "On new session ${session.id}") + withContext(Dispatchers.IO) { + try { + Log.i(TAG, "Sending version ${session.id}") + session.sendVersion(VersionMessage(2)) + } catch (e: Throwable) { + Log.e(TAG, "Failed to send version ${session.id}") + } + } + var encounteredError = false while (!_stopped && !encounteredError) { try { diff --git a/receivers/android/app/src/main/java/com/futo/fcast/receiver/Packets.kt b/receivers/android/app/src/main/java/com/futo/fcast/receiver/Packets.kt index 1910dcf..44e37aa 100644 --- a/receivers/android/app/src/main/java/com/futo/fcast/receiver/Packets.kt +++ b/receivers/android/app/src/main/java/com/futo/fcast/receiver/Packets.kt @@ -44,4 +44,9 @@ data class SetSpeedMessage( @Serializable data class SetVolumeMessage( val volume: Double +) + +@Serializable +data class VersionMessage( + val version: Long ) \ No newline at end of file diff --git a/receivers/electron/src/FCastSession.ts b/receivers/electron/src/FCastSession.ts index 942c35d..44de7e6 100644 --- a/receivers/electron/src/FCastSession.ts +++ b/receivers/electron/src/FCastSession.ts @@ -1,6 +1,6 @@ import net = require('net'); import { EventEmitter } from 'node:events'; -import { PlaybackErrorMessage, PlaybackUpdateMessage, PlayMessage, SeekMessage, SetSpeedMessage, SetVolumeMessage, VolumeUpdateMessage } from './Packets'; +import { PlaybackErrorMessage, PlaybackUpdateMessage, PlayMessage, SeekMessage, SetSpeedMessage, SetVolumeMessage, VersionMessage, VolumeUpdateMessage } from './Packets'; import { WebSocket } from 'ws'; enum SessionState { @@ -21,7 +21,8 @@ enum Opcode { VolumeUpdate = 7, SetVolume = 8, PlaybackError = 9, - SetSpeed = 10 + SetSpeed = 10, + Version = 11 }; const LENGTH_BYTES = 4; @@ -42,6 +43,10 @@ export class FCastSession { this.state = SessionState.WaitingForLength; } + sendVersion(value: VersionMessage) { + this.send(Opcode.Version, value); + } + sendPlaybackError(value: PlaybackErrorMessage) { this.send(Opcode.PlaybackError, value); } diff --git a/receivers/electron/src/Packets.ts b/receivers/electron/src/Packets.ts index 2e9de9b..f907493 100644 --- a/receivers/electron/src/Packets.ts +++ b/receivers/electron/src/Packets.ts @@ -47,4 +47,10 @@ export class SetSpeedMessage { constructor( public speed: number, ) {} +} + +export class VersionMessage { + constructor( + public version: number, + ) {} } \ No newline at end of file diff --git a/receivers/electron/src/TcpListenerService.ts b/receivers/electron/src/TcpListenerService.ts index 7ea00d6..f97a446 100644 --- a/receivers/electron/src/TcpListenerService.ts +++ b/receivers/electron/src/TcpListenerService.ts @@ -125,5 +125,12 @@ export class TcpListenerService { this.sessions.splice(index, 1); } }); + + try { + console.log('Sending version'); + session.sendVersion({version: 2}); + } catch (e) { + console.log('Failed to send version'); + } } } \ No newline at end of file diff --git a/receivers/electron/src/WebSocketListenerService.ts b/receivers/electron/src/WebSocketListenerService.ts index 25fa252..44d0135 100644 --- a/receivers/electron/src/WebSocketListenerService.ts +++ b/receivers/electron/src/WebSocketListenerService.ts @@ -1,4 +1,3 @@ -import net = require('net'); import { FCastSession } from './FCastSession'; import { EventEmitter } from 'node:events'; import { PlaybackErrorMessage, PlaybackUpdateMessage, PlayMessage, SeekMessage, SetSpeedMessage, SetVolumeMessage, VolumeUpdateMessage } from './Packets'; @@ -131,5 +130,12 @@ export class WebSocketListenerService { this.sessions.splice(index, 1); } }); + + try { + console.log('Sending version'); + session.sendVersion({version: 2}); + } catch (e) { + console.log('Failed to send version'); + } } } \ No newline at end of file