From e2b7f53da1b33fb25f0ca9eb64a484fc8c706834 Mon Sep 17 00:00:00 2001 From: Zastian Pretorius Date: Tue, 22 Nov 2022 20:20:49 +0000 Subject: [PATCH] added Chrome cast --- Cargo.lock | 156 +++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/anime/anime.rs | 23 +++++-- src/anime/player.rs | 70 ++++++++++++++++++++ src/main.rs | 17 ++++- 5 files changed, 259 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 441a251..639d002 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,6 +51,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "bytes" version = "1.1.0" @@ -209,6 +215,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -239,6 +251,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -370,6 +397,7 @@ dependencies = [ "dirs", "isahc", "regex", + "rust_cast", "serde_json", "termsize", "tui", @@ -481,6 +509,32 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +[[package]] +name = "openssl" +version = "0.10.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -489,9 +543,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg", "cc", @@ -589,6 +643,43 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protobuf" +version = "2.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96" + +[[package]] +name = "protobuf-codegen" +version = "2.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aec1632b7c8f2e620343439a7dfd1f3c47b18906c4be58982079911482b5d707" +dependencies = [ + "protobuf", +] + +[[package]] +name = "protoc" +version = "2.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ef1dc036942fac2470fdb8a911f125404ee9129e9e807f3d12d8589001a38f" +dependencies = [ + "log", + "which", +] + +[[package]] +name = "protoc-rust" +version = "2.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9e315121c8e7e21396e940a3d27f92280a6d28e3931213bf6cbfea76c5cc94" +dependencies = [ + "protobuf", + "protobuf-codegen", + "protoc", + "tempfile", +] + [[package]] name = "quote" version = "1.0.18" @@ -644,6 +735,31 @@ version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "rust_cast" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae2f46d9800706b729d86ef2f4c78e5920b56f56e720b440b311115081f413d" +dependencies = [ + "byteorder", + "log", + "openssl", + "protobuf", + "protoc-rust", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "ryu" version = "1.0.11" @@ -672,6 +788,17 @@ version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2" +[[package]] +name = "serde_derive" +version = "1.0.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_json" version = "1.0.83" @@ -757,6 +884,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.9", +] + [[package]] name = "termion" version = "1.5.6" @@ -945,6 +1086,17 @@ dependencies = [ "cc", ] +[[package]] +name = "which" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "winapi" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index 0b5c891..936a6fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,4 @@ serde_json = "1.0.83" tui = "0.18.0" crossterm = "0.24.0" unicode-width = "0.1.9" +rust_cast = "0.17.0" diff --git a/src/anime/anime.rs b/src/anime/anime.rs index 1958cf5..53908ee 100644 --- a/src/anime/anime.rs +++ b/src/anime/anime.rs @@ -1,9 +1,9 @@ -use crate::open_video; use crate::{anime_link, anime_names}; use crate::{ get_an_progress, get_anime_id, get_user_anime_progress, update_anime_progress, write_an_progress, }; +use crate::{open_cast, open_video}; use crossterm::{ event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, @@ -93,6 +93,7 @@ struct App { anime_id: i32, token: String, provider: String, + cast: (bool, String), } impl<'a> App { @@ -107,11 +108,16 @@ impl<'a> App { anime_id: 0, token: String::new(), provider: String::new(), + cast: (false, "0".to_string()), } } } -pub fn anime_ui(token: String, provider: String) -> Result<(), Box> { +pub fn anime_ui( + token: String, + provider: String, + cast: (bool, String), +) -> Result<(), Box> { // setup terminal enable_raw_mode()?; let mut stdout = io::stdout(); @@ -123,6 +129,7 @@ pub fn anime_ui(token: String, provider: String) -> Result<(), Box> { let mut app = App::default(); app.token = token; app.provider = provider; + app.cast = cast; let res = run_app(&mut terminal, app); // restore terminal @@ -180,7 +187,11 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( } if anime_info.1 == 1 { let link = anime_link(&app.title, 1, &app.provider); - open_video((link.0, link.1)); + if !app.cast.0 { + open_video((link.0, link.1)); + } else { + open_cast((link.0, link.1), &app.cast.1) + } if app.token == "local" || app.anime_id == 0 { write_an_progress(&app.title, &1); } else { @@ -203,7 +214,11 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( .parse::() .unwrap(); let link = anime_link(&app.title, app.ep, &app.provider); - open_video((link.0, link.1)); + if !app.cast.0 { + open_video((link.0, link.1)); + } else { + open_cast((link.0, link.1), &app.cast.1) + } if app.ep > app.progress as u64 { if app.token == "local" || app.anime_id == 0 { write_an_progress(&app.title, &app.ep); diff --git a/src/anime/player.rs b/src/anime/player.rs index b63b7c3..665d777 100644 --- a/src/anime/player.rs +++ b/src/anime/player.rs @@ -1,3 +1,13 @@ +extern crate rust_cast; +use rust_cast::{ + channels::{ + media::{Media, StreamType}, + receiver::CastDeviceApp, + }, + CastDevice, +}; +use std::str::FromStr; + pub fn open_video(link: (String, String)) { let title = link.1; let title = title.replace("-", " "); @@ -10,3 +20,63 @@ pub fn open_video(link: (String, String)) { // clear terminal } + +const DEFAULT_DESTINATION_ID: &str = "receiver-0"; +fn play_media( + device: &CastDevice, + app_to_run: &CastDeviceApp, + media: String, + media_type: String, + media_stream_type: StreamType, +) { + let app = device.receiver.launch_app(app_to_run).unwrap(); + + device + .connection + .connect(app.transport_id.as_str()) + .unwrap(); + + let _status = device + .media + .load( + app.transport_id.as_str(), + app.session_id.as_str(), + &Media { + content_id: media, + content_type: media_type, + stream_type: media_stream_type, + duration: None, + metadata: None, + }, + ) + .unwrap(); +} + +pub fn open_cast(link: (String, String), ip: &str) { + let cast_device = match CastDevice::connect_without_host_verification(ip, 8009) { + Ok(cast_device) => cast_device, + Err(err) => panic!("Could not establish connection with Cast Device: {:?}", err), + }; + + cast_device + .connection + .connect(DEFAULT_DESTINATION_ID.to_string()) + .unwrap(); + cast_device.heartbeat.ping().unwrap(); + + // Play media and keep connection. + + let media_stream_type = match "none" { + value @ "buffered" | value @ "live" | value @ "none" => { + StreamType::from_str(value).unwrap() + } + _ => panic!("Unsupported stream type!"), + }; + play_media( + &cast_device, + &CastDeviceApp::from_str("default").unwrap(), + link.0.to_string(), + "".to_string(), + media_stream_type, + ); +} diff --git a/src/main.rs b/src/main.rs index 7f925da..819acc9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use colored::Colorize; use ln::ln::ln_ui; use crate::anime::{ - player::open_video, + player::{open_cast, open_video}, scraper::{anime_link, anime_names}, trackers::*, }; @@ -22,6 +22,7 @@ fn main() { //let search = option string let mut count = 0; let mut provider: String = "gogo".to_string(); + let mut cast = (false, "0".to_string()); for arg in std::env::args() { if arg == "--help" || arg == "-h" { help = true; @@ -45,6 +46,13 @@ fn main() { provider = "vrv".to_string(); } } + if arg == "--cast" || arg == "-C" { + if let Some(arg) = std::env::args().nth(count + 1) { + cast = (true, String::from(arg)) + } else { + println!("{}", "please provide a ip address".red()) + } + } if arg == "--ln" || arg == "-l" { ln = true; @@ -85,7 +93,7 @@ fn main() { //anime_stream(search, episode, resume); let token = get_token(); - _ = anime_ui(token, provider); + _ = anime_ui(token, provider, cast); } else { println!("Invalid argument"); } @@ -95,6 +103,11 @@ fn print_help() { println!("anime:\t\t{}", format_args!("{}", "-a --anime".red())); //print blank line println!(""); + println!( + "cast:\t\t{}", + format_args!("{} {}", "-C --cast".red(), "".green()) + ); + println!(""); println!("light novel:\t{}", format_args!("{}", "-l --ln".red())); //print blank line println!("");