crab_dlna/
error.rs

1use crate::devices::RenderSpec;
2use std::fmt;
3
4/// Errors that can happen inside crab-dlna
5#[derive(Debug)]
6pub enum Error {
7    /// An error occurred while discovering devices
8    DevicesDiscoverFail(rupnp::Error),
9    /// An error occurred while parsing a device URL
10    DevicesUrlParseError(String),
11    /// An error occurred while parsing and creating a device
12    DevicesCreateError(String, rupnp::Error),
13    /// An error occurred when the specified render is not found
14    DevicesRenderNotFound(RenderSpec),
15    /// An error occurred parsing a host or IP address
16    StreamingHostParseError(String),
17    /// An error occurred when a certain media file does not exist
18    StreamingFileDoesNotExist(String),
19    /// An error occurred while trying to connect to the render
20    StreamingRemoteRenderConnectFail(String, std::io::Error),
21    /// An error occurred while trying to identify the host IP address
22    StreamingIdentifyLocalAddressError(local_ip_address::Error),
23    /// An error occurred while sending the SetAVTransportURI DLNA action to the render
24    DLNASetAVTransportURIError(rupnp::Error),
25    /// An error occurred while sending the Play DLNA action to the render
26    DLNAPlayError(rupnp::Error),
27    /// An error occurred while serving and streaming the media files
28    DLNAStreamingError(tokio::task::JoinError),
29}
30
31impl fmt::Display for Error {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        match self {
34            Error::DevicesDiscoverFail(err) => write!(f, "Failed to discover devices: {}", err),
35            Error::DevicesUrlParseError(url) => write!(f, "Failed to parse URL '{}'", url),
36            Error::DevicesCreateError(url, err) => write!(
37                f,
38                "Failed to parse and create device from '{}': {}",
39                url, err
40            ),
41            Error::DevicesRenderNotFound(render_spec) => match render_spec {
42                RenderSpec::Location(device_url) => {
43                    write!(f, "No render found at '{}'", device_url)
44                }
45                RenderSpec::Query(timeout, device_query) => write!(
46                    f,
47                    "No render found withing {} seconds with query '{}'",
48                    timeout, device_query
49                ),
50                RenderSpec::First(timeout) => {
51                    write!(f, "No render found within {} seconds", timeout)
52                }
53            },
54            Error::StreamingHostParseError(addr) => {
55                write!(f, "Failed to parse host address '{}'", addr)
56            }
57            Error::StreamingFileDoesNotExist(file) => write!(f, "File '{}' does not exist", file),
58            Error::StreamingRemoteRenderConnectFail(host, err) => {
59                write!(f, "Failed to connect to remote render '{}': {}", host, err)
60            }
61            Error::StreamingIdentifyLocalAddressError(err) => {
62                write!(f, "Failed to identify local address: {}", err)
63            }
64            Error::DLNASetAVTransportURIError(err) => {
65                write!(f, "Failed to set AVTransportURI: {}", err)
66            }
67            Error::DLNAPlayError(err) => write!(f, "Failed to Play: {}", err),
68            Error::DLNAStreamingError(err) => write!(f, "Failed to stream: {}", err),
69        }
70    }
71}
72
73impl std::error::Error for Error {
74    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
75        match self {
76            Error::DevicesDiscoverFail(err) => Some(err),
77            Error::DevicesCreateError(_, err) => Some(err),
78            Error::StreamingRemoteRenderConnectFail(_, err) => Some(err),
79            Error::StreamingIdentifyLocalAddressError(err) => Some(err),
80            Error::DLNASetAVTransportURIError(err) => Some(err),
81            Error::DLNAPlayError(err) => Some(err),
82            Error::DLNAStreamingError(err) => Some(err),
83            _ => None,
84        }
85    }
86}
87
88impl From<ssdp_client::Error> for Error {
89    fn from(err: ssdp_client::Error) -> Self {
90        Error::DevicesDiscoverFail(rupnp::Error::SSDPError(err))
91    }
92}
93
94pub type Result<T, E = Error> = std::result::Result<T, E>;