Skip to content

Commit

Permalink
Print useful messages if stream is offline/ends
Browse files Browse the repository at this point in the history
  • Loading branch information
2bc4 committed Jan 4, 2024
1 parent 44df46f commit 98ab579
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 19 deletions.
25 changes: 22 additions & 3 deletions src/hls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
time::{Duration, Instant},
};

use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, bail, Context, Result};
use log::{debug, error, info};
use rand::{
distributions::{Alphanumeric, DistString},
Expand All @@ -15,7 +15,10 @@ use rand::{
use serde_json::{json, Value};
use url::Url;

use crate::{constants, http::TextRequest};
use crate::{
constants,
http::{self, TextRequest},
};

#[derive(Debug)]
pub enum Error {
Expand Down Expand Up @@ -212,6 +215,11 @@ pub fn fetch_proxy_playlist(servers: &[String], channel: &str, quality: &str) ->
match request.text() {
Ok(playlist_url) => Some(playlist_url),
Err(e) => {
if http::Error::is_not_found(&e) {
error!("Playlist not found. Stream offline?");
return None;
}

error!("{e}");
None
}
Expand Down Expand Up @@ -293,7 +301,18 @@ pub fn fetch_twitch_playlist(
],
)?;

parse_variant_playlist(&TextRequest::get(&url)?.text()?, quality)
let master_playlist = match TextRequest::get(&url)?.text() {
Ok(master_playlist) => master_playlist,
Err(e) => {
if http::Error::is_not_found(&e) {
bail!("Stream offline");
}

return Err(e);
}
};

parse_variant_playlist(&master_playlist, quality)
}

fn parse_variant_playlist(master_playlist: &str, quality: &str) -> Result<Url> {
Expand Down
18 changes: 13 additions & 5 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,26 @@ use crate::{constants, ARGS};
#[derive(Debug)]
pub enum Error {
Status(u32, String),
NotFound(String),
}

impl std::error::Error for Error {}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Status(code, url) => write!(f, "Status code {code} on {url}"),
Self::Status(code, url) => write!(f, "{code} on {url}"),
Self::NotFound(url) => write!(f, "{url} not found"),
}
}
}

impl Error {
pub fn is_not_found(error: &anyhow::Error) -> bool {
matches!(error.downcast_ref::<Self>(), Some(Self::NotFound(_)))
}
}

pub struct RawRequest<T>
where
T: Write,
Expand Down Expand Up @@ -178,9 +186,9 @@ fn perform<T: Write>(handle: &Easy2<RequestHandler<T>>) -> Result<()> {
handle.get_ref().check_error()?;

let code = handle.response_code()?;
if code != 200 {
return Err(Error::Status(code, handle.effective_url()?.unwrap().to_owned()).into());
match code {
200 => Ok(()),
404 => Err(Error::NotFound(handle.effective_url()?.unwrap().to_owned()).into()),
_ => Err(Error::Status(code, handle.effective_url()?.unwrap().to_owned()).into()),
}

Ok(())
}
31 changes: 20 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ use once_cell::sync::OnceCell;
use simplelog::{format_description, ColorChoice, ConfigBuilder, LevelFilter, TermLogger, TerminalMode};

use args::Args;
use hls::{Error as HlsErr, MediaPlaylist, PrefetchUrlKind};
use hls::{MediaPlaylist, PrefetchUrlKind};
use player::Player;
use worker::{Error as WorkerErr, Worker};
use worker::Worker;

static ARGS: OnceCell<Args> = OnceCell::new();

Expand All @@ -30,8 +30,8 @@ fn run(worker: &Worker, mut playlist: MediaPlaylist) -> Result<()> {
loop {
let time = Instant::now();
if let Err(e) = playlist.reload() {
match e.downcast_ref::<HlsErr>() {
Some(HlsErr::Unchanged) => {
match e.downcast_ref::<hls::Error>() {
Some(hls::Error::Unchanged) => {
debug!("{e}, retrying in half segment duration...");
playlist.sleep_half_segment_duration(time.elapsed());
continue;
Expand Down Expand Up @@ -77,8 +77,8 @@ fn main() -> Result<()> {

let playlist_url = match playlist_url {
Ok(playlist_url) => playlist_url,
Err(e) => match e.downcast_ref::<HlsErr>() {
Some(HlsErr::NotLowLatency(url)) => {
Err(e) => match e.downcast_ref::<hls::Error>() {
Some(hls::Error::NotLowLatency(url)) => {
info!("{e}, opening player with playlist URL");
Player::spawn_and_wait(&args.player, &args.player_args, url, args.quiet)?;
return Ok(());
Expand All @@ -97,12 +97,21 @@ fn main() -> Result<()> {
let worker = Worker::new(player.stdin()?)?;
match run(&worker, playlist) {
Ok(()) => Ok(()),
Err(e) => match e.downcast_ref::<WorkerErr>() {
Some(WorkerErr::SendFailed | WorkerErr::SyncFailed) => {
Err(e) => {
if http::Error::is_not_found(&e) {
info!("Stream ended, exiting...");
return Ok(());
}

if matches!(
e.downcast_ref::<worker::Error>(),
Some(worker::Error::SendFailed | worker::Error::SyncFailed)
) {
info!("Player closed, exiting...");
Ok(())
return Ok(());
}
_ => Err(e),
},

Err(e)
}
}
}

0 comments on commit 98ab579

Please sign in to comment.