about summary refs log tree commit diff stats
path: root/libmpv2/src/mpv/protocol.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-08-23 12:57:19 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-08-23 12:58:02 +0200
commit0ae5018c33cc4bfe27583c9902472b499f4bd269 (patch)
treeafc2fbfcb126215f47afbc32e555d203d4d6d88c /libmpv2/src/mpv/protocol.rs
parentchore(yt_dlp/progress_hook): Also consider the `total_bytes_estimate` field (diff)
downloadyt-0ae5018c33cc4bfe27583c9902472b499f4bd269.tar.gz
yt-0ae5018c33cc4bfe27583c9902472b499f4bd269.zip
refactor(libmpv2): Move to the `crates` directory
Diffstat (limited to 'libmpv2/src/mpv/protocol.rs')
-rw-r--r--libmpv2/src/mpv/protocol.rs261
1 files changed, 0 insertions, 261 deletions
diff --git a/libmpv2/src/mpv/protocol.rs b/libmpv2/src/mpv/protocol.rs
deleted file mode 100644
index 4ae4f16..0000000
--- a/libmpv2/src/mpv/protocol.rs
+++ /dev/null
@@ -1,261 +0,0 @@
-// yt - A fully featured command line YouTube client
-//
-// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-// This file is part of Yt.
-//
-// You should have received a copy of the License along with this program.
-// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
-
-use super::*;
-
-use std::alloc::{self, Layout};
-use std::marker::PhantomData;
-use std::mem;
-use std::os::raw as ctype;
-use std::panic;
-use std::panic::RefUnwindSafe;
-use std::slice;
-use std::sync::{atomic::Ordering, Mutex};
-
-impl Mpv {
-    /// Create a context with which custom protocols can be registered.
-    ///
-    /// # Panics
-    /// Panics if a context already exists
-    pub fn create_protocol_context<T, U>(&self) -> ProtocolContext<T, U>
-    where
-        T: RefUnwindSafe,
-        U: RefUnwindSafe,
-    {
-        match self.protocols_guard.compare_exchange(
-            false,
-            true,
-            Ordering::AcqRel,
-            Ordering::Acquire,
-        ) {
-            Ok(_) => ProtocolContext::new(self.ctx, PhantomData::<&Self>),
-            Err(_) => panic!("A protocol context already exists"),
-        }
-    }
-}
-
-/// Return a persistent `T` that is passed to all other `Stream*` functions, panic on errors.
-pub type StreamOpen<T, U> = fn(&mut U, &str) -> T;
-/// Do any necessary cleanup.
-pub type StreamClose<T> = fn(Box<T>);
-/// Seek to the given offset. Return the new offset, or either `MpvError::Generic` if seeking
-/// failed or panic.
-pub type StreamSeek<T> = fn(&mut T, i64) -> i64;
-/// Target buffer with fixed capacity.
-/// Return either the number of read bytes, `0` on EOF, or either `-1` or panic on error.
-pub type StreamRead<T> = fn(&mut T, &mut [ctype::c_char]) -> i64;
-/// Return the total size of the stream in bytes. Panic on error.
-pub type StreamSize<T> = fn(&mut T) -> i64;
-
-unsafe extern "C" fn open_wrapper<T, U>(
-    user_data: *mut ctype::c_void,
-    uri: *mut ctype::c_char,
-    info: *mut libmpv2_sys::mpv_stream_cb_info,
-) -> ctype::c_int
-where
-    T: RefUnwindSafe,
-    U: RefUnwindSafe,
-{
-    let data = user_data as *mut ProtocolData<T, U>;
-
-    (*info).cookie = user_data;
-    (*info).read_fn = Some(read_wrapper::<T, U>);
-    (*info).seek_fn = Some(seek_wrapper::<T, U>);
-    (*info).size_fn = Some(size_wrapper::<T, U>);
-    (*info).close_fn = Some(close_wrapper::<T, U>);
-
-    let ret = panic::catch_unwind(|| {
-        let uri = mpv_cstr_to_str!(uri as *const _).unwrap();
-        ptr::write(
-            (*data).cookie,
-            ((*data).open_fn)(&mut (*data).user_data, uri),
-        );
-    });
-
-    if ret.is_ok() {
-        0
-    } else {
-        mpv_error::Generic as _
-    }
-}
-
-unsafe extern "C" fn read_wrapper<T, U>(
-    cookie: *mut ctype::c_void,
-    buf: *mut ctype::c_char,
-    nbytes: u64,
-) -> i64
-where
-    T: RefUnwindSafe,
-    U: RefUnwindSafe,
-{
-    let data = cookie as *mut ProtocolData<T, U>;
-
-    let ret = panic::catch_unwind(|| {
-        let slice = slice::from_raw_parts_mut(buf, nbytes as _);
-        ((*data).read_fn)(&mut *(*data).cookie, slice)
-    });
-    if let Ok(ret) = ret {
-        ret
-    } else {
-        -1
-    }
-}
-
-unsafe extern "C" fn seek_wrapper<T, U>(cookie: *mut ctype::c_void, offset: i64) -> i64
-where
-    T: RefUnwindSafe,
-    U: RefUnwindSafe,
-{
-    let data = cookie as *mut ProtocolData<T, U>;
-
-    if (*data).seek_fn.is_none() {
-        return mpv_error::Unsupported as _;
-    }
-
-    let ret =
-        panic::catch_unwind(|| (*(*data).seek_fn.as_ref().unwrap())(&mut *(*data).cookie, offset));
-    if let Ok(ret) = ret {
-        ret
-    } else {
-        mpv_error::Generic as _
-    }
-}
-
-unsafe extern "C" fn size_wrapper<T, U>(cookie: *mut ctype::c_void) -> i64
-where
-    T: RefUnwindSafe,
-    U: RefUnwindSafe,
-{
-    let data = cookie as *mut ProtocolData<T, U>;
-
-    if (*data).size_fn.is_none() {
-        return mpv_error::Unsupported as _;
-    }
-
-    let ret = panic::catch_unwind(|| (*(*data).size_fn.as_ref().unwrap())(&mut *(*data).cookie));
-    if let Ok(ret) = ret {
-        ret
-    } else {
-        mpv_error::Unsupported as _
-    }
-}
-
-#[allow(unused_must_use)]
-unsafe extern "C" fn close_wrapper<T, U>(cookie: *mut ctype::c_void)
-where
-    T: RefUnwindSafe,
-    U: RefUnwindSafe,
-{
-    let data = Box::from_raw(cookie as *mut ProtocolData<T, U>);
-
-    panic::catch_unwind(|| ((*data).close_fn)(Box::from_raw((*data).cookie)));
-}
-
-struct ProtocolData<T, U> {
-    cookie: *mut T,
-    user_data: U,
-
-    open_fn: StreamOpen<T, U>,
-    close_fn: StreamClose<T>,
-    read_fn: StreamRead<T>,
-    seek_fn: Option<StreamSeek<T>>,
-    size_fn: Option<StreamSize<T>>,
-}
-
-/// This context holds state relevant to custom protocols.
-/// It is created by calling `Mpv::create_protocol_context`.
-pub struct ProtocolContext<'parent, T: RefUnwindSafe, U: RefUnwindSafe> {
-    ctx: NonNull<libmpv2_sys::mpv_handle>,
-    protocols: Mutex<Vec<Protocol<T, U>>>,
-    _does_not_outlive: PhantomData<&'parent Mpv>,
-}
-
-unsafe impl<'parent, T: RefUnwindSafe, U: RefUnwindSafe> Send for ProtocolContext<'parent, T, U> {}
-unsafe impl<'parent, T: RefUnwindSafe, U: RefUnwindSafe> Sync for ProtocolContext<'parent, T, U> {}
-
-impl<'parent, T: RefUnwindSafe, U: RefUnwindSafe> ProtocolContext<'parent, T, U> {
-    fn new(
-        ctx: NonNull<libmpv2_sys::mpv_handle>,
-        marker: PhantomData<&'parent Mpv>,
-    ) -> ProtocolContext<'parent, T, U> {
-        ProtocolContext {
-            ctx,
-            protocols: Mutex::new(Vec::new()),
-            _does_not_outlive: marker,
-        }
-    }
-
-    /// Register a custom `Protocol`. Once a protocol has been registered, it lives as long as
-    /// `Mpv`.
-    ///
-    /// Returns `Error::Mpv(MpvError::InvalidParameter)` if a protocol with the same name has
-    /// already been registered.
-    pub fn register(&self, protocol: Protocol<T, U>) -> Result<()> {
-        let mut protocols = self.protocols.lock().unwrap();
-        protocol.register(self.ctx.as_ptr())?;
-        protocols.push(protocol);
-        Ok(())
-    }
-}
-
-/// `Protocol` holds all state used by a custom protocol.
-pub struct Protocol<T: Sized + RefUnwindSafe, U: RefUnwindSafe> {
-    name: String,
-    data: *mut ProtocolData<T, U>,
-}
-
-impl<T: RefUnwindSafe, U: RefUnwindSafe> Protocol<T, U> {
-    /// `name` is the prefix of the protocol, e.g. `name://path`.
-    ///
-    /// `user_data` is data that will be passed to `open_fn`.
-    ///
-    /// # Safety
-    /// Do not call libmpv functions in any supplied function.
-    /// All panics of the provided functions are catched and can be used as generic error returns.
-    pub unsafe fn new(
-        name: String,
-        user_data: U,
-        open_fn: StreamOpen<T, U>,
-        close_fn: StreamClose<T>,
-        read_fn: StreamRead<T>,
-        seek_fn: Option<StreamSeek<T>>,
-        size_fn: Option<StreamSize<T>>,
-    ) -> Protocol<T, U> {
-        let c_layout = Layout::from_size_align(mem::size_of::<T>(), mem::align_of::<T>()).unwrap();
-        let cookie = alloc::alloc(c_layout) as *mut T;
-        let data = Box::into_raw(Box::new(ProtocolData {
-            cookie,
-            user_data,
-
-            open_fn,
-            close_fn,
-            read_fn,
-            seek_fn,
-            size_fn,
-        }));
-
-        Protocol { name, data }
-    }
-
-    fn register(&self, ctx: *mut libmpv2_sys::mpv_handle) -> Result<()> {
-        let name = CString::new(&self.name[..])?;
-        unsafe {
-            mpv_err(
-                (),
-                libmpv2_sys::mpv_stream_cb_add_ro(
-                    ctx,
-                    name.as_ptr(),
-                    self.data as *mut _,
-                    Some(open_wrapper::<T, U>),
-                ),
-            )
-        }
-    }
-}