Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
nsrCodes committed Feb 26, 2022
0 parents commit 33a501d
Show file tree
Hide file tree
Showing 12 changed files with 1,033 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "spur"
version = "0.1.0"
edition = "2021"

[dependencies]
clap = { version = "3.1.2", features = ["derive"] }
x11rb = { version = "0.9.0", features = ["cursor"] }
scrap = "0.5.0"
v4l = {version = "0.12.1", features = ["v4l2-sys"] }
gstreamer = "0.17.4"
gstreamer-video = "0.17.2"
num-rational = "0.4.0"
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# spur
Simple recorder with webcam overlay

4 changes: 4 additions & 0 deletions src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub const AUTHOR: &str = "nsrCodes";
pub const DESCRIPTION: &str = "Make easily sharable recordings with ease";
pub const CMD: &str = "spur";
pub const VERSION: &str = "0.1.0";
100 changes: 100 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use clap::Arg;
use options::{FrameRate, Quality, SType};
pub mod constants;
pub mod options;
pub mod overlay;
pub mod parser;
pub mod recorder;
pub mod session;
pub mod streamer;

#[derive(Debug)]
pub enum CustomError {
InvalidAnswer,
}

#[derive(Debug)]
pub enum ThreadMessages {
StopPipeline,
StartPipeline,
PipelineStoped,
PipelineStarted,
}

/*Config*/
#[derive(Debug, Clone)]
pub struct Config {
pub s_type: SType,
pub name: String,
pub cmd: &'static str,
pub path: &'static str,
pub quality: Quality,
pub framerate: FrameRate,
pub overlay: bool,
}

impl Config {
pub fn new(st: SType) -> Self {
let (name, path) = match st {
// Make tis a function
SType::Record => (SType::to_string(&SType::Record), "rtmp://someendpoint:1935"),
SType::Stream => (SType::to_string(&SType::Stream), "my-demo.mkv"),
};
Config {
cmd: constants::CMD,
name,
path,
framerate: FrameRate::default(),
quality: Quality::default(),
overlay: overlay::default(),
s_type: st,
}
}
pub fn update_session_type(&mut self, st: SType) {
self.s_type = st;
let (name, path) = match st {
SType::Record => (SType::to_string(&SType::Record), "rtmp://someendpoint:1935"),
SType::Stream => (SType::to_string(&SType::Stream), "my-demo.mkv"),
};
self.name = name;
self.path = path;
}
pub fn create_path_arg<'a>(&self) -> Arg<'a> {
Arg::new("path")
.long("path")
.takes_value(self.s_type == SType::Record)
.default_value(self.path)
.help("Set path of recording")
}

pub fn create_list_arg<'a>() -> Arg<'a> {
Arg::new("list")
.long("list")
.short('l')
.takes_value(false)
.help("Lists info of past recordings")
}
pub fn create_config_arg<'a>() -> Arg<'a> {
Arg::new("config")
.long("config")
.short('c')
.takes_value(false)
.help("Show current config settings")
}
}
/*Media*/
pub trait Media {
fn new(config: Config) -> Self
where
Self: Sized;
fn start_pipeline(&mut self);
fn stop_stream(&self);
fn cancel_stream(&self);
fn create_pipeline(&mut self);
}

impl Default for Config {
fn default() -> Self {
Config::new(SType::default())
}
}
18 changes: 18 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use spur::parser::create_session_from_args;
use std::{io, thread};
fn main() {
let mut current_session = create_session_from_args();
current_session.start();
// Input
let mut input = String::new();
let main_handler = thread::spawn(move || loop {
if input == String::from("end\n") {
current_session.end();
break;
}
input = String::new();
io::stdin().read_line(&mut input).unwrap();
// current_session.execute(&input);
});
main_handler.join().unwrap();
}
156 changes: 156 additions & 0 deletions src/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
use crate::CustomError;
use clap::Arg;
use std::str::FromStr;
pub trait MetaOption {
const COMMAND_NAME: &'static str;
fn values() -> [&'static str; 2];
fn create_arg<'a>() -> Arg<'a>;
}

/** Quality */
#[derive(Debug, Clone, Copy)]
pub enum Quality {
Q720 = 720,
Q1080 = 1080,
}
impl Default for Quality {
fn default() -> Self {
Quality::Q720
}
}

impl FromStr for Quality {
type Err = CustomError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"720" => Ok(Quality::Q720),
"1080" => Ok(Quality::Q1080),
_ => Err(CustomError::InvalidAnswer),
}
}
}

impl ToString for Quality {
fn to_string(&self) -> String {
match self {
&Self::Q720 => String::from("720"),
&Self::Q1080 => String::from("1080"),
}
}
}
impl MetaOption for Quality {
const COMMAND_NAME: &'static str = "quality";
fn values() -> [&'static str; 2] {
["720", "1080"]
}

fn create_arg<'a>() -> Arg<'a> {
Arg::new(Self::COMMAND_NAME)
.long(Self::COMMAND_NAME)
.takes_value(true)
.default_value("720")
.required(false)
.help("The quality of the recording")
}
}

/** Framerate */
#[derive(Debug, Clone, Copy)]
pub enum FrameRate {
F24 = 24 as isize,
F30 = 30 as isize,
}

impl Default for FrameRate {
fn default() -> Self {
FrameRate::F24
}
}

impl FromStr for FrameRate {
type Err = CustomError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"24" => Ok(FrameRate::F24),
"30" => Ok(FrameRate::F30),
_ => Err(CustomError::InvalidAnswer),
}
}
}

impl ToString for FrameRate {
fn to_string(&self) -> String {
match self {
&Self::F24 => String::from("24"),
&Self::F30 => String::from("30"),
}
}
}

impl MetaOption for FrameRate {
const COMMAND_NAME: &'static str = "framerate";
fn values() -> [&'static str; 2] {
["24", "30"]
}

fn create_arg<'a>() -> Arg<'a> {
Arg::new(Self::COMMAND_NAME)
.long(Self::COMMAND_NAME)
.takes_value(true)
.default_value("24")
.required(false)
.help("Framerate of recording")
}
}

/** Type */
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum SType {
Record = 0,
Stream = 1,
}

impl Default for SType {
fn default() -> Self {
SType::Stream
}
}

impl FromStr for SType {
type Err = CustomError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"record" => Ok(SType::Record),
"stream" => Ok(SType::Stream),
_ => Err(CustomError::InvalidAnswer),
}
}
}

impl ToString for SType {
fn to_string(&self) -> String {
match self {
&Self::Record => String::from("record"),
&Self::Stream => String::from("stream"),
}
}
}
impl MetaOption for SType {
const COMMAND_NAME: &'static str = "session";
fn values() -> [&'static str; 2] {
const SUB_COMMANDS: [&'static str; 2] = ["record", "stream"];
SUB_COMMANDS
}

fn create_arg<'a>() -> Arg<'a> {
Arg::new(Self::COMMAND_NAME)
.long(Self::COMMAND_NAME)
.takes_value(true)
.default_value("record")
.required(false)
.help("Wether to stream to server or store to storage")
}
}
Loading

0 comments on commit 33a501d

Please sign in to comment.