update to the (unreleased) version of servicepoint
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Rust / build (pull_request) Successful in 7m29s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Rust / build (pull_request) Successful in 7m29s
				
			This commit is contained in:
		
							parent
							
								
									a903cbed85
								
							
						
					
					
						commit
						2efe86a592
					
				
					 10 changed files with 79 additions and 68 deletions
				
			
		
							
								
								
									
										3
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -1702,8 +1702,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "servicepoint" | ||||
| version = "0.13.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "33abd53582a995aaf5d387be4a1f7eb294a084185f88f8cf61652b6272041660" | ||||
| source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#300bb5d6474f0f6152ab04feed4478995fcb3ec8" | ||||
| dependencies = [ | ||||
|  "bitvec", | ||||
|  "log", | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ homepage = "https://crates.io/crates/servicepoint-cli" | |||
| keywords = ["cccb", "cccb-servicepoint", "cli"] | ||||
| 
 | ||||
| [dependencies] | ||||
| servicepoint = { version = "0.13.2", features = ["protocol_websocket"] } | ||||
| servicepoint = {features = ["protocol_websocket"] , git = "https://git.berlin.ccc.de/servicepoint/servicepoint/", branch = "next"} | ||||
| clap = { version = "4.5", features = ["derive"] } | ||||
| env_logger = "0.11" | ||||
| log = "0.4" | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| use crate::cli::BrightnessCommand; | ||||
| use log::info; | ||||
| use servicepoint::{Brightness, Command, Connection}; | ||||
| use servicepoint::{Brightness, Connection}; | ||||
| 
 | ||||
| pub(crate) fn brightness(connection: &Connection, brightness_command: BrightnessCommand) { | ||||
| pub(crate) fn brightness(connection: &impl Connection, brightness_command: BrightnessCommand) { | ||||
|     match brightness_command { | ||||
|         BrightnessCommand::Max => brightness_set(connection, Brightness::MAX), | ||||
|         BrightnessCommand::Min => brightness_set(connection, Brightness::MIN), | ||||
|  | @ -12,9 +12,9 @@ pub(crate) fn brightness(connection: &Connection, brightness_command: Brightness | |||
|     } | ||||
| } | ||||
| 
 | ||||
| pub(crate) fn brightness_set(connection: &Connection, brightness: Brightness) { | ||||
| pub(crate) fn brightness_set(connection: &impl Connection, brightness: Brightness) { | ||||
|     connection | ||||
|         .send(Command::Brightness(brightness)) | ||||
|         .send(servicepoint::BrightnessCommand::from(brightness)) | ||||
|         .expect("Failed to set brightness"); | ||||
|     info!("set brightness to {brightness:?}"); | ||||
| } | ||||
|  |  | |||
|  | @ -100,7 +100,7 @@ impl ImageProcessingPipeline { | |||
|         let result = if self.options.no_dither { | ||||
|             let cutoff = median_brightness(&orig); | ||||
|             let bits = orig.iter().map(move |x| x > &cutoff).collect(); | ||||
|             Bitmap::from_bitvec(orig.width() as usize, bits) | ||||
|             Bitmap::from_bitvec(orig.width() as usize, bits).unwrap() | ||||
|         } else { | ||||
|             ostromoukhov_dither(orig, u8::MAX / 2) | ||||
|         }; | ||||
|  | @ -113,7 +113,7 @@ impl ImageProcessingPipeline { | |||
| 
 | ||||
|         let width = source.width(); | ||||
|         let result_height = Self::calc_height_without_spacers(source.height()); | ||||
|         let mut result = Bitmap::new(width, result_height); | ||||
|         let mut result = Bitmap::new(width, result_height).unwrap(); | ||||
| 
 | ||||
|         let mut source_y = 0; | ||||
|         for result_y in 0..result_height { | ||||
|  |  | |||
|  | @ -200,7 +200,7 @@ pub(crate) fn ostromoukhov_dither(source: GrayImage, bias: u8) -> Bitmap { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Bitmap::from_bitvec(width as usize, destination) | ||||
|     Bitmap::from_bitvec(width as usize, destination).unwrap() | ||||
| } | ||||
| 
 | ||||
| #[inline] | ||||
|  |  | |||
							
								
								
									
										35
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -6,7 +6,7 @@ use crate::{ | |||
| }; | ||||
| use clap::Parser; | ||||
| use log::debug; | ||||
| use servicepoint::{Brightness, Connection}; | ||||
| use servicepoint::{Brightness, Connection, FakeConnection, UdpConnection, WebsocketConnection}; | ||||
| 
 | ||||
| mod brightness; | ||||
| mod cli; | ||||
|  | @ -22,13 +22,23 @@ fn main() { | |||
|     init_logging(cli.verbose); | ||||
|     debug!("running with arguments: {:?}", cli); | ||||
| 
 | ||||
|     let connection = make_connection(cli.destination, cli.transport); | ||||
|     debug!("connection established: {:#?}", connection); | ||||
| 
 | ||||
|     execute_mode(cli.command, connection); | ||||
|     
 | ||||
|     match cli.transport { | ||||
|         Protocol::Udp => { | ||||
|             let connection = UdpConnection::open(cli.destination).expect("Failed to open UDP connection"); | ||||
|             execute_mode(cli.command, connection);}, | ||||
|         Protocol::WebSocket => { | ||||
|             let url = cli.destination.parse().expect( | ||||
|                 "provided destination is not a valid url - make sure it starts with 'ws://'", | ||||
|             ); | ||||
|             let connection = WebsocketConnection::open(url).expect("Failed to open WebSocket connection"); | ||||
|             execute_mode(cli.command, connection); | ||||
|         } | ||||
|         Protocol::Fake => execute_mode(cli.command, FakeConnection), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn execute_mode(mode: Mode, connection: Connection) { | ||||
| pub fn execute_mode(mode: Mode, connection: impl Connection) { | ||||
|     match mode { | ||||
|         Mode::ResetEverything => { | ||||
|             brightness_set(&connection, Brightness::MAX); | ||||
|  | @ -40,19 +50,6 @@ pub fn execute_mode(mode: Mode, connection: Connection) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_connection(destination: String, transport: Protocol) -> Connection { | ||||
|     match transport { | ||||
|         Protocol::Udp => Connection::open(destination).expect("Failed to open UDP connection"), | ||||
|         Protocol::WebSocket => { | ||||
|             let url = destination.parse().expect( | ||||
|                 "provided destination is not a valid url - make sure it starts with 'ws://'", | ||||
|             ); | ||||
|             Connection::open_websocket(url).expect("Failed to open WebSocket connection") | ||||
|         } | ||||
|         Protocol::Fake => Connection::Fake, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn init_logging(debug: bool) { | ||||
|     let filter = if debug { | ||||
|         log::LevelFilter::Debug | ||||
|  |  | |||
|  | @ -1,12 +1,15 @@ | |||
| use crate::{ | ||||
|     image_processing::ImageProcessingPipeline, | ||||
|     cli::{ImageProcessingOptions, PixelCommand, SendImageOptions}, | ||||
|     stream_window::stream_window | ||||
|     image_processing::ImageProcessingPipeline, | ||||
|     stream_window::stream_window, | ||||
| }; | ||||
| use log::info; | ||||
| use servicepoint::{BitVec, Command, CompressionCode, Connection, Origin, PIXEL_COUNT}; | ||||
| use servicepoint::{ | ||||
|     BinaryOperation, BitVec, BitVecCommand, BitmapCommand, ClearCommand, CompressionCode, | ||||
|     Connection, Origin, PIXEL_COUNT, | ||||
| }; | ||||
| 
 | ||||
| pub(crate) fn pixels(connection: &Connection, pixel_command: PixelCommand) { | ||||
| pub(crate) fn pixels(connection: &impl Connection, pixel_command: PixelCommand) { | ||||
|     match pixel_command { | ||||
|         PixelCommand::Off => pixels_off(connection), | ||||
|         PixelCommand::Flip => pixels_invert(connection), | ||||
|  | @ -22,31 +25,37 @@ pub(crate) fn pixels(connection: &Connection, pixel_command: PixelCommand) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| fn pixels_on(connection: &Connection) { | ||||
|     let mask = BitVec::repeat(true, PIXEL_COUNT); | ||||
|     connection | ||||
|         .send(Command::BitmapLinear(0, mask, CompressionCode::Lzma)) | ||||
|         .expect("could not send command"); | ||||
| fn pixels_on(connection: &impl Connection) { | ||||
|     let command = BitVecCommand { | ||||
|         offset: 0, | ||||
|         bitvec: BitVec::repeat(true, PIXEL_COUNT), | ||||
|         compression: CompressionCode::Lzma, | ||||
|         operation: BinaryOperation::Or, | ||||
|     }; | ||||
|     connection.send(command).expect("could not send command"); | ||||
|     info!("turned on all pixels") | ||||
| } | ||||
| 
 | ||||
| fn pixels_invert(connection: &Connection) { | ||||
|     let mask = BitVec::repeat(true, PIXEL_COUNT); | ||||
|     connection | ||||
|         .send(Command::BitmapLinearXor(0, mask, CompressionCode::Lzma)) | ||||
|         .expect("could not send command"); | ||||
| fn pixels_invert(connection: &impl Connection) { | ||||
|     let command = BitVecCommand { | ||||
|         offset: 0, | ||||
|         bitvec: BitVec::repeat(true, PIXEL_COUNT), | ||||
|         compression: CompressionCode::Lzma, | ||||
|         operation: BinaryOperation::Xor, | ||||
|     }; | ||||
|     connection.send(command).expect("could not send command"); | ||||
|     info!("inverted all pixels"); | ||||
| } | ||||
| 
 | ||||
| pub(crate) fn pixels_off(connection: &Connection) { | ||||
| pub(crate) fn pixels_off(connection: &impl Connection) { | ||||
|     connection | ||||
|         .send(Command::Clear) | ||||
|         .send(ClearCommand) | ||||
|         .expect("failed to clear pixels"); | ||||
|     info!("reset pixels"); | ||||
| } | ||||
| 
 | ||||
| fn pixels_image( | ||||
|     connection: &Connection, | ||||
|     connection: &impl Connection, | ||||
|     options: SendImageOptions, | ||||
|     processing_options: ImageProcessingOptions, | ||||
| ) { | ||||
|  | @ -54,11 +63,11 @@ fn pixels_image( | |||
|     let mut pipeline = ImageProcessingPipeline::new(processing_options); | ||||
|     let bitmap = pipeline.process(image); | ||||
|     connection | ||||
|         .send(Command::BitmapLinearWin( | ||||
|             Origin::ZERO, | ||||
|         .send(BitmapCommand { | ||||
|             origin: Origin::ZERO, | ||||
|             bitmap, | ||||
|             CompressionCode::default(), | ||||
|         )) | ||||
|             compression: CompressionCode::default(), | ||||
|         }) | ||||
|         .expect("failed to send image command"); | ||||
|     info!("sent image to display"); | ||||
| } | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ use log::warn; | |||
| use servicepoint::*; | ||||
| use std::thread::sleep; | ||||
| 
 | ||||
| pub(crate) fn stream_stdin(connection: &Connection, slow: bool) { | ||||
| pub(crate) fn stream_stdin(connection: &impl Connection, slow: bool) { | ||||
|     warn!("This mode will break when using multi-byte characters and does not support ANSI escape sequences yet."); | ||||
|     let mut app = App { | ||||
|         connection, | ||||
|  | @ -13,17 +13,17 @@ pub(crate) fn stream_stdin(connection: &Connection, slow: bool) { | |||
|     app.run() | ||||
| } | ||||
| 
 | ||||
| struct App<'t> { | ||||
|     connection: &'t Connection, | ||||
| struct App<'t, TConnection: Connection> { | ||||
|     connection: &'t TConnection, | ||||
|     mirror: CharGrid, | ||||
|     y: usize, | ||||
|     slow: bool, | ||||
| } | ||||
| 
 | ||||
| impl App<'_> { | ||||
| impl<TConnection: Connection> App<'_, TConnection> { | ||||
|     fn run(&mut self) { | ||||
|         self.connection | ||||
|             .send(Command::Clear) | ||||
|             .send(ClearCommand) | ||||
|             .expect("couldn't clear screen"); | ||||
|         let last_y = self.mirror.height() - 1; | ||||
|         for line in std::io::stdin().lines() { | ||||
|  | @ -62,11 +62,12 @@ impl App<'_> { | |||
|     } | ||||
| 
 | ||||
|     fn send_mirror(&self) { | ||||
|         let command = CharGridCommand { | ||||
|             origin: Origin::ZERO, | ||||
|             grid: self.mirror.clone(), | ||||
|         }; | ||||
|         self.connection | ||||
|             .send(Command::Utf8Data( | ||||
|                 Origin::ZERO, | ||||
|                 self.mirror.clone(), | ||||
|             )) | ||||
|             .send(command) | ||||
|             .expect("couldn't send screen to display"); | ||||
|     } | ||||
| 
 | ||||
|  | @ -75,8 +76,12 @@ impl App<'_> { | |||
|         line_grid.fill(' '); | ||||
|         Self::line_onto_grid(&mut line_grid, 0, line); | ||||
|         Self::line_onto_grid(&mut self.mirror, self.y, line); | ||||
|         let command = CharGridCommand { | ||||
|             origin: Origin::new(0, self.y), | ||||
|             grid: line_grid, | ||||
|         }; | ||||
|         self.connection | ||||
|             .send(Command::Utf8Data(Origin::new(0, self.y), line_grid)) | ||||
|             .send(command) | ||||
|             .expect("couldn't send single line to screen"); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -9,11 +9,11 @@ use scap::{ | |||
|     frame::convert_bgra_to_rgb, | ||||
|     frame::Frame, | ||||
| }; | ||||
| use servicepoint::{Command, CompressionCode, Connection, Origin, FRAME_PACING}; | ||||
| use servicepoint::{BitmapCommand, CompressionCode, Connection, Origin, FRAME_PACING}; | ||||
| use std::time::{Duration, Instant}; | ||||
| 
 | ||||
| pub fn stream_window( | ||||
|     connection: &Connection, | ||||
|     connection: &impl Connection, | ||||
|     options: StreamScreenOptions, | ||||
|     processing_options: ImageProcessingOptions, | ||||
| ) { | ||||
|  | @ -35,12 +35,13 @@ pub fn stream_window( | |||
| 
 | ||||
|         trace!("bitmap ready to send in: {:?}", start.elapsed()); | ||||
| 
 | ||||
|         let command = BitmapCommand { | ||||
|             compression: CompressionCode::default(), | ||||
|             bitmap: bitmap.clone(), | ||||
|             origin: Origin::ZERO, | ||||
|         }; | ||||
|         connection | ||||
|             .send(Command::BitmapLinearWin( | ||||
|                 Origin::ZERO, | ||||
|                 bitmap.clone(), | ||||
|                 CompressionCode::default(), | ||||
|             )) | ||||
|             .send(command) | ||||
|             .expect("failed to send frame to display"); | ||||
| 
 | ||||
|         debug!("frame time: {:?}", start.elapsed()); | ||||
|  |  | |||
|  | @ -2,6 +2,6 @@ use servicepoint::Connection; | |||
| use crate::cli::TextCommand; | ||||
| use crate::stream_stdin::stream_stdin; | ||||
| 
 | ||||
| pub fn text(connection: &Connection, command: TextCommand) { | ||||
| pub fn text(connection: &impl Connection, command: TextCommand) { | ||||
|    match command { TextCommand::Stdin  { slow } => stream_stdin(connection, slow), } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter