Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/medialibrary
  • luyikei/medialibrary
  • qiubit/medialibrary
  • lemourin/medialibrary
  • gsoc/GSoC2017/Bubu/medialibrary
  • Nerf/medialibrary
  • Dekans/medialibrary
  • Skantes/medialibrary
  • robUx4/medialibrary
  • bubu/medialibrary
  • craig_janeway/medialibrary
  • rom1v/medialibrary
  • tguillem/medialibrary
  • b1ue/medialibrary
  • Corbax/medialibrary
  • ilearninging/medialibrary
  • stevengivens542/medialibrary
  • fkuehne/medialibrary
  • gorbahaaa/medialibrary
  • 1480c1/medialibrary
  • ashleerenee2727/medialibrary
  • ashrafuddin5636/medialibrary
  • hkosacki/medialibrary
  • joykim/medialibrary
  • gsoc/gsoc2020/arnav-ishaan/medialibrary
  • elbrujo1987/medialibrary
  • asenat/medialibrary
  • Aza/medialibrary
  • gtskhadadze83/medialibrary
  • rm10161130/medialibrary
  • sandsmark/medialibrary
  • Aymeriic/medialibrary
  • louis/medialibrary
  • krsingh.chandan/medialibrary
  • ForteFrankie/medialibrary
  • mstorsjo/medialibrary
  • luc65r/medialibrary
  • abodbre1/medialibrary
  • Juniorzito8415/medialibrary
  • atas70835/medialibrary
  • Ninaquinin/medialibrary
  • litteh82/medialibrary
  • king7532/medialibrary
  • bharatraval7162/medialibrary
  • yenidunyabetul443/medialibrary
  • sergiomb2/medialibrary
  • boykaisaac758/medialibrary
  • Niram7777/medialibrary
  • tvermaashutosh/medialibrary
  • chub/medialibrary
  • bdazzle431/medialibrary
51 results
Show changes
Commits on Source (305)
Showing
with 834 additions and 162 deletions
......@@ -53,6 +53,20 @@ static void ListAllPublicAlbums( benchmark::State& state )
}
}
static void SearchAlbumByName( benchmark::State& state )
{
auto bml = commonInit();
const std::string req = "SELECT * FROM " + Album::Table::Name +
" WHERE title = 'album_5'";
for ( auto _ : state )
{
auto albums = Album::fetchAll<Album>(
static_cast<MediaLibrary*>( bml.ml.get() ),
req );
benchmark::DoNotOptimize( albums );
}
}
BENCHMARK( ListAllAlbums )
->Arg( toInt( SortingCriteria::Artist ) )
->Arg( toInt( SortingCriteria::ReleaseDate ) )
......@@ -63,3 +77,5 @@ BENCHMARK( ListAllAlbums )
->Arg( toInt( SortingCriteria::Default ) );
BENCHMARK( ListAllPublicAlbums );
BENCHMARK( SearchAlbumByName );
......@@ -5,7 +5,10 @@ NB_ALBUMS_PER_ARTIST=10
NB_TRACKS_PER_ALBUM=10
SCRIPT_DIRECTORY=$(dirname "$0")
CORPUS_DIRECTORY=/tmp/medialib_samples/
CORPUS_DIRECTORY=${TMPDIR:=/tmp}/medialib_samples/
command -v id3tag >/dev/null 2>&1 || (echo "Could not find id3tag, exiting." >&2; exit 1)
command -v shuf >/dev/null 2>&1 || (echo "Could not find shuf, exiting." >&2; exit 1)
usage()
{
......
variables:
GIT_SUBMODULE_STRATEGY: normal
MEDIALIBRARY_IMG: registry.videolan.org/medialibrary:20220128153337
MEDIALIBRARY_WIN32_IMG: registry.videolan.org/medialibrary-win32:20220502075714
MEDIALIBRARY_WIN64_IMG: registry.videolan.org/medialibrary-win64:20220502082738
VLC_DEBIAN_UNSTABLE_IMG: registry.videolan.org/vlc-debian-unstable:20220127084320
MEDIALIBRARY_ALPINE_IMG: registry.videolan.org/medialibrary-alpine:20210902074848
MEDIALIBRARY_ARCH_IMG: registry.videolan.org/medialibrary-archlinux:20220124130611
MEDIALIBRARY_30_IMAGE: registry.videolan.org/medialibrary-3.0:20231017192545
MEDIALIBRARY_40_IMAGE: registry.videolan.org/medialibrary-4.0:20231017192545
MEDIALIBRARY_WIN32_IMG: registry.videolan.org/medialibrary-win32:20231013034500
MEDIALIBRARY_WIN64_IMG: registry.videolan.org/medialibrary-win64:20231013035411
VLC_DEBIAN_UNSTABLE_IMG: registry.videolan.org/vlc-debian-unstable:20221213103803
MEDIALIBRARY_ALPINE_IMG: registry.videolan.org/medialibrary-alpine:20220706115155
MEDIALIBRARY_ARCH_IMG: registry.videolan.org/medialibrary-archlinux:20220706120650
MEDIALIB_TEST_FOLDER: $CI_PROJECT_DIR/medialib_tests/
stages:
......@@ -20,7 +21,7 @@ default:
interruptible: true
build:novlc:
image: $MEDIALIBRARY_IMG
image: $MEDIALIBRARY_30_IMAGE
stage: build
rules:
- if: $CI_MERGE_REQUEST_IID
......@@ -46,48 +47,39 @@ build:arch:
- meson build
- cd build && ninja
test:debian:
image: $MEDIALIBRARY_IMG
.test:debian.base:
image: $MEDIALIBRARY_30_IMAGE
rules:
- if: $CI_MERGE_REQUEST_IID
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_PIPELINE_SOURCE == "schedule" && $MEDIALIB_MANUAL_JOB_NAME == null'
stage: test
script:
- cd /tmp/ && git clone --single-branch --branch=display_stack_on_timeout --depth=1 https://github.com/chouquette/meson
- export PATH=/tmp/meson:$PATH
- cd $CI_PROJECT_DIR
- meson.py -Db_coverage=true build
- meson -Db_coverage=true build
- cd build
- meson.py test --no-stdsplit
- mkdir html/
- >
gcovr -r "$CI_PROJECT_DIR/"
-e "$CI_PROJECT_DIR/libvlcpp"
-e "$CI_PROJECT_DIR/test"
-e "$CI_PROJECT_DIR/src/database/SqliteErrors.h"
-e "$CI_PROJECT_DIR/src/database/SqliteErrors.cpp"
-e "$CI_PROJECT_DIR/include/medialibrary/filesystem/Errors.h"
-e "$CI_PROJECT_DIR/include/medialibrary/IMediaLibrary.h"
-e "$CI_PROJECT_DIR/src/utils/xxhash/"
--xml cobertura.xml --html=html/medialibrary.html --html-details
-s
-j 4
- meson test --no-stdsplit
- gcovr -r "$CI_PROJECT_DIR/" --json $CI_PROJECT_DIR/$CI_JOB_NAME.cov.json -j 4
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: build/cobertura.xml
junit: build/meson-logs/testlog.junit.xml
name: "coverage-medialibrary-$CI_COMMIT_SHORT_SHA"
paths:
- build/html/
- $MEDIALIB_TEST_FOLDER/**/test.db
- $CI_PROJECT_DIR/build/meson-logs/testlog.txt
- $CI_PROJECT_DIR/$CI_JOB_NAME.cov.json
when: always
test:debian-3.0:
extends: .test:debian.base
image: $MEDIALIBRARY_30_IMAGE
test:debian-4.0:
extends: .test:debian.base
image: $MEDIALIBRARY_40_IMAGE
test:win32:
image: $MEDIALIBRARY_WIN32_IMG
allow_failure: true
variables:
MESON_TESTTHREADS: 8
stage: test
......@@ -107,18 +99,19 @@ test:win32:
- cp /prefix/dll/libvlccore.dll .
- ln -s /prefix/lib/vlc/plugins/ .
- wineserver -p && wine wineboot
- MEDIALIB_TEST_FOLDER=`winepath -w $MEDIALIB_TEST_FOLDER` meson test --no-stdsplit
- MEDIALIB_TEST_FOLDER=`winepath -w $MEDIALIB_TEST_FOLDER` meson test --no-stdsplit --timeout-multiplier=2
artifacts:
when: always
reports:
junit: build/meson-logs/testlog.junit.xml
paths:
paths:
- $MEDIALIB_TEST_FOLDER/**/test.db
- $CI_PROJECT_DIR/build/meson-logs/testlog.txt
expire_in: 1 week
test:win64:
image: $MEDIALIBRARY_WIN64_IMG
allow_failure: true
variables:
MESON_TESTTHREADS: 8
stage: test
......@@ -138,12 +131,12 @@ test:win64:
- cp /prefix/dll/libvlc.dll .
- cp /prefix/dll/libvlccore.dll .
- ln -s /prefix/lib/vlc/plugins/ .
- MEDIALIB_TEST_FOLDER=`winepath -w $MEDIALIB_TEST_FOLDER` meson test --no-stdsplit
- MEDIALIB_TEST_FOLDER=`winepath -w $MEDIALIB_TEST_FOLDER` meson test --no-stdsplit --timeout-multiplier=2
artifacts:
when: always
reports:
junit: build/meson-logs/testlog.junit.xml
paths:
paths:
- $MEDIALIB_TEST_FOLDER/**/test.db
- $CI_PROJECT_DIR/build/meson-logs/testlog.txt
expire_in: 1 week
......@@ -161,55 +154,51 @@ asan-ubsan:
- ./configure LDFLAGS="-lasan -lubsan" --prefix=$(pwd)/prefix --disable-qt --with-sanitizer=address,undefined --disable-medialibrary --disable-nls --enable-debug
- make install -j8
- export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$(pwd)/prefix/lib/pkgconfig"
- cd /tmp/ && git clone --single-branch --branch=display_stack_on_timeout --depth=1 https://github.com/chouquette/meson
- export PATH=/tmp/meson:$PATH
- cd $CI_PROJECT_DIR
- meson.py -Db_sanitize=address,undefined build
- cd build && meson.py test --no-stdsplit
- meson.py compile fast_discover_cancel fast_teardown
- ./test/fast_teardown/fast_teardown $CI_PROJECT_DIR/test/samples/samples
- ./test/fast_discover_cancel/fast_discover_cancel $CI_PROJECT_DIR/test/samples/samples
- meson -Db_sanitize=address,undefined -Dlong_running_tests=true build
- cd build && meson test --no-stdsplit --no-suite long_running_tests
- meson test --suite long_running_tests --test-args $CI_PROJECT_DIR/test/samples/samples --no-stdsplit --logbase longtests
artifacts:
when: on_failure
paths:
- $MEDIALIB_TEST_FOLDER/**/test.db
- $CI_PROJECT_DIR/build/meson-logs/testlog.txt
- $CI_PROJECT_DIR/build/meson-logs/longtests.txt
expire_in: 1 week
.base-sanitizer:
image: $MEDIALIBRARY_IMG
image: $MEDIALIBRARY_40_IMAGE
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "$CI_DEFAULT_BRANCH@videolan/medialibrary"'
stage: test
script:
- cd /tmp/ && git clone --single-branch --branch=display_stack_on_timeout --depth=1 https://github.com/chouquette/meson
- export PATH=/tmp/meson:$PATH
- cd $CI_PROJECT_DIR
- >
CXX=clang++
meson.py
meson
-Dpkg_config_path=$PKG_CONFIG_PATH:$CI_PROJECT_DIR/vlc/prefix/lib/pkgconfig
-Db_sanitize=$SANITIZERS
-Db_lundef=false
-Dlong_running_tests=true
build
- cd build && meson.py test --no-stdsplit
- meson.py compile fast_discover_cancel fast_teardown
- ./test/fast_teardown/fast_teardown $CI_PROJECT_DIR/test/samples/samples
- ./test/fast_discover_cancel/fast_discover_cancel $CI_PROJECT_DIR/test/samples/samples
- cd build && meson test --no-stdsplit --no-suite long_running_tests
- meson test --suite long_running_tests --test-args $CI_PROJECT_DIR/test/samples/samples --no-stdsplit --logbase longtests
artifacts:
when: on_failure
paths:
- $MEDIALIB_TEST_FOLDER/**/test.db
- $CI_PROJECT_DIR/build/meson-logs/testlog.txt
- $CI_PROJECT_DIR/build/meson-logs/longtests.txt
expire_in: 1 week
test:tsan:
extends: .base-sanitizer
image: $MEDIALIBRARY_30_IMAGE
variables:
TSAN_OPTIONS: 'suppressions=$CI_PROJECT_DIR/ci/tsan_suppress_file'
SANITIZERS: thread
test:asan-ubsan:
extends: .base-sanitizer
variables:
......@@ -217,7 +206,7 @@ test:asan-ubsan:
SANITIZERS: address,undefined
gen-test-db:
image: $MEDIALIBRARY_IMG
image: $MEDIALIBRARY_30_IMAGE
stage: generate
dependencies: []
rules:
......@@ -225,14 +214,14 @@ gen-test-db:
script:
- meson --buildtype=release build
- cd build && ninja
- ../ci/generate-samples.sh -o $CI_PROJECT_DIR/dummysamples -n 10
- ../ci/generate-samples.sh -o $CI_PROJECT_DIR/dummysamples -n 2
- test/discoverer/discoverer $CI_PROJECT_DIR/dummysamples -q
- echo "BEGIN;" > $CI_PROJECT_DIR/test_db.sql
- >
sqlite3 $MEDIALIB_TEST_FOLDER/medialib/discoverer_test/test.db '.schema --nosys'
- >
sqlite3 $MEDIALIB_TEST_FOLDER/medialib/discoverer_test/test.db '.schema --nosys'
| grep -vF '/*' >> $CI_PROJECT_DIR/test_db.sql
- >
sqlite3 $MEDIALIB_TEST_FOLDER/medialib/discoverer_test/test.db '.dump --data-only --nosys'
sqlite3 $MEDIALIB_TEST_FOLDER/medialib/discoverer_test/test.db '.dump --data-only --nosys'
| grep -v '^INSERT INTO [[:alpha:]]*Fts'
>> $CI_PROJECT_DIR/test_db.sql
- echo "COMMIT;" >> $CI_PROJECT_DIR/test_db.sql
......@@ -243,3 +232,36 @@ gen-test-db:
paths:
- "$CI_PROJECT_DIR/test_db.sql"
- "$CI_PROJECT_DIR/test.db"
# Combine multiple coverage output into a single coverage artifact
gen-coverage:
image: $MEDIALIBRARY_30_IMAGE
stage: generate
needs: ["test:debian-3.0", "test:debian-4.0"]
rules:
- if: $CI_MERGE_REQUEST_IID
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_PIPELINE_SOURCE == "schedule" && $MEDIALIB_MANUAL_JOB_NAME == null'
script:
- mkdir html
- >
gcovr --add-tracefile '*.cov.json'
-e "$CI_PROJECT_DIR/libvlcpp"
-e "$CI_PROJECT_DIR/test"
-e "$CI_PROJECT_DIR/src/database/SqliteErrors.h"
-e "$CI_PROJECT_DIR/src/database/SqliteErrors.cpp"
-e "$CI_PROJECT_DIR/include/medialibrary/filesystem/Errors.h"
-e "$CI_PROJECT_DIR/include/medialibrary/IMediaLibrary.h"
-e "$CI_PROJECT_DIR/src/utils/xxhash/"
--xml cobertura.xml --html=html/medialibrary.html --html-details
-s
-j 4
coverage: /^\s*lines:\s*\d+.\d+\%/
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: cobertura.xml
paths:
- html/
name: "coverage-medialibrary-$CI_COMMIT_SHORT_SHA"
......@@ -90,6 +90,14 @@ public:
* @brief isUnknownAlbum returns true is this is an unknown album
*/
virtual bool isUnknownAlbum() const = 0;
/**
* @brief isFavorite returns true if the album is marked as favorite.
*/
virtual bool isFavorite() const = 0;
/**
* @brief setFavorite mark or unmark an album as favorite.
*/
virtual bool setFavorite( bool ) = 0;
virtual Query<IMedia> searchTracks( const std::string& pattern,
const QueryParameters* params = nullptr ) const = 0;
......
......@@ -76,6 +76,15 @@ public:
virtual unsigned int nbAlbums() const = 0;
virtual unsigned int nbTracks() const = 0;
virtual unsigned int nbPresentTracks() const = 0;
/**
* @brief isFavorite returns true if the artist is marked as favorite.
*/
virtual bool isFavorite() const = 0;
/**
* @brief setFavorite mark or unmark an artist as favorite.
*/
virtual bool setFavorite( bool ) = 0;
};
}
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright © 2022 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#pragma once
#include <string>
namespace medialibrary
{
class ICacher
{
public:
virtual ~ICacher() = default;
virtual bool cache( const std::string& inputMrl,
const std::string& outputPath ) = 0;
virtual void interrupt() = 0;
};
}
......@@ -23,6 +23,7 @@
#pragma once
#include <string>
#include <cstdint>
namespace medialibrary
{
......
......@@ -34,7 +34,7 @@ namespace medialibrary
*
* An external device lister shall only be used when the medialibrary can't list
* the devices itself.
* The device/folder/file management will still be the medialibrary's responsability
* The device/folder/file management will still be the medialibrary's responsibility
*/
class IDeviceListerCb
{
......
......@@ -22,6 +22,7 @@
#pragma once
#include <cstdint>
#include <string>
namespace medialibrary
......@@ -52,6 +53,17 @@ public:
Playlist,
/// A disc file. Also considered to be a "main" file
Disc,
/// A resource describing a subscription.
Subscription,
/// A cached version of the main file
Cache,
};
enum class CacheType : uint8_t
{
Uncached,
Manual,
Automatic,
};
virtual ~IFile() = default;
......@@ -69,7 +81,7 @@ public:
virtual const std::string& mrl() const = 0;
virtual Type type() const = 0;
virtual time_t lastModificationDate() const = 0;
virtual int64_t size() const = 0;
virtual uint64_t size() const = 0;
virtual bool isRemovable() const = 0;
///
/// \brief isExternal returns true if this stream isn't managed by the medialibrary
......@@ -87,6 +99,15 @@ public:
* This can be used to have a Disc file considered as the main file
*/
virtual bool isMain() const = 0;
virtual time_t insertionDate() const = 0;
/**
* @brief cacheType Returns the cache type, if the file is a cached representation.
*
* If this is not a cache file, CacheType::Uncached will be returned.
*/
virtual CacheType cacheType() const = 0;
};
}
......@@ -54,7 +54,7 @@ public:
virtual bool isPresent() const = 0;
virtual bool isRemovable() const = 0;
/**
* @brief isBanned Will return true if the folder was explicitely banned
* @brief isBanned Will return true if the folder was explicitly banned
* from being discovered.
*/
virtual bool isBanned() const = 0;
......@@ -135,6 +135,9 @@ public:
* If some media duration is unknown, it is ignored in this total.
*/
virtual int64_t duration() const = 0;
virtual bool isFavorite() const = 0;
virtual bool setFavorite( bool favorite ) = 0;
};
}
......@@ -87,10 +87,19 @@ public:
* @param sizeType The thumbnail size type
* @param takeOwnership If true, the medialibrary will copy the thumbnail in
* its thumbnail directory and will manage its lifetime
* @return true if the thumbnail was successfully overriden, false otherwise.
* @return true if the thumbnail was successfully overridden, false otherwise.
*/
virtual bool setThumbnail( const std::string& mrl, ThumbnailSizeType sizeType,
bool takeOwnership ) = 0;
/**
* @brief isFavorite returns true if the genre is marked as favorite.
*/
virtual bool isFavorite() const = 0;
/**
* @brief setFavorite mark or unmark a genre as favorite.
*/
virtual bool setFavorite( bool ) = 0;
};
}
......@@ -111,10 +111,10 @@ public:
*/
enum class ProgressResult : uint8_t
{
/// An error occured and the progress wasn't changed
/// An error occurred and the progress wasn't changed
Error,
/// The provided position/time was interpreted as the beginning of the
/// media and has been reset to -1. This nedia playback is now not
/// media and has been reset to -1. This media playback is now not
/// considered started.
Begin,
/// The provided position/time was not interpreted as a special position
......@@ -170,11 +170,11 @@ public:
* @brief setLastPosition updates the last playback position
*
* @param lastPosition The current playback position expressed by a number in the range [0;1]
* @return a ProgressResult value indicating how the value was intepreted and
* @return a ProgressResult value indicating how the value was interpreted and
* if the operation succeeded
*
* The media library will interpret the value to determine if the playback
* is completed and the media should be marked as watched (therefor increasing
* is completed and the media should be marked as watched (therefore increasing
* the playcount). If the progress isn't large enough, the media library will
* ignore the new progress.
* The base value for the beginning/end of a media is 5%, meaning that the
......@@ -207,7 +207,7 @@ public:
/**
* @brief setLastTime Sets the last playback time.
* @param lastTime A time in millisecond
* @return a ProgressResult value indicating how the value was intepreted and
* @return a ProgressResult value indicating how the value was interpreted and
* if the operation succeeded
*
* This is similar to setLastPosition but works with a time in
......@@ -238,6 +238,7 @@ public:
virtual bool markAsPlayed() = 0;
virtual ShowEpisodePtr showEpisode() const = 0;
virtual const std::vector<FilePtr>& files() const = 0;
virtual FilePtr mainFile() const = 0;
/**
* @brief addFile Add a file to this media
* @param mrl The new file mrl
......@@ -307,7 +308,7 @@ public:
/// Upon completion (successful or not) IMediaLibraryCb::onMediaThumbnailReady
/// will be called.
/// In case a thumbnail was already generated for the media, a new thumbnail
/// will be generated, and the previous one will be overriden.
/// will be generated, and the previous one will be overridden.
/// \param sizeType The size type of the thumbnail to generate
/// \param desiredWidth The desired thumbnail width
/// \param desiredHeight The desired thumbnail height
......@@ -333,7 +334,7 @@ public:
virtual bool removeThumbnail( ThumbnailSizeType sizeType ) = 0;
virtual unsigned int insertionDate() const = 0;
virtual unsigned int releaseDate() const = 0;
virtual time_t releaseDate() const = 0;
/// Metadata
///
......@@ -347,7 +348,7 @@ public:
///
virtual std::unordered_map<MetadataType, std::string> metadata() const = 0;
///
/// \brief setMetadata Immediatly saves a metadata in database
/// \brief setMetadata Immediately saves a metadata in database
///
virtual bool setMetadata( MetadataType type, const std::string& value ) = 0;
virtual bool setMetadata( MetadataType type, int64_t value ) = 0;
......@@ -411,12 +412,12 @@ public:
///
/// \brief isDiscoveredMedia Returns true if this media was discovered
/// during a scan.
/// false means that the media has been explicitely added by the user
/// false means that the media has been explicitly added by the user
/// as a stream, or an external media
///
virtual bool isDiscoveredMedia() const = 0;
///
/// \brief isExternalMedia Returns true if the media was explicitely added
/// \brief isExternalMedia Returns true if the media was explicitly added
/// by the application.
/// This is the opposite counterpart of isDiscoveredMedia
///
......@@ -467,7 +468,7 @@ public:
/// The media is considered present if the device containing its main file
/// is present (ie. if a removable drive is mounted, or a network drive
/// connected)
/// This is only relevent when the media is not external
/// This is only relevant when the media is not external
///
virtual bool isPresent() const = 0;
......@@ -488,6 +489,21 @@ public:
virtual const std::string& lyrics() const = 0;
virtual bool isPublic() const = 0;
virtual uint32_t nbSubscriptions() const = 0;
/// \brief linkedSubscriptions Returns a query representing subscriptions
/// containing this media
/// \param params Some query parameters, or nullptr for the default
///
/// The only query parameter supported for this query for now is to choose
/// a descending order of the name sorting.
virtual Query<ISubscription> linkedSubscriptions( const QueryParameters* ) const = 0;
/**
* @brief description Returns this media description, if available.
* @return A description or a reference to an empty string when none is available.
*/
virtual const std::string& description() const = 0;
};
}
......@@ -114,7 +114,7 @@ public:
/**
* @brief userInteracted Returns true if the group has had user interactions
*
* This includes being renamed, or being explicitely created with some specific
* This includes being renamed, or being explicitly created with some specific
* media or an explicit title.
* It doesn't include groups that were automatically created by the media library
* Removing a media from an automatically created group won't be interpreted
......@@ -178,7 +178,7 @@ public:
/**
* @brief rename Rename a group
* @param name The new name
* @return true if the rename was successfull, false otherwise
* @return true if the rename was successful, false otherwise
*
* This will not change the group content, however, it will prevent further
* media that matched the previous name to be automatically added to this
......@@ -192,6 +192,9 @@ public:
* This will ungroup all media that are part of this group.
*/
virtual bool destroy() = 0;
virtual bool isFavorite() const = 0;
virtual bool setFavorite( bool favorite ) = 0;
};
}
......@@ -30,6 +30,7 @@
#include "Types.h"
#include "IQuery.h"
#include "IMedia.h"
#include "IService.h"
struct libvlc_instance_t;
......@@ -111,6 +112,9 @@ struct QueryParameters
* public entities only.
*/
bool publicOnly = false;
/* If true, only favorite entities will be returned */
bool favoriteOnly = false;
};
enum class InitializeResult
......@@ -163,8 +167,10 @@ enum class ThumbnailStatus : uint8_t
enum class HistoryType : uint8_t
{
/// The history of both local and network media played
Global,
/// The history of media analyzed by the media library & external media
Media,
Local,
/// The network streams history
Network,
};
......@@ -182,9 +188,13 @@ enum class PlaylistType : uint8_t
{
/// Include all kind of playlist, regarding of the media types
All,
/// Only include audio playlists
/// Include playlists containing at least one audio track
Audio,
/// Include playlists containing at least one video or one unknown track
Video,
/// Include playlists containing audio tracks only
AudioOnly,
/// Only include video playlist
/// Include playlists containing video tracks only
VideoOnly,
};
......@@ -212,7 +222,7 @@ struct SetupConfig
/**
* @brief logLevel The default log level to initialize the medialibrary with.
* This can be overwriten at a later point using IMediaLibrary::setVerbosity
* This can be overwritten at a later point using IMediaLibrary::setVerbosity
*/
LogLevel logLevel = LogLevel::Error;
......@@ -222,6 +232,8 @@ struct SetupConfig
* If nullptr is provided, the default IOstream logger will be used.
*/
std::shared_ptr<ILogger> logger;
std::shared_ptr<ICacher> cacher;
};
class IMediaLibraryCb
......@@ -272,12 +284,16 @@ public:
virtual void onFoldersModified( std::set<int64_t> folderIds ) = 0;
virtual void onFoldersDeleted( std::set<int64_t> folderIds ) = 0;
virtual void onSubscriptionsAdded( std::vector<SubscriptionPtr> subscriptions ) = 0;
virtual void onSubscriptionsModified( std::set<int64_t> subscriptionIds ) = 0;
virtual void onSubscriptionsDeleted( std::set<int64_t> subscriptionsIds ) = 0;
/**
* @brief onDiscoveryStarted This callback will be invoked when the discoverer
* starts to crawl an entrypoint that was scheduled for discovery or reload.
* starts to crawl a root folder that was scheduled for discovery or reload.
*
* This callback will be invoked when the discoverer thread gets woken up
* regardless of how many entry points need to be discovered.
* regardless of how many roots need to be discovered.
*/
virtual void onDiscoveryStarted() = 0;
/**
......@@ -285,7 +301,7 @@ public:
* discoverer enters a new folder.
* @param currentFolder The folder being discovered
*
* This callback can be invoked multiple times even though a single entry point was asked to be
* This callback can be invoked multiple times even though a single root was asked to be
* discovered. ie. In the case of a file system discovery, discovering a folder would make this
* callback being invoked for all subfolders
*/
......@@ -294,58 +310,57 @@ public:
* @brief onDiscoveryCompleted Will be invoked when the discoverer finishes
* all its queued operations and goes back to idle.
*
* This callback will be invoked once for each invocation fo onDiscoveryStarted
* This callback will be invoked once for each invocation of onDiscoveryStarted
*/
virtual void onDiscoveryCompleted() = 0;
/**
* @brief onDiscoveryFailed Will be invoked when a discovery operation fails
* @param entryPoint The entry point for which the discovery failed.
* @param root The root folder for which the discovery failed.
*/
virtual void onDiscoveryFailed( const std::string& entryPoint ) = 0;
virtual void onDiscoveryFailed( const std::string& root ) = 0;
/**
* @brief onEntryPointAdded will be invoked when an entrypoint gets added
* @param entryPoint The entry point which was scheduled for discovery
* @brief onRootAdded will be invoked when an root folder is added
* @param root The root folder which was scheduled for discovery
* @param success A boolean to represent the operation's success
*
* This callback will only be emitted the first time the entry point gets
* This callback will only be emitted the first time the root folder is
* processed, after it has been inserted to the database.
* In case of failure, it might be emited every time the request is sent, since
* the provided entry point would most likely be invalid, and couldn't be inserted.
* Later processing of that entry point will still cause \sa{onDiscoveryStarted}
* In case of failure, it might be emitted every time the request is sent, since
* the provided folder would most likely be invalid, and couldn't be inserted.
* Later processing of the folder will still cause \sa{onDiscoveryStarted}
* \sa{onDiscoveryProgress} and \sa{onDiscoveryCompleted} events to be fired
* \warning This event will be fired after \sa{onDiscoveryStarted} since we
* don't know if an entry point is known before starting its processing
* don't know if a root folder is known before starting its processing
*/
virtual void onEntryPointAdded( const std::string& entryPoint, bool success ) = 0;
virtual void onRootAdded( const std::string& root, bool success ) = 0;
/**
* @brief onEntryPointRemoved will be invoked when an entrypoint removal
* request gets processsed
* by the appropriate worker thread.
* @param entryPoint The entry point which removal was required
* @brief onRootRemoved will be invoked when a root removal request is
* processsed by the appropriate worker thread.
* @param root The root folder which removal was required
* @param success A boolean representing the operation's success
*/
virtual void onEntryPointRemoved( const std::string& entryPoint, bool success ) = 0;
virtual void onRootRemoved( const std::string& root, bool success ) = 0;
/**
* @brief onEntryPointBanned will be called when an entrypoint ban request
* is done being processed.
* @param entryPoint The banned entrypoint
* @brief onRootBanned will be called when a root ban request
* has been processed.
* @param root The banned root folder
* @param success A boolean representing the operation's success
*/
virtual void onEntryPointBanned( const std::string& entryPoint, bool success ) = 0;
virtual void onRootBanned( const std::string& root, bool success ) = 0;
/**
* @brief onEntryPointUnbanned will be called when an entrypoint unban request
* is done being processed.
* @param entryPoint The unbanned entrypoint
* @brief onRootUnbanned will be called when a root unban request
* is done being processed.
* @param root The unbanned root folder
* @param success A boolean representing the operation's success
*/
virtual void onEntryPointUnbanned( const std::string& entryPoint, bool success ) = 0;
virtual void onRootUnbanned( const std::string& root, bool success ) = 0;
/**
* @brief onParsingStatsUpdated Called when the parser statistics are updated
*
* There is no waranty about how often this will be called.
* There is no warranty about how often this will be called.
* @param opsDone The number of operation the parser completed
* @param opsScheduled The number of operations currently scheduled by the parser
*
......@@ -389,7 +404,7 @@ public:
* IMediaLibrary::clearDatabase. After doing so, the medialibrary can still
* be used without any further calls (but will need to rescan the entire user
* collection). If clearDatabase isn't called, the database should be
* considered as corrupted, and therefor the medialibrary considered unusable.
* considered as corrupted, and therefore the medialibrary considered unusable.
*
* If clearSuggested is false, there are no certain way of knowing if the
* database is still usable or not.
......@@ -400,10 +415,34 @@ public:
/**
* @brief onRescanStarted will be invoked when a rescan is started.
*
* This won't be emited when the media library issues a rescan itself, due
* This won't be emitted when the media library issues a rescan itself, due
* to a migration.
*/
virtual void onRescanStarted() = 0;
/**
* @brief onSubscriptionNewMedia will be invoked when some media are added to
* one or more subscription(s)
* @param subscriptionId The subscription ID(s)
*/
virtual void onSubscriptionNewMedia( std::set<int64_t> subscriptionId ) = 0;
/**
* @brief onSubscriptionCacheUpdated Invoked after at least a media changed cached status
* for a subscription.
* @param subscriptionId The subscription for which the cache was updated
*
* If the subscription by the cache worker didn't change, this will not
* be invoked.
*/
virtual void onSubscriptionCacheUpdated( int64_t subscriptionId ) = 0;
/**
* @brief onCacheIdleChanged Will be invoked when the background cache worker
* changes its idle state
* @param idle true if the worker went back to idle, false if it resumed, meaning
* some media and/or subscriptions are being cached.
*/
virtual void onCacheIdleChanged( bool idle ) = 0;
};
class IMediaLibrary
......@@ -430,11 +469,45 @@ public:
*/
virtual InitializeResult initialize( IMediaLibraryCb* mlCallback ) = 0;
/**
* @brief setVerbosity Sets the log level
* @param v The required log level
*
* This defaults to Error.
*/
virtual void setVerbosity( LogLevel v ) = 0;
/**
* @brief createLabel Create a label that can be assigned to various entities
* @param label The label name
* @return A label instance
*
* Creating 2 labels with the same name is considered an error and will
* throw a ConstraintUnique exception
*/
virtual LabelPtr createLabel( const std::string& label ) = 0;
/**
* @brief deleteLabel Delete a label from the database
* @param label An instance of the label to be deleted
* @return true if the label was deleted, false otherwise
*/
virtual bool deleteLabel( LabelPtr label ) = 0;
/**
* @brief media Fetch a media by its ID
* @param mediaId The ID of the media to fetch
* @return A media instance, or nullptr in case of error or if no media matched
*/
virtual MediaPtr media( int64_t mediaId ) const = 0;
/**
* @brief media Attempts to fetch a media by its MRL
* @param mrl The MRL of the media to fetch
* @return A media instance or nullptr in case of error or if no media matched
*
* This will attempt to fetch an external media with the given MRL first, and
* will then attempt to fetch an analyzed media.
* Even if the media is removable, the MRL must represent the absolute path
* to the media
*/
virtual MediaPtr media( const std::string& mrl ) const = 0;
/**
* @brief addExternalMedia Adds an external media to the list of known media
......@@ -465,11 +538,11 @@ public:
virtual bool removeExternalMedia( MediaPtr media ) = 0;
/**
* @brief audioFiles Returns the media classified as Audio
* @brief mediaFiles Returns the media unclassified
* @param params Some query parameters.
* @return A query representing the results set
*
* All media accessors throughout the media library suppor the same sorting
* All media accessors throughout the media library supports the same sorting
* criteria, which are:
* - Duration
* - InsertionDate
......@@ -480,13 +553,21 @@ public:
* - FileSize
* Default sorting parameter uses the media's title, in ascending order
*/
virtual Query<IMedia> mediaFiles( const QueryParameters* params = nullptr ) const = 0;
/**
* @brief audioFiles Returns the media classified as Audio
* @param params Some query parameters.
* @return A query representing the results set
*
* \see{IMediaLibrary::mediaFiles} for the supported sorting criteria
*/
virtual Query<IMedia> audioFiles( const QueryParameters* params = nullptr ) const = 0;
/**
* @brief videoFiles Returns the media classified as Video
* @param params Some query parameters.
* @return A query representing the results set
*
* \see{IMediaLibrary::audioFile} for the supported sorting criteria
* \see{IMediaLibrary::mediaFiles} for the supported sorting criteria
*/
virtual Query<IMedia> videoFiles( const QueryParameters* params = nullptr ) const = 0;
......@@ -495,10 +576,19 @@ public:
* @param params Some query parameters.
* @return A query representing the results set
*
* \see{IMediaLibrary::videoFiles} for the supported sorting criteria
* \see{IMediaLibrary::audioFiles} for the supported sorting criteria
*/
virtual Query<IMedia> movies( const QueryParameters* params = nullptr ) const = 0;
/**
* @brief subscriptionMedia Returns the media discovered in subscriptions
* @param params Some query parameters.
* @return A query representing the results set
*
* \see{IMediaLibrary::audioFiles} for the supported sorting criteria
*/
virtual Query<IMedia> subscriptionMedia( const QueryParameters* params = nullptr ) const = 0;
/**
* @brief inProgressMedia Returns media for which playback wasn't completed
* @param type The type of media to fetch, or 'Unknown' for all
......@@ -556,7 +646,7 @@ public:
virtual Query<IMediaGroup> searchMediaGroups( const std::string& pattern,
const QueryParameters* params = nullptr ) const = 0;
/**
* @brief regroupAll Attemps to regroup all media that belong to a forced singleton group
* @brief regroupAll Attempts to regroup all media that belong to a forced singleton group
*
* This will try to regroup all media that were manually removed from their
* group, and now belong to a forced singleton group.
......@@ -577,6 +667,7 @@ public:
virtual ShowPtr show( int64_t id ) const = 0;
virtual MoviePtr movie( int64_t id ) const = 0;
virtual ArtistPtr artist( int64_t id ) const = 0;
virtual SubscriptionPtr subscription( int64_t id ) const = 0;
virtual Query<IShow> shows( const QueryParameters* params = nullptr ) const = 0;
virtual Query<IShow> searchShows( const std::string& pattern,
const QueryParameters* params = nullptr ) const = 0;
......@@ -628,35 +719,58 @@ public:
/**
* History
*/
virtual Query<IMedia> history() const = 0;
/**
* @brief history Fetch the media already played.
* @param type Filter the history.
* @params params Some query parameters, supports what is already supported for media listing.
* Default sort is descending last play date.
*/
virtual Query<IMedia> history( HistoryType, const QueryParameters* params = nullptr ) const = 0;
/**
* @brief audioHistory Fetch the local audio history.
* @params params Some query parameters, supports what is already supported for media listing.
* Default sort is descending last play date.
*
* @note There's no way to filter network history with media types for now. Hence the lack of
* HistoryType parameters.
*/
virtual Query<IMedia> audioHistory( const QueryParameters* params = nullptr ) const = 0;
/**
* @brief history Returns the history for media of the provided type
* @param type Can be either Audio or Video. Other types are not supported
* @brief videoHistory Fetch the local video history.
* @params params Some query parameters, supports what is already supported for media listing.
* Default sort is descending last play date.
*
* @note There's no way to filter network history with media types for now. Hence the lack of
* HistoryType parameters.
*/
virtual Query<IMedia> history( IMedia::Type type ) const = 0;
virtual Query<IMedia> streamHistory() const = 0;
virtual Query<IMedia> videoHistory( const QueryParameters* params = nullptr ) const = 0;
/**
* @brief clearHistory will clear both streams history & media history.
* @param type Filter the history to clear.
* @return true in case of success, false otherwise. The database will stay untouched in case
* of failure.
*
* This will clear all history, and also reset any potential playback progress
* for all media
*/
virtual bool clearHistory() = 0;
virtual bool clearHistory(HistoryType) = 0;
/**
* Search
*/
/**
* @brief searchMedia, searchAudio, and searchVideo search for some media, based on a pattern.
* @brief searchMedia, searchAudio, searchMovie, and searchVideo search for some media, based on a pattern.
* @param pattern A 3 character or more pattern that will be matched against the media's title
* or filename if no title was set for this media.
* @param params Some query parameters.
*
* Only media that were discovered by the medialibrary will be included.
* For instance, media that are added explicitely, playlist items that
* For instance, media that are added explicitly, playlist items that
* point to remote content, will *not* be included
*
* \see{IMediaLibrary::audioFile} for the supported sorting criteria
......@@ -667,8 +781,20 @@ public:
const QueryParameters* params = nullptr ) const = 0;
virtual Query<IMedia> searchVideo( const std::string& pattern,
const QueryParameters* params = nullptr ) const = 0;
virtual Query<IMedia> searchMovie( const std::string& pattern,
const QueryParameters* params = nullptr ) const = 0;
/**
* @brief searchSubscriptionMedia search a subscription media.
* @param pattern A 3 character or more pattern that will be matched against the media's title
* or filename if no title was set for this media.
* @param params Some query parameters.
*/
virtual Query<IMedia>
searchSubscriptionMedia( const std::string& pattern,
const QueryParameters* params = nullptr ) const = 0;
virtual Query<IPlaylist> searchPlaylists( const std::string& name,
virtual Query<IPlaylist> searchPlaylists( const std::string& name, PlaylistType type,
const QueryParameters* params = nullptr ) const = 0;
virtual Query<IAlbum> searchAlbums( const std::string& pattern,
const QueryParameters* params = nullptr ) const = 0;
......@@ -680,15 +806,15 @@ public:
const QueryParameters* params = nullptr ) const = 0;
/**
* @brief discover Launch a discovery on the provided entry point.
* @brief discover Launch a discovery on the provided root folder.
* This will start the discoverer thread, device listers, and file system
* factories if needed
* The actuall discovery will run asynchronously, meaning this method will immediatly return.
* The actual discovery will run asynchronously, meaning this method will immediately return.
* Depending on which discoverer modules where provided, this might or might not work
* @note This must be called after initialize()
* @param entryPoint The MRL of the entrypoint to discover.
* @param root The MRL of the root folder to discover.
*/
virtual void discover( const std::string& entryPoint ) = 0;
virtual void discover( const std::string& root ) = 0;
/**
* @brief setDiscoverNetworkEnabled Enable discovery of network shares
* @return true In case of success, false otherwise.
......@@ -717,14 +843,15 @@ public:
*
* This is essentially a way of knowing what has been passed to discover()
* throughout the database life.
* The resulting list includes entry points on device that are currently unmounted.
* The resulting list includes root folders on device that are currently
* unmounted.
* If the passed params field publicOnly is true, this function will list
* top level public folders instead of the folders provided to discover()
*/
virtual Query<IFolder> roots( const QueryParameters* params ) const = 0;
/**
* @brief isIndexed Returns true if the mrl point to a file of folder in an
* indexed entrypoint
* @brief isIndexed Returns true if the mrl point to a file or folder in an
* indexed root.
* @param mrl The MRL to probe
* @return true if the mrl is indexed, false otherwise
*/
......@@ -757,7 +884,7 @@ public:
* would return a query containing 'z' and 'c' as the other folders are
* not containing any media.
* In case a non flattened list is desired, the
* entryPoints() & IFolder::subFolders() functions should be used.
* roots() & IFolder::subFolders() functions should be used.
*/
virtual Query<IFolder> folders( IMedia::Type type,
const QueryParameters* params = nullptr ) const = 0;
......@@ -767,10 +894,10 @@ public:
virtual FolderPtr folder( int64_t folderId ) const = 0;
virtual FolderPtr folder( const std::string& mrl ) const = 0;
/**
* @brief removeEntryPoint Removes an entry point
* @param entryPoint The MRL of the entry point to remove
* @brief removeRoot Removes a root folder
* @param root The MRL of the root folder point to remove
*
* This will remove the provided entry point from the list of know locations
* This will remove the provided root folder from the list of know locations
* to manage by the media library.
* The location will be ignored afterward, even if it is a sub folder of
* another managed location.
......@@ -780,9 +907,9 @@ public:
* task
* @note This must be called after initialize()
*/
virtual void removeEntryPoint( const std::string& entryPoint ) = 0;
virtual void removeRoot( const std::string& root ) = 0;
/**
* @brief banFolder will prevent an entry point folder from being discovered.
* @brief banFolder will prevent a root folder from being discovered.
* If the folder was already discovered, it will be removed prior to the ban, and all
* associated media will be discarded.
* @param mrl The MRL to ban
......@@ -793,9 +920,9 @@ public:
*/
virtual void banFolder( const std::string& mrl ) = 0;
/**
* @brief unbanFolder Unban an entrypoint.
* In case this entry point was indeed previously banned, this will issue a reload of
* that entry point
* @brief unbanFolder Unban a root folder.
* In case this root folder was indeed previously banned, this will issue a
* reload of that folder
* @param mrl The MRL to unban
* @note This method is asynchronous, but will interrupt any ongoing
* discovery, process the request, and resume the previously running
......@@ -804,12 +931,12 @@ public:
*/
virtual void unbanFolder( const std::string& mrl ) = 0;
/**
* @brief bannedEntryPoints Returns a query representing the banned entry points
* @brief bannedRoots Returns a query representing the banned root folders.
*
* The result set will include entry points on missing devices as well. Folder
* hierarchy isn't preserved, and the results are flattened.
* The result set will include root folders on missing devices as well.
* Folder hierarchy isn't preserved, and the results are flattened.
*/
virtual Query<IFolder> bannedEntryPoints() const = 0;
virtual Query<IFolder> bannedRoots() const = 0;
/**
* @brief pauseBackgroundOperations Will stop potentially CPU intensive background
* operations, until resumeBackgroundOperations() is called.
......@@ -822,7 +949,7 @@ public:
*/
virtual void resumeBackgroundOperations() = 0;
/**
* @brief reload Reload all known entry points
* @brief reload Reload all known roots
* @note This must be called after initialize()
*
* This will start the discoverer thread, appropriate device listers and
......@@ -830,14 +957,14 @@ public:
*/
virtual void reload() = 0;
/**
* @brief reload Reload a specific entry point
* @param entryPoint The entrypoint to reload
* @brief reload Reload a specific root folder.
* @param root The root folder to reload
* @note This must be called after initialize()
*
* This will start the discoverer thread, appropriate device listers and
* file system factories if needed.
*/
virtual void reload( const std::string& entryPoint ) = 0;
virtual void reload( const std::string& root ) = 0;
/**
* @brief forceParserRetry Forces a re-run of all metadata parsers and resets any
* unterminated file retry count to 0, granting them 3 new tries at being parsed
......@@ -871,7 +998,7 @@ public:
/**
* @brief enableFailedThumbnailRegeneration Allow failed thumbnail attempt to be retried
*
* This will not attempt to regenerate the thumbnail immediatly, requestThumbnail
* This will not attempt to regenerate the thumbnail immediately, requestThumbnail
* still has to be called afterward.
*/
virtual void enableFailedThumbnailRegeneration() = 0;
......@@ -929,7 +1056,7 @@ public:
* This will delete *ALL* removable devices from the database, causing *ALL*
* files & media stored on that device to be deleted as well.
* This is intended for applications with an external device lister to
* recover in case of an issue causing multiple devices or invalide entries
* recover in case of an issue causing multiple devices or invalid entries
* to be inserted in the database
*/
virtual bool deleteRemovableDevices() = 0;
......@@ -946,10 +1073,34 @@ public:
*/
virtual bool isSubtitleExtensionSupported( const char* ext ) const = 0;
/**
* @brief requestThumbnail Request an asynchronous thumbnail generation
* @param mediaId The media for which to generate a thumbnail
* @param sizeType A value representing the type of thumbnail size
* @param desiredWidth The desired width
* @param desiredHeight The desired height
* @param position A position in the range [0;1]
* @return true if the request has been scheduled
*
* When the thumbnail is generated, IMediaLibraryCb::onMediaThumbnailReady
* will be invoked from the thumbnailer thread.
* If this is invoked multiple time before the original request is processed,
* the later requests will be ignored, and no callback will be invoked before
* the first one has completed.
* The desired width or height might be 0 to automatically infer one from the
* other by respecting the source aspect ratio.
* If both sizes are provided, the resulting thumbnail will be cropped to
* abide by the source aspect ratio.
*/
virtual bool requestThumbnail( int64_t mediaId, ThumbnailSizeType sizeType,
uint32_t desiredWidth, uint32_t desiredHeight,
float position ) = 0;
/**
* @brief bookmark Returns the bookmark with the given ID
* @param bookmarkId The bookmark ID
* @return A bookmark instance, or nullptr if no bookmark has this ID
*/
virtual BookmarkPtr bookmark( int64_t bookmarkId ) const = 0;
/**
......@@ -964,6 +1115,12 @@ public:
*/
virtual bool setExternalLibvlcInstance( libvlc_instance_t* inst ) = 0;
/**
* @brief acquirePriorityAccess Acquires a priority context for the calling thread
* @return A PriorityAccess wrapper object.
*
* The returned object will release its priority context when it gets destroyed.
*/
virtual PriorityAccess acquirePriorityAccess() = 0;
/**
......@@ -976,6 +1133,101 @@ public:
* thumbnail for will not have a thumbnail associated with it anymore.
*/
virtual bool flushUserProvidedThumbnails() = 0;
virtual bool removeSubscription( int64_t subscriptionId ) = 0;
/**
* @brief cacheNewSubscriptionMedia Asynchronously starts a caching of new subscription media
*/
virtual void cacheNewSubscriptionMedia() = 0;
/**
* @brief fitsInSubscriptionCache Checks if the provided media will fit in
* the subscription cache
* @param m The media to probe
* @return true if the media fits *or if its size is unknown* false otherwise
*
* This will use the associated files to figure out the size on disk. If the
* size is unknown, true will be returned, and the size will be updated in
* database when caching is attempted.
* The media will fit in cache if:
* - The global maximum cache size allows for it to fit
* - Its associated subscription maximum cache size allows it to fit as well
* The maximum number of media, be it global or for the associated
* subscription, it *not* taken into account for this.
*/
virtual bool fitsInSubscriptionCache( const IMedia& m ) const = 0;
/**
* @brief service Returns an object representing a service
* @param type The service type
* @return A service instance, or nullptr if the service isn't available
*/
virtual ServicePtr service( IService::Type type ) const = 0;
/**
* @brief subscription Returns an object representing a subscription
* @param id The subscription's id
* @return A Subscription instance, or a nullptr if the id matches no
* subscription
* Subscriptions usually should be instantiated through their service, but
* this becomes useful in a JNI context where we can only instantiate
* through an ID.
*/
virtual SubscriptionPtr subscription( uint64_t id ) const = 0;
/**
* @brief setSubscriptionMaxCachedMedia Sets the maximum number of cached media
* for each subscription
* @param nbCachedMedia The number of media to automatically cache
* @return true if the change was successful, false otherwise
*
* This setting will be used when a subscription is set to inherit the global
* setting, but each subscription can individually override this setting.
*/
virtual bool setSubscriptionMaxCachedMedia( uint32_t nbCachedMedia ) = 0;
/**
* @brief setSubscriptionMaxCacheSize Sets the maximum cache size for each subscriptions
* @param maxCacheSize The size of each subscription cache in bytes
* @return true if the change was successful, false otherwise
*
* This setting will be used when a subscription is set to inherit the global
* setting, but each subscription can individually override this setting.
*/
virtual bool setSubscriptionMaxCacheSize( uint64_t maxCacheSize ) = 0;
/**
* @brief setMaxCacheSize Sets the maximum overall cache size
* @param nbCacheMedia The size the global cache in bytes
* @return true if the change was successful, false otherwise
*/
virtual bool setMaxCacheSize( uint64_t maxCacheSize ) = 0;
/**
* @brief getSubscriptionMaxCachedMedia Gets the maximum number of cached media
* for each subscription
* @return maximum number of cached media for each subscription
*
* This setting will be used when a subscription is set to inherit the global
* setting, but each subscription can individually override this setting.
*/
virtual uint32_t getSubscriptionMaxCachedMedia() const = 0;
/**
* @brief getSubscriptionMaxCacheSize Gets the maximum cache size for each subscriptions
* @return maximum cache size for each subscriptions
*
* This setting will be used when a subscription is set to inherit the global
* setting, but each subscription can individually override this setting.
*/
virtual uint64_t getSubscriptionMaxCacheSize() const = 0;
/**
* @brief getMaxCacheSize Gets the maximum overall cache size
* @return maximum overall cache size
*/
virtual uint64_t getMaxCacheSize() const = 0;
/**
* @brief refreshAllSubscriptions Queue refresh tasks for each subscriptions.
* @return true if all the subscriptions were refreshed successfully.
*/
virtual bool refreshAllSubscriptions() = 0;
};
}
......
......@@ -22,6 +22,7 @@
#pragma once
#include <cstdint>
#include <string>
namespace medialibrary
......
......@@ -96,11 +96,7 @@ public:
/// \param params A QueryParameters object or nullptr for the default params
/// \return A query object representing the media in this playlist
///
/// The media will always be sorted by their ascending position in the
/// playlist, meaning QueryParameters::sort & QueryParameters::desc will be
/// ignored.
/// QueryParameters::includeMissing will be used however, so the called can
/// get the missing media for the playlist
/// \note The media will be sorted by their ascending position in the playlist by default.
///
virtual Query<IMedia> media( const QueryParameters* params ) const = 0;
///
......@@ -127,19 +123,48 @@ public:
/// If the position is greater than the playlist size, it will be interpreted
/// as a regular append operation, and the item position will be set to
/// <playlist size>
/// For instance, on the playlist [<B,0>, <A,1>, <C,2>], if add(D, 999)
/// gets called, the resulting playlist will be [<A,0>, <C,1>, <B,2>, <D,3>]
/// For instance, on the playlist [<A,0>, <B,1>, <C,2>], if add(D, 999)
/// gets called, the resulting playlist will be [<A,0>, <B,1>, <C,2>, <D,3>]
///
virtual bool add( const IMedia& media, uint32_t position ) = 0;
/// \brief append a list of medias to a playlist
/// The medias will be the last element of a subsequent call to media()
/// \param mediaList The medias to add
/// \return true on success, false on failure.
///
/// For instance on the playlist [<A,0>, <B,1>, <C,2>], if apend([D,E])
/// gets called, the resulting playlist will be [<A,0>, <B,1>, <C,2>, <D,3>, <E,4>]
///
virtual bool append( const std::vector<MediaPtr>& mediaList ) = 0;
///
/// \brief add Add a list of medias to the playlist at the given position.
/// \param mediaList The medias to add
/// \param position The position of this new medias, in the [0;size-1] range
/// \return true on success, false on failure
///
/// For instance on the playlist [<A,0>, <B,1>, <C,2>], if apend([D,E], 2)
/// gets called, the resulting playlist will be [<A,0>, <B,1>, <D,2>, <E,3>, <C,4>]
///
/// If the position is greater than the playlist size, it will be interpreted
/// as a regular append operation, and the item position will be set to
/// <playlist size
/// For instance, on the playlist [<A,0>, <B,1>, <C,2>], if add([D,E], 999)
/// gets called, the resulting playlist will be [<A,0>, <B,1>, <C,2>, <D,3>, <E,4>]
///
virtual bool add( const std::vector<MediaPtr>& mediaList, uint32_t position ) = 0;
/// Convenience wrappers
virtual bool append( int64_t mediaId ) = 0;
virtual bool add( int64_t mediaId, uint32_t position ) = 0;
virtual bool append( const std::vector<int64_t>& mediaList ) = 0;
virtual bool add( const std::vector<int64_t>& mediaList, uint32_t position ) = 0;
///
/// \brief move Change the position of a media
/// \param from The position of the item being moved
/// \param to The moved item target position
/// \param count The number of elements to move
///
/// \return true on success, false on failure
///
......@@ -149,21 +174,35 @@ public:
/// [<A,0>, <B,1>, <C,2>] on which move(0, 1) is called will result in the
/// playlist being changed to
/// [<B,0>, <A,1>, <C,2>]
///
/// Likewise, when moving multiple elements:
/// On the playlist [<A,0>, <B,1>, <C,2>, <D,3>, <E,4>], move(1, 3, 2) results in
/// [<A,0>, <D,1>, <B,2>, <C,3>, <E,4>]
///
/// Moving one or multiple elements at the same position or within its range has no effects.
/// On the playlist [<A,0>, <B,1>, <C,2>, <D,3>, <E,4>], move(1,1) or move(2,3,2)
/// doesn't alter the playlist. Modification won't be notified, the function returns true
///
/// If the target position is out of range (ie greater than the playlist size)
/// the target position will be interpreted as the playlist size (prior to insertion).
/// For instance, on the playlist [<B,0>, <A,1>, <C,2>], if move(0, 999)
/// gets called, the resulting playlist will be [<A,0>, <C,1>, <B,2>]
/// For instance, on the playlist [<A,0>, <B,1>, <C,2>], if move(0, 999)
/// gets called, the resulting playlist will be [<B,0>, <C,1>, <A,2>].
///
virtual bool move( uint32_t from, uint32_t to ) = 0;
virtual bool move( uint32_t from, uint32_t to, uint32_t count = 1 ) = 0;
///
/// \brief remove Removes an item from the playlist
/// \brief remove Removes a range of items from the playlist
/// \param position The position of the item to remove.
/// \param count The number of element to remove (one by default)
/// \return true on success, false on failure
///
virtual bool remove( uint32_t position ) = 0;
/// For instance, a playlist with <media,position> like
/// [<A,0>, <B,1>, <C,2>, <D,3>] on which remove(1, 2) is called will result in the
/// playlist being changed to[<A,0>, <D,1>]
///
virtual bool remove( uint32_t position, uint32_t count = 1 ) = 0;
///
/// \brief isReadOnly Return true if the playlist is backed by an actual file
/// and should therefor not modified directly.
/// and should therefore not modified directly.
/// \return true if the playlist should be considered read-only, false otherwise
///
/// If the application doesn't respect this, the medialibrary will, for
......@@ -179,6 +218,9 @@ public:
/// In case of errors, an empty string will be returned.
///
virtual std::string mrl() const = 0;
virtual bool isFavorite() const = 0;
virtual bool setFavorite( bool favorite ) = 0;
};
}
......@@ -45,7 +45,7 @@ public:
/**
* @brief items returns a subset of a query result
* @param nbItems The number of item requested
* @param offset The number of elements to omit from the begining of the result
* @param offset The number of elements to omit from the beginning of the result
* @return A vector of shared pointer for the requested type.
*
* If nbItems & offset are both 0, then this method returns all results.
......
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2022 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#pragma once
#include "IQuery.h"
#include <string>
namespace medialibrary
{
class ISubscription;
class IMedia;
struct QueryParameters;
/**
* @brief The IService interface represents a service that can allow the user
* to import subscriptions
*/
class IService
{
public:
enum class Type : uint8_t
{
/*
* The type is used as the service's primary key, so any valid value
* must be != 0
*/
Podcast = 1,
};
virtual ~IService() = default;
virtual Type type() const = 0;
virtual bool isAutoDownloadEnabled() const = 0;
virtual bool setAutoDownloadEnabled( bool enabled ) = 0;
/**
* @brief newMediaNotification Returns true if new content for this service
* should issue a notification
*
* Each subscription can override this setting, or inherit it.
*/
virtual bool isNewMediaNotificationEnabled() const = 0;
virtual bool setNewMediaNotificationEnabled( bool enabled ) = 0;
/**
* @brief maxCacheSize Returns the maximum size of the cache for all of this service
* @return The maximum cache size or -1 if the limit isn't set for this service
*
* If the limit isn't set, the global maximum cache size setting will be
* used instead.
*/
virtual int64_t maxCacheSize() const = 0;
/**
* @brief setMaxCacheSize Sets the maximum cache size for this service
* @param maxSize A size in bytes, or -1 to disable the setting for the service
* and inherit the default one.
* @return true if the change was successful, false otherwise.
*/
virtual bool setMaxCacheSize( int64_t maxSize ) = 0;
virtual bool addSubscription( std::string mrl ) = 0;
virtual Query<ISubscription> subscriptions( const QueryParameters* params ) const = 0;
virtual Query<ISubscription> searchSubscription( const std::string& pattern,
const QueryParameters* params ) const = 0;
virtual Query<IMedia> media( const QueryParameters* params ) const = 0;
virtual Query<IMedia> searchMedia( const std::string& pattern,
const QueryParameters* params ) const = 0;
/**
* @brief nbSubscriptions Returns the number of subscriptions associated with this service
*
* This is equivalent to invoking count() on the query returned by subscriptions(), but
* this version will not issue a request and will return an already computed counter.
*/
virtual uint32_t nbSubscriptions() const = 0;
virtual uint32_t nbUnplayedMedia() const = 0;
virtual uint32_t nbMedia() const = 0;
/**
* @brief refresh Queue refresh tasks for each subscriptions of this service.
* @return true if all the subscriptions were refreshed successfully.
*/
virtual bool refresh() = 0;
};
}
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2022 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#pragma once
#include <string>
#include "medialibrary/Types.h"
#include "medialibrary/IQuery.h"
#include "medialibrary/IService.h"
namespace medialibrary
{
struct QueryParameters;
class ISubscription
{
public:
virtual ~ISubscription() = default;
virtual int64_t id() const = 0;
virtual IService::Type service() const = 0;
virtual const std::string& name() const = 0;
virtual Query<ISubscription> childSubscriptions( const QueryParameters* params ) const = 0;
virtual SubscriptionPtr parent() = 0;
virtual Query<IMedia> media( const QueryParameters* params ) const = 0;
virtual Query<IMedia> search( const std::string&, const QueryParameters* ) const = 0;
virtual bool refresh() = 0;
/**
* @brief cachedSize Returns the sum of all cached files for this collection
*/
virtual uint64_t cachedSize() const = 0;
/**
* @brief maxCachedMedia Returns the maximum number of cached media for this
* collection, or -1 is unset
*/
virtual int32_t maxCachedMedia() const = 0;
/**
* @brief setMaxCachedMedia Sets the maximum number of automatically cached media
* @param nbCachedMedia The number of cached media, or a negative value to unset
* @return true if the setting was changed, false otherwise
*
* If this isn't set for the collection, the global setting is used instead.
* If this is set to a negative value, this collection's setting will be
* erased and the parent setting will be used again when caching, however
* the maxCachedMedia will return -1 to denote that this collection inherits
* its setting from its parent.
*/
virtual bool setMaxCachedMedia( int32_t nbCachedMedia ) = 0;
/**
* @brief maxCacheSize Returns the maximum size in bytes for this collection
*
* This will return the collection specific setting, regardless of the global
* setting value.
* In case the value is unset, -1 will be returned. In this case, the parent
* setting will be used when performing caching.
*/
virtual int64_t maxCacheSize() const = 0;
/**
* @brief setMaxCacheSize Sets the maximum cache size for this collection
* @param maxCacheSize The size in bytes for this collection cache, or a
* negative value to use the parent setting.
* @return true if the change was successful, false otherwise.
*
* This will not perform any checks against the global setting, but if this
* is greater than the global maximum cache size, the global setting will
* prevail when caching.
* If passing the current value, this will return true.
*/
virtual bool setMaxCacheSize( int64_t maxCacheSize ) = 0;
/**
* @brief newMediaNotification Returns the new media notification setting
* @return A positive value if explicitly enabled, 0 if explicitly disabled, -1 is unset
*
* If this value is unset, the parent service setting will be used.
*/
virtual int8_t newMediaNotification() const = 0;
/**
* @brief setNewMediaNotification Sets the new media notification setting
* @param value A negative value to default to the parent service setting, 0
* to disable, and a positive value to enable.
* @return true if the change was successful, false otherwise.
*/
virtual bool setNewMediaNotification( int8_t value ) = 0;
/**
* @brief nbUnplayedMedia Returns the number of media that belong to this
* subscription and haven't been played
*/
virtual uint32_t nbUnplayedMedia() const = 0;
/**
* @brief nbMedia Returns the number of media that belong to this
* subscription.
*/
virtual uint32_t nbMedia() const = 0;
/**
* @brief artworkMRL Returns the subscription's artwork MRL.
*
* @note An empty string is returned in case of no artwork MRL is available.
*/
virtual const std::string& artworkMRL() const = 0;
};
}
......@@ -50,6 +50,9 @@ class IFolder;
class ISubtitleTrack;
class IThumbnailer;
class IMediaGroup;
class ISubscription;
class ICacher;
class IService;
namespace parser
{
......@@ -79,6 +82,8 @@ using DeviceListerPtr = std::shared_ptr<IDeviceLister>;
using FolderPtr = std::shared_ptr<IFolder>;
using SubtitleTrackPtr = std::shared_ptr<ISubtitleTrack>;
using MediaGroupPtr = std::shared_ptr<IMediaGroup>;
using SubscriptionPtr = std::shared_ptr<ISubscription>;
using ServicePtr = std::shared_ptr<IService>;
}