Giter Club home page Giter Club logo

mkube's Introduction

MKube - Minimalist Media Manager

Yet another media manager, but better (?).

MKube aims to be a complete (and free) media manager in your terminal.

State of development

Currently MKube is at most a PoC, and lots of changes await it. Nonetheless, here a small list of features, MKube is expected to provide today or in the future :

  • Local libraries
  • Remote libraries (currently supporting FTP & SMB)
  • Movie listing
  • Movie search (using TheMovieDB)
  • Metadata retrieval (using ffmpeg)
  • NFO generation (for Kodi only)
  • Persistent configuration
  • Movie details
  • Movie Editor
  • Artwork retrievals
  • Saga support (#15)
  • TV Show support (#5)

Build & Run

MKube is written in Rust and currently built using Nix (to allow easy build on multiple arch).

Supported platforms

Until a first release, MKube will not be tested on any other machine than mine, moreover the main branch might break from time to time.

My long term strategy is to support mainly Linux platforms (amd64, arm64).
MacOS might work (as dependencies at least exist there) but it will not be tested.
I am unsure if Windows will get supported one day, even partially.

Using Cargo

MKube currently requires the following dependencies (but it might not be limited to these):

  • ffmpeg(-dev)
  • openssl
  • libdbus (secrets feature, enabled by default)
  • libsmbclient (smb feature, disabled by default)

Then, just build it: cargo build --release

Note: You might need to install a recent (or nightly) rust toolchain to build MKube. At the time of writting, MKube targets Rust 1.71.0.

Using Nix

MKube uses Nix Flakes to describe its build steps, therefore you might need to enable flakes (experimental-features) before building MKube using nix build.

Note: For developement, you should prefer to run nix develop to create a shell adapted to rust development.

Showcase

mkube

Inspirations

The Linux community is lacking a good media manager, that can support remote libraries. Some good media managers exist, like tinyMediaManager but lack features or enforce to buy premium version to access all their features, including some essential ones. MKube is an attempt to resolve this issue I had myself.

Licensing

Licensed under the EUPL v. 1.2 only.
Note that the EUPL v1.2 license is compatible with many other recognized licenses (see appendix).

Fusetim (2023) - All rights reserved.

mkube's People

Contributors

fusetim avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

mkube's Issues

Storing Credentials in clear-text

Currently credentials (for SMB/FTP libraries) are stored in clear text in the config file, meaning that anyone in that have access to ~/.config can retrieve the credentials. To increase the security of the app, Mkube might implement the Secrets DBus API.

CI: Nix cross-compiling builds

Short description:
It would be awesome to build and distribute the app executable for a large set of platforms.
Using nix it should be rather simple to put in place.

Plan:

  • CI Builds
  • CI CrossCompiling Builds

Bug: input panics due to overflow

What happened?
When using an input and scrolling through the columns (tested only in Movie Editor, with the plot field), it panics (not every time).

Seems that it has been introduced by 90521bd

Trace:

{"backtrace":"   0: structured_logger::log_panic\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/structured-logger-1.0.2/src/lib.rs:445:21\n   1: core::ops::function::Fn::call\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:79:5\n   2: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/boxed.rs:1987:9\n   3: std::panicking::rust_panic_with_hook\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:695:13\n   4: std::panicking::begin_panic_handler::{{closure}}\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:582:13\n   5: std::sys_common::backtrace::__rust_end_short_backtrace\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys_common/backtrace.rs:150:18\n   6: rust_begin_unwind\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:5\n   7: core::panicking::panic_fmt\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:67:14\n   8: core::panicking::panic_bounds_check\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:162:5\n   9: <usize as core::slice::index::SliceIndex<[T]>>::index\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/slice/index.rs:261:10\n  10: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/slice/index.rs:19:9\n  11: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/vec/mod.rs:2691:9\n  12: mkube::views::widgets::input::Input::render_text\n             at ./src/views/widgets/input.rs:218:37\n  13: <mkube::views::movie_manager::editor::MovieEditor as tui::widgets::StatefulWidget>::render::{{closure}}\n             at ./src/views/movie_manager/editor.rs:88:40\n  14: core::iter::adapters::map::map_fold::{{closure}}\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/iter/adapters/map.rs:84:28\n  15: <core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold::enumerate::{{closure}}\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/iter/adapters/enumerate.rs:107:27\n  16: core::iter::traits::iterator::Iterator::fold\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/iter/traits/iterator.rs:2482:21\n  17: <core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::fold\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/iter/adapters/enumerate.rs:113:9\n  18: <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/iter/adapters/map.rs:124:9\n  19: core::iter::traits::iterator::Iterator::for_each\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/iter/traits/iterator.rs:857:9\n  20: alloc::vec::Vec<T,A>::extend_trusted\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/vec/mod.rs:2844:17\n  21: <alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/vec/spec_extend.rs:26:9\n  22: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/vec/spec_from_iter_nested.rs:62:9\n  23: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/vec/spec_from_iter.rs:33:9\n  24: <alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/vec/mod.rs:2712:9\n  25: core::iter::traits::iterator::Iterator::collect\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/iter/traits/iterator.rs:1896:9\n  26: <mkube::views::movie_manager::editor::MovieEditor as tui::widgets::StatefulWidget>::render\n             at ./src/views/movie_manager/editor.rs:77:30\n  27: <mkube::views::movie_manager::MovieManager as tui::widgets::StatefulWidget>::render\n             at ./src/views/movie_manager/mod.rs:66:17\n  28: <mkube::views::App as tui::widgets::StatefulWidget>::render\n             at ./src/views/mod.rs:193:17\n  29: tui::terminal::Frame<B>::render_stateful_widget\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tui-0.19.0/src/terminal.rs:133:9\n  30: mkube::run::{{closure}}::{{closure}}\n             at ./src/main.rs:231:21\n  31: tui::terminal::Terminal<B>::draw\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tui-0.19.0/src/terminal.rs:263:9\n  32: mkube::run::{{closure}}\n             at ./src/main.rs:229:17\n  33: mkube::main::{{closure}}\n             at ./src/main.rs:47:29\n  34: tokio::runtime::park::CachedParkThread::block_on::{{closure}}\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/park.rs:283:63\n  35: tokio::runtime::coop::with_budget\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/coop.rs:107:5\n  36: tokio::runtime::coop::budget\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/coop.rs:73:5\n  37: tokio::runtime::park::CachedParkThread::block_on\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/park.rs:283:31\n  38: tokio::runtime::context::blocking::BlockingRegionGuard::block_on\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/context/blocking.rs:66:9\n  39: tokio::runtime::scheduler::multi_thread::MultiThread::block_on::{{closure}}\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/multi_thread/mod.rs:87:13\n  40: tokio::runtime::context::runtime::enter_runtime\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/context/runtime.rs:65:16\n  41: tokio::runtime::scheduler::multi_thread::MultiThread::block_on\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/scheduler/multi_thread/mod.rs:86:9\n  42: tokio::runtime::runtime::Runtime::block_on\n             at /home/fusetim/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.29.1/src/runtime/runtime.rs:313:45\n  43: mkube::main\n             at ./src/main.rs:67:5\n  44: core::ops::function::FnOnce::call_once\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5\n  45: std::sys_common::backtrace::__rust_begin_short_backtrace\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/sys_common/backtrace.rs:134:18\n  46: std::rt::lang_start::{{closure}}\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/rt.rs:166:18\n  47: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:287:13\n  48: std::panicking::try::do_call\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:485:40\n  49: std::panicking::try\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:449:19\n  50: std::panic::catch_unwind\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panic.rs:140:14\n  51: std::rt::lang_start_internal::{{closure}}\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/rt.rs:148:48\n  52: std::panicking::try::do_call\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:485:40\n  53: std::panicking::try\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:449:19\n  54: std::panic::catch_unwind\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panic.rs:140:14\n  55: std::rt::lang_start_internal\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/rt.rs:148:20\n  56: std::rt::lang_start\n             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/rt.rs:165:17\n  57: main\n  58: <unknown>\n  59: __libc_start_main\n  60: _start\n","file":"src/views/widgets/input.rs","level":"ERROR","line":218,"message":"thread 'main' panicked at 'index out of bounds: the len is 103 but the index is 103', src/views/widgets/input.rs:218:37","target":"panic","thread_name":"main","timestamp":1692116948151}

TMDB supports lang/country selector, but the app does not

Short description:
The TMDB API supports query with lang/country selector, but currently the app does not give any option to use it.

This feature is important as it impacts the translations of the overview and even the artworks downloaded by the app.

Roadmap:

  • 65c659e - Accept lang and region parameter (using config).
  • Expose these preferences in the app settings.

Movie editor

Short description:
Create an editor to easily edit the NFO info.

Permanent configuration

Short description:
Save and restore the configuration, it will includes the known libraries and in the future preferences (lang, countries,..)

Propositions to enhance Movie Search

Short Description:
Currently, movie search only works if you input a title very close to the original title.
Proposed by others, we might integrate a small DB to enhance the search by precalculating
numerous title, and their TMDB ID and use the Levenshtein distance to search for the closest match.

We might (if I really want to) try to fingerprint the audio track to find automatically the corresponding movie, but
that surely will require a large DB of such audio fingerprint. While for music, multiple exists, it is uncertain for movies.

Movie quick tag

Implement some keyboard shortcut to quickly re-tag some movies.
For instance, press t to set Source to "TV", b for "Bluray" etc.

Input still does not handle graphemes correctly

Following changes introduced by #1 and #9, input does not handle correctly graphemes.
Currently, input will uses graphemes to produces their internal value from an initialization value, but then,
the interval value separates only chars and not graphemes.

How to Reproduce the issue:
Paste eฬ (\u{0065}\u{0301}) in the input.
Weird behaviors happen when you put your cursor between the two chars.

Severity: The issue can only occur when copy-pasting some Unicode text containing "Combinaing characters" (found in emoji, accentuated letters, etc). (Real) keyboard input can only produce sane one-char grapheme.

Proposal:
On KeyEvent, if a key (char input) is typed, we must take the last item in the internal value, concatenated it to the input, then call graphemes and extend the internal value with the new graphemes.

Movie details

Short description:
In the Movie Manager's pages, showing more details about the film selected is quite essential.

Resolve copyright/licensing issues

MKube is licensed under EUPL1.2-only, but mkube cannot be distributed as a binary currently without violating copyright/licenses of some dependencies.

Most of Mkube's dependencies are licensed under MIT or Apache 2.0 licenses and those are perfectly fine.
Nonetheless, two libraries one library that Mkube uses do does not allow redistribution under derivative works:

  • pavao (dependence of remotefs-smb) is licensed only under GPL3+, this would cause the MKube binary to be licensed under GPL3 (due to EUPL1.2-only compatibility with GPL3) which is not terrible. Mkube binary without smb support can still be licensed under EUPL1.2-only.
  • tmdb-api (direct dependency) is a more severe question as it is not licensed under any license at all. Therefore no mkube binary can be redistributed. tmdb-api is actually licensed under the MIT license, so no problem.

Extend the app to TV Shows

Short description:
Create or adapt the current app to be used with TV Show libraries. NFO must be adapted, and the GUI too.

Input does not support UTF8

Short description:
Using any UTF8 character that is not an ASCII char in an input will panic!

Why does it happen?
We use numerous method on String that can split or get a char that is not a UTF8 char boundary, therefore creating an invalid substring.

What should we do?
Use graphems and not chars.
Indeed even if we fix the original issue by checking or finding the closest UTF8 char boundary, it might introduce some weird behavior when using extended graphems (like emoji modifiers).

Conditional compilation and features

Short description:
This app supports multiple file systems, including some remote ones. Most of those require dedicated system libraries (eg. libsmbclient for SMB support). Therefore, using conditional compilation would allow to distribute to more people the app with different sets of features, and removing the ones unsupported by their platforms.

Note: it would be cool to use nix conditional compilation too.

Input calls too many time graphemes()

Short description:
Input calls graphemes() on render, which is very inefficient. As the String value, is mostly only use by external widgets,
we could replace our String value by a Vec (produced by graphemes) and produces the String value on demand.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.