You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

318 lines
14 KiB

#include "utils.h"
#define LOG_TAG "VLC/JNI/Utils"
#include "log.h"
utils::jni::object
mediaToMediaWrapper(JNIEnv* env, fields *fields, medialibrary::MediaPtr const& mediaPtr)
{
if (mediaPtr == nullptr)
return {};
const std::vector<medialibrary::FilePtr> files = mediaPtr->files();
if (files.empty())
return {};
//TODO get track, audio & spu track numbers
jint type;
switch (mediaPtr->type()) {
case medialibrary::IMedia::Type::Audio:
type = 1; //MediaWrapper.TYPE_AUDIO
break;
case medialibrary::IMedia::Type::Video:
type = 0; //MediaWrapper.TYPE_VIDEO
break;
default:
type = -1; //MediaWrapper.TYPE_ALL
break;
}
utils::jni::string artist, genre, album, albumArtist, mrl, title, thumbnail, filename;
jint trackNumber = 0, discNumber = 0;
const bool isPresent = mediaPtr->isPresent();
medialibrary::ArtistPtr artistPtr = mediaPtr->artist();
medialibrary::GenrePtr genrePtr = mediaPtr->genre();
medialibrary::AlbumPtr albumPtr = mediaPtr->album();
if (artistPtr != NULL)
artist = vlcNewStringUTF(env, artistPtr->name().c_str());
if (genrePtr != NULL)
genre = vlcNewStringUTF(env, genrePtr->name().c_str());
if (albumPtr!= NULL) {
album = vlcNewStringUTF(env, albumPtr->title().c_str());
medialibrary::ArtistPtr albumArtistPtr = albumPtr->albumArtist();
if (albumArtistPtr != NULL)
albumArtist = vlcNewStringUTF(env, albumArtistPtr->name().c_str());
}
trackNumber = mediaPtr->trackNumber();
discNumber = mediaPtr->discNumber();
const medialibrary::IMetadata& metaAudioTrack = mediaPtr->metadata(medialibrary::IMedia::MetadataType::AudioTrack);
jint audioTrack = metaAudioTrack.isSet() ? metaAudioTrack.asInt() : -2;
const medialibrary::IMetadata& metaSpuTrack = mediaPtr->metadata(medialibrary::IMedia::MetadataType::SubtitleTrack);
jint spuTrack = metaSpuTrack.isSet() ? metaSpuTrack.asInt() : -2;
if (!mediaPtr->title().empty())
title = vlcNewStringUTF(env, mediaPtr->title().c_str());
if (!mediaPtr->fileName().empty())
filename = vlcNewStringUTF(env, mediaPtr->fileName().c_str());
try {
mrl = vlcNewStringUTF(env, files.at(0)->mrl().c_str());
} catch(const medialibrary::fs::errors::DeviceRemoved&) {
mrl = vlcNewStringUTF(env, "missing://");
}
auto thumbnailStr = mediaPtr->thumbnailMrl(medialibrary::ThumbnailSizeType::Thumbnail);
if (!thumbnailStr.empty())
thumbnail = vlcNewStringUTF(env, thumbnailStr.c_str());
std::vector<medialibrary::VideoTrackPtr> videoTracks = mediaPtr->videoTracks()->all();
bool hasVideoTracks = !videoTracks.empty();
unsigned int width = hasVideoTracks ? videoTracks.at(0)->width() : 0;
unsigned int height = hasVideoTracks ? videoTracks.at(0)->height() : 0;
int64_t duration = mediaPtr->duration();
auto hasThumbnail = mediaPtr->thumbnailStatus(medialibrary::ThumbnailSizeType::Thumbnail) == medialibrary::ThumbnailStatus::Available;
auto isFavorite = mediaPtr->isFavorite();
return { env, env->NewObject(fields->MediaWrapper.clazz, fields->MediaWrapper.initID,
(jlong) mediaPtr->id(), mrl.get(), (jlong) mediaPtr->lastTime(), (jfloat) mediaPtr->lastPosition(), (jlong) duration, type,
title.get(), filename.get(), artist.get(), genre.get(), album.get(),
albumArtist.get(), width, height, thumbnail.get(),
audioTrack, spuTrack, trackNumber, discNumber, (jlong) files.at(0)->lastModificationDate(),
(jlong) mediaPtr->playCount(), hasThumbnail, isFavorite, mediaPtr->releaseDate(), isPresent)
};
}
utils::jni::object
convertAlbumObject(JNIEnv* env, fields *fields, medialibrary::AlbumPtr const& albumPtr)
{
auto title = vlcNewStringUTF(env, albumPtr->title().c_str());
auto thumbnailMrl = vlcNewStringUTF(env, albumPtr->thumbnailMrl(medialibrary::ThumbnailSizeType::Thumbnail).c_str());
medialibrary::ArtistPtr artist = albumPtr->albumArtist();
jlong albumArtistId = artist != nullptr ? albumPtr->albumArtist()->id() : 0;
utils::jni::string artistName;
auto isFavorite = albumPtr->isFavorite();
if ( artist != nullptr )
artistName = vlcNewStringUTF(env, artist->name().c_str());
return utils::jni::object{ env, env->NewObject(fields->Album.clazz, fields->Album.initID,
(jlong) albumPtr->id(), title.get(), albumPtr->releaseYear(),
thumbnailMrl.get(), artistName.get(), albumArtistId, (jint) albumPtr->nbTracks(), (jint) albumPtr->nbPresentTracks(), albumPtr->duration(), isFavorite)
};
}
utils::jni::object
convertArtistObject(JNIEnv* env, fields *fields, medialibrary::ArtistPtr const& artistPtr)
{
auto name = vlcNewStringUTF(env, artistPtr->name().c_str());
auto thumbnailMrl = vlcNewStringUTF(env, artistPtr->thumbnailMrl(medialibrary::ThumbnailSizeType::Thumbnail).c_str());
auto shortBio = vlcNewStringUTF(env, artistPtr->shortBio().c_str());
auto isFavorite = artistPtr->isFavorite();
auto musicBrainzId = vlcNewStringUTF(env, artistPtr->musicBrainzId().c_str());
return utils::jni::object{ env, env->NewObject(fields->Artist.clazz, fields->Artist.initID,
(jlong) artistPtr->id(), name.get(), shortBio.get(), thumbnailMrl.get(),
musicBrainzId.get(), (jint) artistPtr->nbAlbums(), (jint) artistPtr->nbTracks(), (jint) artistPtr->nbPresentTracks(), isFavorite)
};
}
utils::jni::object
convertGenreObject(JNIEnv* env, fields *fields, medialibrary::GenrePtr const& genrePtr)
{
auto name = vlcNewStringUTF(env, genrePtr->name().c_str());
auto isFavorite = genrePtr->isFavorite();
return utils::jni::object{ env, env->NewObject(fields->Genre.clazz, fields->Genre.initID,
(jlong) genrePtr->id(), name.get(), (jint) genrePtr->nbTracks(), (jint) genrePtr->nbPresentTracks(), isFavorite)
};
}
utils::jni::object
convertPlaylistObject(JNIEnv* env, fields *fields, medialibrary::PlaylistPtr const& playlistPtr, jboolean includeMissing, jboolean onlyFavorites)
{
auto name = vlcNewStringUTF(env, playlistPtr->name().c_str());
return utils::jni::object{ env, env->NewObject(fields->Playlist.clazz, fields->Playlist.initID,
(jlong) playlistPtr->id(), name.get(), (jint)playlistPtr->nbMedia(), (jlong)playlistPtr->duration(), (jint)playlistPtr->nbVideo(), (jint)playlistPtr->nbAudio(), (jint)playlistPtr->nbUnknown(), (jint)playlistPtr->nbDurationUnknown(), (jboolean)playlistPtr->isFavorite())
};
}
utils::jni::object
convertFolderObject(JNIEnv* env, fields *fields, medialibrary::FolderPtr const& folderPtr, int count)
{
auto name = vlcNewStringUTF(env, folderPtr->name().c_str());
auto mrl = vlcNewStringUTF(env, folderPtr->mrl().c_str());
return utils::jni::object{ env, env->NewObject(fields->Folder.clazz, fields->Folder.initID,
(jlong) folderPtr->id(), name.get(), mrl.get(), (jint) count, (jboolean)folderPtr->isFavorite())
};
}
utils::jni::object
convertVideoGroupObject(JNIEnv* env, fields *fields, medialibrary::MediaGroupPtr const& videogroupPtr)
{
auto name = vlcNewStringUTF(env, videogroupPtr->name().c_str());
return utils::jni::object{ env, env->NewObject(fields->VideoGroup.clazz, fields->VideoGroup.initID,
(jlong) videogroupPtr->id(), name.get(), (jint)videogroupPtr->nbVideo(), (jint)videogroupPtr->nbPresentVideo(), (jint)videogroupPtr->nbPresentSeen(), (jboolean)videogroupPtr->isFavorite())
};
}
utils::jni::object
convertBookmarkObject(JNIEnv* env, fields *fields, medialibrary::BookmarkPtr const& bookmarkPtr)
{
auto name = vlcNewStringUTF(env, bookmarkPtr->name().c_str());
auto description = vlcNewStringUTF(env, bookmarkPtr->description().c_str());
return utils::jni::object{ env, env->NewObject(fields->Bookmark.clazz, fields->Bookmark.initID,
(jlong) bookmarkPtr->id(), name.get(), description.get(), (jlong) bookmarkPtr->mediaId(), (jlong) bookmarkPtr->time())
};
}
utils::jni::object
convertSearchAggregateObject(JNIEnv* env, fields *fields, medialibrary::SearchAggregate const& searchAggregatePtr, jboolean includeMissing, jboolean onlyFavorites)
{
//Albums
utils::jni::objectArray albums;
int index = -1;
if (searchAggregatePtr.albums != nullptr) {
albums = utils::jni::objectArray{ env, (jobjectArray) env->NewObjectArray(searchAggregatePtr.albums->count(), fields->Album.clazz, NULL) };
for(medialibrary::AlbumPtr const& album : searchAggregatePtr.albums->all()) {
auto item = convertAlbumObject(env, fields, album);
env->SetObjectArrayElement(albums.get(), ++index, item.get());
}
}
//Artists
utils::jni::objectArray artists;
if (searchAggregatePtr.artists != nullptr) {
index = -1;
artists = utils::jni::objectArray{ env, (jobjectArray) env->NewObjectArray(searchAggregatePtr.artists->count(), fields->Artist.clazz, NULL) };
for(medialibrary::ArtistPtr const& artist : searchAggregatePtr.artists->all()) {
auto item = convertArtistObject(env, fields, artist);
env->SetObjectArrayElement(artists.get(), ++index, item.get());
}
}
//Genres
utils::jni::objectArray genres;
if (searchAggregatePtr.genres != nullptr) {
index = -1;
genres = utils::jni::objectArray{ env, (jobjectArray) env->NewObjectArray(searchAggregatePtr.genres->count(), fields->Genre.clazz, NULL) };
for(medialibrary::GenrePtr const& genre : searchAggregatePtr.genres->all()) {
auto item = convertGenreObject(env, fields, genre);
env->SetObjectArrayElement(genres.get(), ++index, item.get());
}
}
//Playlists
utils::jni::objectArray playlists;
if (searchAggregatePtr.playlists != nullptr) {
index = -1;
playlists = utils::jni::objectArray{ env, (jobjectArray) env->NewObjectArray(searchAggregatePtr.playlists->count(), fields->Playlist.clazz, NULL) };
for(medialibrary::PlaylistPtr const& playlist : searchAggregatePtr.playlists->all()) {
auto item = convertPlaylistObject(env, fields, playlist, includeMissing, onlyFavorites);
env->SetObjectArrayElement(playlists.get(), ++index, item.get());
}
}
//Media
std::vector<medialibrary::MediaPtr> videos = {};
std::vector<medialibrary::MediaPtr> tracks = {};
utils::jni::objectArray videoList;
utils::jni::objectArray tracksList;
if (searchAggregatePtr.media != nullptr) {
for(medialibrary::MediaPtr const& media : searchAggregatePtr.media->all()) {
if (media->subType() == medialibrary::IMedia::SubType::AlbumTrack) tracks.push_back(media);
else videos.push_back(media);
}
videoList = utils::jni::objectArray{ env, (jobjectArray) env->NewObjectArray(videos.size(), fields->MediaWrapper.clazz, NULL) };
index = -1;
for(medialibrary::MediaPtr const& media : videos) {
auto item = mediaToMediaWrapper(env, fields, media);
env->SetObjectArrayElement(videoList.get(), ++index, item.get());
}
tracksList = utils::jni::objectArray{ env, (jobjectArray) env->NewObjectArray(tracks.size(), fields->MediaWrapper.clazz, NULL) };
index = -1;
for(medialibrary::MediaPtr const& media : tracks) {
auto item = mediaToMediaWrapper(env, fields, media);
env->SetObjectArrayElement(tracksList.get(), ++index, item.get());
}
}
return { env, env->NewObject(fields->SearchAggregate.clazz, fields->SearchAggregate.initID,
albums.get(), artists.get(), genres.get(), videoList.get(), tracksList.get(), playlists.get())
};
}
utils::jni::object
convertSubscriptionObject(JNIEnv* env, fields *fields, medialibrary::SubscriptionPtr const& subsPtr)
{
auto name = vlcNewStringUTF(env, subsPtr->name().c_str());
return utils::jni::object{ env, env->NewObject(fields->Subscription.clazz, fields->Subscription.initID,
(jlong) subsPtr->id(), (jint) subsPtr->service(), name.get())
};
}
utils::jni::object
convertServiceObject(JNIEnv* env, fields *fields, medialibrary::ServicePtr const& servicePtr)
{
return utils::jni::object{ env, env->NewObject(fields->Service.clazz,
fields->Service.initID, (jint) servicePtr->type())
};
}
utils::jni::longArray
idArray(JNIEnv* env, std::set<int64_t> ids)
{
int i = 0;
utils::jni::longArray results{ env, (jlongArray)env->NewLongArray(ids.size()) };
jlong fill[ids.size()];
for (auto id : ids) {
fill[i] = id;
i++;
}
env->SetLongArrayRegion(results.get(), 0, ids.size(), fill);
return results;
}
utils::jni::objectArray
filteredArray(JNIEnv* env, utils::jni::objectArray array, jclass clazz, int removalCount)
{
int size = -1, index = -1;
if (removalCount == -1)
{
removalCount = 0;
size = env->GetArrayLength(array.get());
for (int i = 0; i<size; ++i)
{
utils::jni::object item{ env, env->GetObjectArrayElement(array.get(), i) };
if (item == nullptr)
++removalCount;
}
}
if (removalCount == 0)
return array;
if (size == -1)
size = env->GetArrayLength(array.get());
utils::jni::objectArray mediaRefs{ env, (jobjectArray) env->NewObjectArray(size-removalCount, clazz, NULL) };
for (int i = 0; i<size; ++i)
{
utils::jni::object item{ env, env->GetObjectArrayElement(array.get(), i) };
if (item != nullptr)
{
env->SetObjectArrayElement(mediaRefs.get(), ++index, item.get());
--removalCount;
}
}
return mediaRefs;
}
utils::jni::string
vlcNewStringUTF(JNIEnv* env, const char* psz_string)
{
for (int i = 0 ; psz_string[i] != '\0' ; ) {
uint8_t lead = psz_string[i++];
uint8_t nbBytes;
if ((lead & 0x80) == 0)
continue;
else if ((lead >> 5) == 0x06)
nbBytes = 1;
else if ((lead >> 4) == 0x0E)
nbBytes = 2;
else if ((lead >> 3) == 30)
nbBytes = 3;
else {
LOGE("Invalid UTF lead character\n");
return {};
}
for (int j = 0 ; j < nbBytes && psz_string[i] != '\0' ; j++) {
uint8_t byte = psz_string[i++];
if ((byte & 0x80) == 0) {
LOGE("Invalid UTF byte\n");
return {};
}
}
}
return utils::jni::string{ env, env->NewStringUTF(psz_string) };
}