1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
//! Blocking wrappers for using `rustube` in a synchronous context.
//!
//! Downloading videos with the blocking API works exactly like described for the asynchronous API 
//! in the [`crate`] documentation, and in the [`Video`](crate::Video) documentation, except for the
//! last step:
//! ```no_run
//!# use rustube::blocking::Video;
//!# use url::Url;
//!# fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let url = Url::parse("https://youtube.com/watch?iv=5jlI4uzZGjU")?;
//! let path_to_video = Video::from_url(&url)?
//!    .best_quality()
//!    .unwrap()
//!    .blocking_download()?;
//!#  Ok(())
//!# }
//!```
//!   
//! As you can see, there's no corresponding synchronous version of [`Stream`](crate::Stream), but
//! only a few methods prefixed with `blocking_`. This is not the most beautiful solution and may 
//! change in the future. 
//!  
//! Another option is using the [`block`] macro:
//! ```no_run
//!# use rustube::blocking::Video;
//!# use rustube::block;
//!# use url::Url;
//!# fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let url = Url::parse("https://youtube.com/watch?iv=5jlI4uzZGjU")?;
//! let video = Video::from_url(&url)?;
//! let best_quality = video.best_quality().unwrap();
//!  
//! let path_to_video = block!(best_quality.download());
//!#  Ok(())
//!# }
//!```
//!    
//!This macro will utilize the [`Runtime`](tokio::runtime::Runtime) created for you by `rustube`, 
//! and block on the provided future (You can also use it for other asynchronous stuff, not related 
//! to `rustube`).

use std::lazy::SyncLazy;

use tokio::runtime::Runtime;

#[doc(inline)]
#[cfg(any(feature = "descramble", doc))]
#[doc(cfg(feature = "descramble"))]
pub use descrambler::VideoDescrambler;
#[doc(inline)]
#[cfg(any(feature = "fetch", doc))]
#[doc(cfg(feature = "fetch"))]
pub use fetcher::VideoFetcher;
#[doc(inline)]
#[cfg(any(feature = "descramble", doc))]
#[doc(cfg(feature = "descramble"))]
pub use video::Video;

/// A [`Runtime`](tokio::runtime::Runtime) for executing asynchronous code. 
pub static RT: SyncLazy<Runtime> = SyncLazy::new(||
    Runtime::new().expect("Unable to start the tokio Runtime")
);

/// A convenient macro for executing asynchronous code in a synchronous context.
#[macro_export]
#[doc(cfg(feature = "blocking"))]
#[cfg(any(feature = "blocking", doc))]
macro_rules! block {
    (async $future:block) => { $crate::blocking::RT.block_on(async $future) };
    (async move $future:block) => { $crate::blocking::RT.block_on(async move $future) };
    ($future:expr) => {
        $crate::blocking::RT.block_on(async {
            $future.await
        })
    };
}

#[doc(hidden)]
#[cfg(any(feature = "fetch", doc))]
#[doc(cfg(feature = "fetch"))]
pub mod fetcher;
#[doc(hidden)]
#[cfg(any(feature = "descramble", doc))]
#[doc(cfg(feature = "descramble"))]
pub mod descrambler;
#[doc(hidden)]
#[cfg(any(feature = "descramble", doc))]
#[doc(cfg(feature = "descramble"))]
pub mod video;


/// A synchronous wrapper around [`download_best_quality`](crate::download_best_quality).
#[inline]
#[cfg(any(all(feature = "download", feature = "regex"), doc))]
#[doc(cfg(all(feature = "download", feature = "regex")))]
pub fn download_best_quality(video_identifier: &str) -> crate::Result<std::path::PathBuf> {
    block!(crate::download_best_quality(video_identifier))
}

/// A synchronous wrapper around [`download_worst_quality`](crate::download_worst_quality).
#[inline]
#[cfg(any(all(feature = "download", feature = "regex"), doc))]
#[doc(cfg(all(feature = "download", feature = "regex")))]
pub fn download_worst_quality(video_identifier: &str) -> crate::Result<std::path::PathBuf> {
    block!(crate::download_worst_quality(video_identifier))
}