2020-12-05 13:08:24 +01:00
|
|
|
#include "stdafx.h"
|
2020-02-15 23:36:20 +01:00
|
|
|
#include "Emu/VFS.h"
|
2017-12-28 22:38:29 +01:00
|
|
|
#include "Emu/IdManager.h"
|
2016-03-21 20:43:03 +01:00
|
|
|
#include "Emu/Cell/PPUModule.h"
|
2018-01-12 21:51:22 +01:00
|
|
|
#include "cellMusic.h"
|
|
|
|
|
#include "cellSysutil.h"
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
#include <string>
|
2016-03-21 20:43:03 +01:00
|
|
|
|
2015-02-22 15:50:11 +01:00
|
|
|
#include "cellSearch.h"
|
2020-02-08 11:07:18 +01:00
|
|
|
#include "Utilities/StrUtil.h"
|
2021-06-17 22:44:06 +02:00
|
|
|
#include "util/media_utils.h"
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
|
2018-08-25 14:39:00 +02:00
|
|
|
LOG_CHANNEL(cellSearch);
|
2013-09-28 04:36:57 +02:00
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
template<>
|
|
|
|
|
void fmt_class_string<CellSearchError>::format(std::string& out, u64 arg)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
format_enum(out, arg, [](auto error)
|
|
|
|
|
{
|
|
|
|
|
switch (error)
|
|
|
|
|
{
|
|
|
|
|
STR_CASE(CELL_SEARCH_CANCELED);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_PARAM);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_BUSY);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_NO_MEMORY);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_UNKNOWN_MODE);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_ALREADY_INITIALIZED);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_NOT_INITIALIZED);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_FINALIZING);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_NOT_SUPPORTED_SEARCH);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_CONTENT_OBSOLETE);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_CONTENT_NOT_FOUND);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_NOT_LIST);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_OUT_OF_RANGE);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_INVALID_SEARCHID);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_ALREADY_GOT_RESULT);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_NOT_SUPPORTED_CONTEXT);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_INVALID_CONTENTTYPE);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_DRM);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_TAG);
|
|
|
|
|
STR_CASE(CELL_SEARCH_ERROR_GENERIC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return unknown;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 21:40:21 +01:00
|
|
|
enum class search_state
|
|
|
|
|
{
|
|
|
|
|
not_initialized = 0,
|
|
|
|
|
idle,
|
|
|
|
|
in_progress,
|
|
|
|
|
initializing,
|
|
|
|
|
canceling,
|
|
|
|
|
finalizing,
|
|
|
|
|
};
|
|
|
|
|
|
2019-08-21 21:51:48 +02:00
|
|
|
struct search_info
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
|
|
|
|
vm::ptr<CellSearchSystemCallback> func;
|
|
|
|
|
vm::ptr<void> userData;
|
2020-02-08 21:40:21 +01:00
|
|
|
|
2020-02-19 18:03:59 +01:00
|
|
|
atomic_t<search_state> state = search_state::not_initialized;
|
2020-02-08 18:07:18 +01:00
|
|
|
|
|
|
|
|
shared_mutex links_mutex;
|
|
|
|
|
std::unordered_map<std::string, std::string> content_links;
|
2017-12-28 22:38:29 +01:00
|
|
|
};
|
|
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
struct search_content_t
|
|
|
|
|
{
|
|
|
|
|
CellSearchContentType type = CELL_SEARCH_CONTENTTYPE_NONE;
|
|
|
|
|
CellSearchTimeInfo timeInfo;
|
|
|
|
|
CellSearchContentInfoPath infoPath;
|
|
|
|
|
union
|
|
|
|
|
{
|
|
|
|
|
CellSearchMusicInfo music;
|
|
|
|
|
CellSearchPhotoInfo photo;
|
|
|
|
|
CellSearchVideoInfo video;
|
|
|
|
|
CellSearchMusicListInfo music_list;
|
|
|
|
|
CellSearchPhotoListInfo photo_list;
|
|
|
|
|
CellSearchVideoListInfo video_list;
|
|
|
|
|
CellSearchVideoSceneInfo scene;
|
|
|
|
|
} data;
|
|
|
|
|
};
|
|
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
using content_id_type = std::pair<u64, std::shared_ptr<search_content_t>>;
|
|
|
|
|
|
|
|
|
|
struct content_id_map
|
|
|
|
|
{
|
|
|
|
|
std::unordered_map<u64, std::shared_ptr<search_content_t>> map;
|
|
|
|
|
|
|
|
|
|
shared_mutex mutex;
|
|
|
|
|
};
|
2020-02-08 11:07:18 +01:00
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
struct search_object_t
|
|
|
|
|
{
|
|
|
|
|
// TODO: Figured out the correct values to set here
|
|
|
|
|
static const u32 id_base = 1;
|
|
|
|
|
static const u32 id_step = 1;
|
2020-02-12 16:17:45 +01:00
|
|
|
static const u32 id_count = 1024; // TODO
|
2020-02-08 11:07:18 +01:00
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
std::vector<content_id_type> content_ids;
|
2017-12-28 22:38:29 +01:00
|
|
|
};
|
2021-03-02 17:22:39 +01:00
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
error_code check_search_state(search_state state, search_state action)
|
|
|
|
|
{
|
|
|
|
|
switch (action)
|
|
|
|
|
{
|
|
|
|
|
case search_state::initializing:
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case search_state::not_initialized:
|
|
|
|
|
break;
|
|
|
|
|
case search_state::initializing:
|
|
|
|
|
return CELL_SEARCH_ERROR_BUSY;
|
|
|
|
|
case search_state::finalizing:
|
|
|
|
|
return CELL_SEARCH_ERROR_FINALIZING;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_ALREADY_INITIALIZED;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case search_state::finalizing:
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case search_state::idle:
|
|
|
|
|
break;
|
|
|
|
|
case search_state::not_initialized:
|
|
|
|
|
return CELL_SEARCH_ERROR_NOT_INITIALIZED;
|
|
|
|
|
case search_state::finalizing:
|
|
|
|
|
return CELL_SEARCH_ERROR_FINALIZING;
|
|
|
|
|
case search_state::in_progress:
|
|
|
|
|
case search_state::initializing:
|
|
|
|
|
case search_state::canceling:
|
|
|
|
|
return CELL_SEARCH_ERROR_BUSY;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_GENERIC;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case search_state::canceling:
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case search_state::in_progress:
|
|
|
|
|
break;
|
|
|
|
|
case search_state::not_initialized:
|
|
|
|
|
case search_state::initializing:
|
|
|
|
|
return CELL_SEARCH_ERROR_NOT_INITIALIZED;
|
|
|
|
|
case search_state::finalizing:
|
|
|
|
|
return CELL_SEARCH_ERROR_FINALIZING;
|
|
|
|
|
case search_state::canceling:
|
|
|
|
|
return CELL_SEARCH_ERROR_BUSY;
|
|
|
|
|
case search_state::idle:
|
|
|
|
|
return CELL_SEARCH_ERROR_ALREADY_GOT_RESULT;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_GENERIC;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case search_state::in_progress:
|
|
|
|
|
default:
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case search_state::idle:
|
|
|
|
|
break;
|
|
|
|
|
case search_state::not_initialized:
|
|
|
|
|
case search_state::initializing:
|
|
|
|
|
return CELL_SEARCH_ERROR_NOT_INITIALIZED;
|
|
|
|
|
case search_state::finalizing:
|
|
|
|
|
return CELL_SEARCH_ERROR_FINALIZING;
|
|
|
|
|
case search_state::in_progress:
|
|
|
|
|
case search_state::canceling:
|
|
|
|
|
return CELL_SEARCH_ERROR_BUSY;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_GENERIC;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-17 22:44:06 +02:00
|
|
|
void populate_music_info(CellSearchMusicInfo& info, const utils::media_info& mi, const fs::dir_entry& item)
|
|
|
|
|
{
|
|
|
|
|
parse_metadata(info.artistName, mi, "artist", "Unknown Artist", CELL_SEARCH_TITLE_LEN_MAX);
|
|
|
|
|
parse_metadata(info.albumTitle, mi, "album", "Unknown Album", CELL_SEARCH_TITLE_LEN_MAX);
|
|
|
|
|
parse_metadata(info.genreName, mi, "genre", "Unknown Genre", CELL_SEARCH_TITLE_LEN_MAX);
|
|
|
|
|
parse_metadata(info.title, mi, "title", item.name.substr(0, item.name.find_last_of('.')), CELL_SEARCH_TITLE_LEN_MAX);
|
|
|
|
|
parse_metadata(info.diskNumber, mi, "disc", "1/1", sizeof(info.diskNumber) - 1);
|
|
|
|
|
|
|
|
|
|
// Special case: track is usually stored as e.g. 2/11
|
|
|
|
|
const std::string tmp = mi.get_metadata<std::string>("track", ""s);
|
|
|
|
|
s64 value{};
|
2022-02-17 00:23:28 +01:00
|
|
|
if (tmp.empty() || !try_to_int64(&value, tmp.substr(0, tmp.find('/')).c_str(), s32{smin}, s32{smax}))
|
|
|
|
|
{
|
|
|
|
|
value = -1;
|
|
|
|
|
}
|
2021-06-17 22:44:06 +02:00
|
|
|
|
2022-02-17 00:23:28 +01:00
|
|
|
info.trackNumber = static_cast<s32>(value);
|
2021-06-17 22:44:06 +02:00
|
|
|
info.size = item.size;
|
|
|
|
|
info.releasedYear = static_cast<s32>(mi.get_metadata<s64>("date", -1));
|
|
|
|
|
info.duration = mi.duration_us / 1000; // we need microseconds
|
|
|
|
|
info.samplingRate = mi.sample_rate;
|
2021-06-24 21:26:40 +02:00
|
|
|
info.bitrate = mi.audio_bitrate_bps;
|
|
|
|
|
info.quantizationBitrate = mi.audio_bitrate_bps; // TODO: Assumption, verify value
|
2021-06-17 22:44:06 +02:00
|
|
|
info.playCount = 0; // we do not track this for now
|
|
|
|
|
info.lastPlayedDate = -1; // we do not track this for now
|
|
|
|
|
info.importedDate = -1; // we do not track this for now
|
|
|
|
|
info.drmEncrypted = 0; // TODO: Needs to be 1 if it's encrypted
|
|
|
|
|
info.status = CELL_SEARCH_CONTENTSTATUS_AVAILABLE;
|
|
|
|
|
|
|
|
|
|
// Convert AVCodecID to CellSearchCodec
|
2021-06-24 21:26:40 +02:00
|
|
|
switch (mi.audio_av_codec_id)
|
2021-06-17 22:44:06 +02:00
|
|
|
{
|
|
|
|
|
case 86017: // AV_CODEC_ID_MP3
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_MP3;
|
|
|
|
|
break;
|
|
|
|
|
case 86018: // AV_CODEC_ID_AAC
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_AAC;
|
|
|
|
|
break;
|
|
|
|
|
case 86019: // AV_CODEC_ID_AC3
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_AC3;
|
|
|
|
|
break;
|
|
|
|
|
case 86023: // AV_CODEC_ID_WMAV1
|
|
|
|
|
case 86024: // AV_CODEC_ID_WMAV2
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_WMA;
|
|
|
|
|
break;
|
|
|
|
|
case 86047: // AV_CODEC_ID_ATRAC3
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_AT3;
|
|
|
|
|
break;
|
|
|
|
|
case 86055: // AV_CODEC_ID_ATRAC3P
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_AT3P;
|
|
|
|
|
break;
|
|
|
|
|
case 88078: // AV_CODEC_ID_ATRAC3AL
|
|
|
|
|
//case 88079: // AV_CODEC_ID_ATRAC3PAL TODO: supported ?
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_ATALL;
|
|
|
|
|
break;
|
|
|
|
|
// TODO: Find out if any of this works
|
|
|
|
|
//case 88069: // AV_CODEC_ID_DSD_LSBF
|
|
|
|
|
//case 88070: // AV_CODEC_ID_DSD_MSBF
|
|
|
|
|
//case 88071: // AV_CODEC_ID_DSD_LSBF_PLANAR
|
|
|
|
|
//case 88072: // AV_CODEC_ID_DSD_MSBF_PLANAR
|
|
|
|
|
// info.codec = CELL_SEARCH_CODEC_DSD;
|
|
|
|
|
// break;
|
|
|
|
|
//case ???:
|
|
|
|
|
// info.codec = CELL_SEARCH_CODEC_WAV;
|
|
|
|
|
// break;
|
|
|
|
|
default:
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_UNKNOWN;
|
|
|
|
|
info.status = CELL_SEARCH_CONTENTSTATUS_NOT_SUPPORTED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-02-17 00:48:42 +01:00
|
|
|
|
2022-02-20 10:10:35 +01:00
|
|
|
cellSearch.notice("CellSearchMusicInfo:, title=%s, albumTitle=%s, artistName=%s, genreName=%s, diskNumber=%s, "
|
|
|
|
|
"trackNumber=%d, duration=%d, size=%d, importedDate=%d, lastPlayedDate=%d, releasedYear=%d, bitrate=%d, "
|
|
|
|
|
"samplingRate=%d, quantizationBitrate=%d, playCount=%d, drmEncrypted=%d, codec=%d, status=%d",
|
2022-02-17 00:48:42 +01:00
|
|
|
info.title, info.albumTitle, info.artistName, info.genreName, info.diskNumber,
|
|
|
|
|
info.trackNumber, info.duration, info.size, info.importedDate, info.lastPlayedDate, info.releasedYear, info.bitrate,
|
|
|
|
|
info.samplingRate, info.quantizationBitrate, info.playCount, info.drmEncrypted, info.codec, info.status);
|
2021-06-17 22:44:06 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-24 21:26:40 +02:00
|
|
|
void populate_video_info(CellSearchVideoInfo& info, const utils::media_info& mi, const fs::dir_entry& item)
|
|
|
|
|
{
|
|
|
|
|
parse_metadata(info.albumTitle, mi, "album", "Unknown Album", CELL_SEARCH_TITLE_LEN_MAX);
|
|
|
|
|
parse_metadata(info.title, mi, "title", item.name.substr(0, item.name.find_last_of('.')), CELL_SEARCH_TITLE_LEN_MAX);
|
|
|
|
|
|
|
|
|
|
info.size = item.size;
|
|
|
|
|
info.duration = mi.duration_us / 1000; // we need microseconds
|
|
|
|
|
info.audioBitrate = mi.audio_bitrate_bps;
|
|
|
|
|
info.videoBitrate = mi.video_bitrate_bps;
|
|
|
|
|
info.playCount = 0; // we do not track this for now
|
|
|
|
|
info.importedDate = -1; // we do not track this for now
|
|
|
|
|
info.takenDate = -1; // we do not track this for now
|
|
|
|
|
info.drmEncrypted = 0; // TODO: Needs to be 1 if it's encrypted
|
|
|
|
|
info.status = CELL_SEARCH_CONTENTSTATUS_AVAILABLE;
|
|
|
|
|
|
|
|
|
|
// Convert Video AVCodecID to CellSearchCodec
|
|
|
|
|
switch (mi.video_av_codec_id)
|
|
|
|
|
{
|
|
|
|
|
case 1: // AV_CODEC_ID_MPEG1VIDEO
|
|
|
|
|
info.videoCodec = CELL_SEARCH_CODEC_MPEG1;
|
|
|
|
|
break;
|
|
|
|
|
case 2: // AV_CODEC_ID_MPEG2VIDEO
|
|
|
|
|
info.videoCodec = CELL_SEARCH_CODEC_MPEG2;
|
|
|
|
|
break;
|
|
|
|
|
case 12: // AV_CODEC_ID_MPEG4
|
|
|
|
|
info.videoCodec = CELL_SEARCH_CODEC_MPEG4;
|
|
|
|
|
break;
|
|
|
|
|
case 27: // AV_CODEC_ID_H264
|
|
|
|
|
info.videoCodec = CELL_SEARCH_CODEC_AVC;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
info.videoCodec = CELL_SEARCH_CODEC_UNKNOWN;
|
|
|
|
|
info.status = CELL_SEARCH_CONTENTSTATUS_NOT_SUPPORTED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert Audio AVCodecID to CellSearchCodec
|
|
|
|
|
switch (mi.audio_av_codec_id)
|
|
|
|
|
{
|
|
|
|
|
// Let's ignore this due to CELL_SEARCH_CODEC_MPEG1_LAYER3
|
|
|
|
|
//case 86017: // AV_CODEC_ID_MP3
|
|
|
|
|
// info.audioCodec = CELL_SEARCH_CODEC_MP3;
|
|
|
|
|
// break;
|
|
|
|
|
case 86018: // AV_CODEC_ID_AAC
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_AAC;
|
|
|
|
|
break;
|
|
|
|
|
case 86019: // AV_CODEC_ID_AC3
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_AC3;
|
|
|
|
|
break;
|
|
|
|
|
case 86023: // AV_CODEC_ID_WMAV1
|
|
|
|
|
case 86024: // AV_CODEC_ID_WMAV2
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_WMA;
|
|
|
|
|
break;
|
|
|
|
|
case 86047: // AV_CODEC_ID_ATRAC3
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_AT3;
|
|
|
|
|
break;
|
|
|
|
|
case 86055: // AV_CODEC_ID_ATRAC3P
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_AT3P;
|
|
|
|
|
break;
|
|
|
|
|
case 88078: // AV_CODEC_ID_ATRAC3AL
|
|
|
|
|
//case 88079: // AV_CODEC_ID_ATRAC3PAL TODO: supported ?
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_ATALL;
|
|
|
|
|
break;
|
|
|
|
|
// TODO: Find out if any of this works
|
|
|
|
|
//case 88069: // AV_CODEC_ID_DSD_LSBF
|
|
|
|
|
//case 88070: // AV_CODEC_ID_DSD_MSBF
|
|
|
|
|
//case 88071: // AV_CODEC_ID_DSD_LSBF_PLANAR
|
|
|
|
|
//case 88072: // AV_CODEC_ID_DSD_MSBF_PLANAR
|
|
|
|
|
// info.audioCodec = CELL_SEARCH_CODEC_DSD;
|
|
|
|
|
// break;
|
|
|
|
|
//case ???:
|
|
|
|
|
// info.audioCodec = CELL_SEARCH_CODEC_WAV;
|
|
|
|
|
// break;
|
|
|
|
|
case 86058: // AV_CODEC_ID_MP1
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_MPEG1_LAYER1;
|
|
|
|
|
break;
|
|
|
|
|
case 86016: // AV_CODEC_ID_MP2
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_MPEG1_LAYER2;
|
|
|
|
|
break;
|
|
|
|
|
case 86017: // AV_CODEC_ID_MP3
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_MPEG1_LAYER3;
|
|
|
|
|
break;
|
|
|
|
|
//case ???:
|
|
|
|
|
// info.audioCodec = CELL_SEARCH_CODEC_MPEG2_LAYER1;
|
|
|
|
|
// break;
|
|
|
|
|
//case ???:
|
|
|
|
|
// info.audioCodec = CELL_SEARCH_CODEC_MPEG2_LAYER2;
|
|
|
|
|
// break;
|
|
|
|
|
//case ???:
|
|
|
|
|
// info.audioCodec = CELL_SEARCH_CODEC_MPEG2_LAYER3;
|
|
|
|
|
// break;
|
|
|
|
|
default:
|
|
|
|
|
info.audioCodec = CELL_SEARCH_CODEC_UNKNOWN;
|
|
|
|
|
info.status = CELL_SEARCH_CONTENTSTATUS_NOT_SUPPORTED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-02-17 00:48:42 +01:00
|
|
|
|
2022-02-20 10:10:35 +01:00
|
|
|
cellSearch.notice("CellSearchVideoInfo: title='%s', albumTitle='%s', duration=%d, size=%d, importedDate=%d, takenDate=%d, "
|
|
|
|
|
"videoBitrate=%d, audioBitrate=%d, playCount=%d, drmEncrypted=%d, videoCodec=%d, audioCodec=%d, status=%d",
|
2022-02-17 00:48:42 +01:00
|
|
|
info.title, info.albumTitle, info.duration, info.size, info.importedDate, info.takenDate,
|
|
|
|
|
info.videoBitrate, info.audioBitrate, info.playCount, info.drmEncrypted, info.videoCodec, info.audioCodec, info.status);
|
2021-06-24 21:26:40 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-20 10:10:35 +01:00
|
|
|
void populate_photo_info(CellSearchPhotoInfo& info, const utils::media_info& /*mi*/, const fs::dir_entry& item)
|
|
|
|
|
{
|
|
|
|
|
// TODO - Some kinda file photo analysis and assign the values as such
|
|
|
|
|
info.size = item.size;
|
|
|
|
|
info.importedDate = -1;
|
|
|
|
|
info.takenDate = -1;
|
|
|
|
|
info.width = 0;
|
|
|
|
|
info.height = 0;
|
|
|
|
|
info.orientation = CELL_SEARCH_ORIENTATION_UNKNOWN;
|
|
|
|
|
info.codec = CELL_SEARCH_CODEC_UNKNOWN;
|
|
|
|
|
info.status = CELL_SEARCH_CONTENTSTATUS_AVAILABLE;
|
|
|
|
|
strcpy_trunc(info.title, item.name.substr(0, item.name.find_last_of('.')));
|
|
|
|
|
strcpy_trunc(info.albumTitle, "ALBUM TITLE");
|
|
|
|
|
|
|
|
|
|
cellSearch.notice("CellSearchPhotoInfo: title='%s', albumTitle='%s', size=%d, width=%d, height=%d, orientation=%d, codec=%d, status=%d, importedDate=%d, takenDate=%d",
|
|
|
|
|
info.title, info.albumTitle, info.size, info.width, info.height, info.orientation, info.codec, info.status, info.importedDate, info.takenDate);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchInitialize(CellSearchMode mode, u32 container, vm::ptr<CellSearchSystemCallback> func, vm::ptr<void> userData)
|
|
|
|
|
{
|
2019-12-02 22:31:34 +01:00
|
|
|
cellSearch.warning("cellSearchInitialize(mode=0x%x, container=0x%x, func=*0x%x, userData=*0x%x)", +mode, container, func, userData);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
if (!func)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 21:40:21 +01:00
|
|
|
if (mode != CELL_SEARCH_MODE_NORMAL)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_UNKNOWN_MODE;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
2020-02-08 21:40:21 +01:00
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(search.state.compare_and_swap(search_state::not_initialized, search_state::initializing), search_state::initializing))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
search.func = func;
|
|
|
|
|
search.userData = userData;
|
2015-02-22 15:50:11 +01:00
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
sysutil_register_cb([=, &search](ppu_thread& ppu) -> s32
|
2017-11-22 23:02:23 +01:00
|
|
|
{
|
2021-03-02 12:59:19 +01:00
|
|
|
search.state.store(search_state::idle);
|
2017-11-22 23:02:23 +01:00
|
|
|
func(ppu, CELL_SEARCH_EVENT_INITIALIZE_RESULT, CELL_OK, vm::null, userData);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
});
|
2015-02-22 15:50:11 +01:00
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchFinalize()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2020-02-08 11:07:18 +01:00
|
|
|
cellSearch.todo("cellSearchFinalize()");
|
2015-02-22 15:50:11 +01:00
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
2020-02-08 21:40:21 +01:00
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::finalizing), search_state::finalizing))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2019-08-21 21:51:48 +02:00
|
|
|
|
2021-06-17 22:44:06 +02:00
|
|
|
sysutil_register_cb([&search](ppu_thread& ppu) -> s32
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
2020-02-08 18:07:18 +01:00
|
|
|
{
|
2021-03-02 12:59:19 +01:00
|
|
|
std::lock_guard lock(search.links_mutex);
|
|
|
|
|
search.content_links.clear();
|
2020-02-08 18:07:18 +01:00
|
|
|
}
|
2021-03-02 12:59:19 +01:00
|
|
|
search.state.store(search_state::not_initialized);
|
|
|
|
|
search.func(ppu, CELL_SEARCH_EVENT_FINALIZE_RESULT, CELL_OK, vm::null, search.userData);
|
2017-12-28 22:38:29 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
});
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchStartListSearch(CellSearchListSearchType type, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2019-12-02 22:31:34 +01:00
|
|
|
cellSearch.todo("cellSearchStartListSearch(type=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", +type, +sortOrder, outSearchId);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!outSearchId)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
const char* media_dir;
|
|
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_MUSIC_ALBUM:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_MUSIC_GENRE:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_MUSIC_ARTIST:
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_MUSIC_PLAYLIST:
|
|
|
|
|
media_dir = "music";
|
|
|
|
|
break;
|
2020-02-08 11:07:18 +01:00
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_PHOTO_YEAR:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_PHOTO_MONTH:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_PHOTO_ALBUM:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_PHOTO_PLAYLIST:
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
media_dir = "photo";
|
|
|
|
|
break;
|
2020-02-08 11:07:18 +01:00
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_VIDEO_ALBUM:
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
media_dir = "video";
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_NONE:
|
2020-02-08 11:07:18 +01:00
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sortOrder != CELL_SEARCH_SORTORDER_ASCENDING && sortOrder != CELL_SEARCH_SORTORDER_DESCENDING)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
2020-02-08 21:40:21 +01:00
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2019-08-21 21:51:48 +02:00
|
|
|
|
2020-02-12 16:17:45 +01:00
|
|
|
const u32 id = *outSearchId = idm::make<search_object_t>();
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
sysutil_register_cb([=, &content_map = g_fxo->get<content_id_map>(), &search](ppu_thread& ppu) -> s32
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
auto curr_search = idm::get<search_object_t>(id);
|
2017-12-28 22:38:29 +01:00
|
|
|
vm::var<CellSearchResultParam> resultParam;
|
2020-02-12 16:17:45 +01:00
|
|
|
resultParam->searchId = id;
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
resultParam->resultNum = 0; // Set again later
|
|
|
|
|
|
|
|
|
|
std::function<void(const std::string&)> searchInFolder = [&, type](const std::string& vpath)
|
|
|
|
|
{
|
|
|
|
|
// TODO: this is just a workaround. On a real PS3 the playlists seem to be stored in dev_hdd0/mms/db/metadata_db_hdd
|
|
|
|
|
|
|
|
|
|
std::vector<fs::dir_entry> dirs_sorted;
|
|
|
|
|
|
|
|
|
|
for (auto&& entry : fs::dir(vfs::get(vpath)))
|
|
|
|
|
{
|
|
|
|
|
entry.name = vfs::unescape(entry.name);
|
|
|
|
|
|
|
|
|
|
if (entry.is_directory)
|
|
|
|
|
{
|
|
|
|
|
if (entry.name == "." || entry.name == "..")
|
|
|
|
|
{
|
|
|
|
|
continue; // these dirs are not included in the dir list
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dirs_sorted.push_back(entry);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
|
std::sort(dirs_sorted.begin(), dirs_sorted.end(), [&](const fs::dir_entry& a, const fs::dir_entry& b) -> bool
|
|
|
|
|
{
|
|
|
|
|
switch (sortOrder)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_SORTORDER_ASCENDING:
|
|
|
|
|
// Order alphabetically ascending
|
|
|
|
|
return a.name < b.name;
|
|
|
|
|
case CELL_SEARCH_SORTORDER_DESCENDING:
|
|
|
|
|
// Order alphabetically descending
|
|
|
|
|
return a.name > b.name;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
|
|
for (auto&& item : dirs_sorted)
|
|
|
|
|
{
|
|
|
|
|
item.name = vfs::unescape(item.name);
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (item.name == "." || item.name == ".." || !item.is_directory)
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string item_path(vpath + "/" + item.name);
|
|
|
|
|
|
|
|
|
|
// Count files
|
|
|
|
|
u32 numOfItems = 0;
|
|
|
|
|
for (auto&& file : fs::dir(vfs::get(item_path)))
|
|
|
|
|
{
|
|
|
|
|
file.name = vfs::unescape(file.name);
|
|
|
|
|
|
|
|
|
|
if (file.name == "." || file.name == ".." || file.is_directory)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
numOfItems++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u64 hash = std::hash<std::string>()(item_path);
|
2021-03-02 17:22:39 +01:00
|
|
|
auto found = content_map.map.find(hash);
|
|
|
|
|
if (found == content_map.map.end()) // content isn't yet being tracked
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
{
|
|
|
|
|
std::shared_ptr<search_content_t> curr_find = std::make_shared<search_content_t>();
|
|
|
|
|
if (item_path.length() > CELL_SEARCH_PATH_LEN_MAX)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Create mapping which will be resolved to an actual hard link in VFS by cellSearchPrepareFile
|
|
|
|
|
cellSearch.warning("cellSearchStartListSearch(): Directory-Path \"%s\" is too long and will be omitted: %i", item_path, item_path.length());
|
|
|
|
|
continue;
|
2022-02-20 10:10:35 +01:00
|
|
|
// const size_t ext_offset = item.name.find_last_of('.');
|
2022-02-20 19:01:21 +01:00
|
|
|
// std::string link = "/.tmp/" + std::to_string(hash) + item.name.substr(ext_offset);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
// strcpy_trunc(curr_find->infoPath.contentPath, link);
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
// std::lock_guard lock(search.links_mutex);
|
|
|
|
|
// search.content_links.emplace(std::move(link), item_path);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy_trunc(curr_find->infoPath.contentPath, item_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.name.size() > CELL_SEARCH_TITLE_LEN_MAX)
|
|
|
|
|
{
|
|
|
|
|
item.name.resize(CELL_SEARCH_TITLE_LEN_MAX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_MUSIC_ALBUM:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_MUSIC_GENRE:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_MUSIC_ARTIST:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_MUSIC_PLAYLIST:
|
|
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_MUSICLIST;
|
|
|
|
|
CellSearchMusicListInfo& info = curr_find->data.music_list;
|
|
|
|
|
info.listType = type; // CellSearchListType matches CellSearchListSearchType
|
|
|
|
|
info.numOfItems = numOfItems;
|
|
|
|
|
info.duration = 0;
|
|
|
|
|
strcpy_trunc(info.title, item.name);
|
|
|
|
|
strcpy_trunc(info.artistName, "ARTIST NAME");
|
2022-02-20 10:10:35 +01:00
|
|
|
|
|
|
|
|
cellSearch.notice("CellSearchMusicListInfo: title='%s', artistName='%s', listType=%d, numOfItems=%d, duration=%d",
|
|
|
|
|
info.title, info.artistName, info.listType, info.numOfItems, info.duration);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_PHOTO_YEAR:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_PHOTO_MONTH:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_PHOTO_ALBUM:
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_PHOTO_PLAYLIST:
|
|
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_PHOTOLIST;
|
|
|
|
|
CellSearchPhotoListInfo& info = curr_find->data.photo_list;
|
|
|
|
|
info.listType = type; // CellSearchListType matches CellSearchListSearchType
|
|
|
|
|
info.numOfItems = numOfItems;
|
|
|
|
|
strcpy_trunc(info.title, item.name);
|
2022-02-20 10:10:35 +01:00
|
|
|
|
|
|
|
|
cellSearch.notice("CellSearchPhotoListInfo: title='%s', listType=%d, numOfItems=%d",
|
|
|
|
|
info.title, info.listType, info.numOfItems);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_VIDEO_ALBUM:
|
|
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_VIDEOLIST;
|
|
|
|
|
CellSearchVideoListInfo& info = curr_find->data.video_list;
|
|
|
|
|
info.listType = type; // CellSearchListType matches CellSearchListSearchType
|
|
|
|
|
info.numOfItems = numOfItems;
|
|
|
|
|
info.duration = 0;
|
|
|
|
|
strcpy_trunc(info.title, item.name);
|
2022-02-20 10:10:35 +01:00
|
|
|
|
|
|
|
|
cellSearch.notice("CellSearchVideoListInfo: title='%s', listType=%d, numOfItems=%d, duration=%d",
|
|
|
|
|
info.title, info.listType, info.numOfItems, info.duration);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_LISTSEARCHTYPE_NONE:
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
default:
|
|
|
|
|
{
|
2022-02-20 10:10:35 +01:00
|
|
|
// Should be unreachable, because it is already handled in the main function
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
content_map.map.emplace(hash, curr_find);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
curr_search->content_ids.emplace_back(hash, curr_find); // place this file's "ID" into the list of found types
|
|
|
|
|
|
2022-02-20 15:22:41 +01:00
|
|
|
cellSearch.notice("cellSearchStartListSearch(): CellSearchId: 0x%x, Content ID: %08X, Path: \"%s\"", id, hash, item_path);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
|
|
|
|
else // list is already stored and tracked
|
|
|
|
|
{
|
|
|
|
|
// TODO
|
|
|
|
|
// Perform checks to see if the identified list has been modified since last checked
|
|
|
|
|
// In which case, update the stored content's properties
|
|
|
|
|
// auto content_found = &content_map->at(content_id);
|
2022-02-20 15:22:41 +01:00
|
|
|
curr_search->content_ids.emplace_back(found->first, found->second);
|
|
|
|
|
|
|
|
|
|
cellSearch.notice("cellSearchStartListSearch(): Already tracked: CellSearchId: 0x%x, Content ID: %08X, Path: \"%s\"", id, hash, item_path);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
searchInFolder(fmt::format("/dev_hdd0/%s", media_dir));
|
|
|
|
|
resultParam->resultNum = ::narrow<s32>(curr_search->content_ids.size());
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
search.state.store(search_state::idle);
|
|
|
|
|
search.func(ppu, CELL_SEARCH_EVENT_LISTSEARCH_RESULT, CELL_OK, vm::cast(resultParam.addr()), search.userData);
|
2017-12-28 22:38:29 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
});
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchStartContentSearchInList(vm::cptr<CellSearchContentId> listId, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2019-12-02 22:31:34 +01:00
|
|
|
cellSearch.todo("cellSearchStartContentSearchInList(listId=*0x%x, sortKey=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", listId, +sortKey, +sortOrder, outSearchId);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!listId || !outSearchId)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
switch (sortKey)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_SORTKEY_DEFAULT:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_TITLE:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_ALBUMTITLE:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_GENRENAME:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_ARTISTNAME:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_IMPORTEDDATE:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_TRACKNUMBER:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_TAKENDATE:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_USERDEFINED:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_MODIFIEDDATE:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sortOrder != CELL_SEARCH_SORTORDER_ASCENDING && sortOrder != CELL_SEARCH_SORTORDER_DESCENDING)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
2020-02-08 21:40:21 +01:00
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2019-08-21 21:51:48 +02:00
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(*reinterpret_cast<const u64*>(listId->data));
|
|
|
|
|
if (found == content_map.map.end())
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
{
|
|
|
|
|
// content ID not found, perform a search first
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CellSearchContentSearchType type = CELL_SEARCH_CONTENTSEARCHTYPE_NONE;
|
|
|
|
|
|
|
|
|
|
const auto& content_info = found->second;
|
|
|
|
|
switch (content_info->type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_MUSICLIST:
|
|
|
|
|
type = CELL_SEARCH_CONTENTSEARCHTYPE_MUSIC_ALL;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_PHOTOLIST:
|
|
|
|
|
type = CELL_SEARCH_CONTENTSEARCHTYPE_PHOTO_ALL;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_VIDEOLIST:
|
|
|
|
|
type = CELL_SEARCH_CONTENTSEARCHTYPE_VIDEO_ALL;
|
|
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_MUSIC:
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_PHOTO:
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_VIDEO:
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_SCENE:
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_CONTENTTYPE_NONE:
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_NOT_LIST;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-12 16:17:45 +01:00
|
|
|
const u32 id = *outSearchId = idm::make<search_object_t>();
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
sysutil_register_cb([=, list_path = std::string(content_info->infoPath.contentPath), &search, &content_map](ppu_thread& ppu) -> s32
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
auto curr_search = idm::get<search_object_t>(id);
|
2017-12-28 22:38:29 +01:00
|
|
|
vm::var<CellSearchResultParam> resultParam;
|
2020-02-12 16:17:45 +01:00
|
|
|
resultParam->searchId = id;
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
resultParam->resultNum = 0; // Set again later
|
|
|
|
|
|
|
|
|
|
std::function<void(const std::string&)> searchInFolder = [&, type](const std::string& vpath)
|
|
|
|
|
{
|
|
|
|
|
std::vector<fs::dir_entry> files_sorted;
|
|
|
|
|
|
|
|
|
|
for (auto&& entry : fs::dir(vfs::get(vpath)))
|
|
|
|
|
{
|
|
|
|
|
entry.name = vfs::unescape(entry.name);
|
|
|
|
|
|
|
|
|
|
if (entry.is_directory || entry.name == "." || entry.name == "..")
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
files_sorted.push_back(entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
|
std::sort(files_sorted.begin(), files_sorted.end(), [&](const fs::dir_entry& a, const fs::dir_entry& b) -> bool
|
|
|
|
|
{
|
|
|
|
|
switch (sortOrder)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_SORTORDER_ASCENDING:
|
|
|
|
|
// Order alphabetically ascending
|
|
|
|
|
return a.name < b.name;
|
|
|
|
|
case CELL_SEARCH_SORTORDER_DESCENDING:
|
|
|
|
|
// Order alphabetically descending
|
|
|
|
|
return a.name > b.name;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
|
|
// TODO: Use sortKey (CellSearchSortKey) to allow for sorting by category
|
|
|
|
|
|
|
|
|
|
for (auto&& item : files_sorted)
|
|
|
|
|
{
|
|
|
|
|
// TODO
|
|
|
|
|
// Perform first check that file is of desired type. For example, don't wanna go
|
|
|
|
|
// identifying "AlbumArt.jpg" as an MP3. Hrm... Postpone this thought. Do games
|
|
|
|
|
// perform their own checks? DIVA ignores anything without the MP3 extension.
|
|
|
|
|
|
|
|
|
|
const std::string item_path(vpath + "/" + item.name);
|
|
|
|
|
|
|
|
|
|
const u64 hash = std::hash<std::string>()(item_path);
|
2021-03-02 17:22:39 +01:00
|
|
|
auto found = content_map.map.find(hash);
|
|
|
|
|
if (found == content_map.map.end()) // content isn't yet being tracked
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
{
|
|
|
|
|
std::shared_ptr<search_content_t> curr_find = std::make_shared<search_content_t>();
|
|
|
|
|
if (item_path.length() > CELL_SEARCH_PATH_LEN_MAX)
|
|
|
|
|
{
|
|
|
|
|
// Create mapping which will be resolved to an actual hard link in VFS by cellSearchPrepareFile
|
2022-02-20 10:10:35 +01:00
|
|
|
const size_t ext_offset = item.name.find_last_of('.');
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
std::string link = "/.tmp/" + std::to_string(hash) + item.name.substr(ext_offset);
|
|
|
|
|
strcpy_trunc(curr_find->infoPath.contentPath, link);
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
std::lock_guard lock(search.links_mutex);
|
|
|
|
|
search.content_links.emplace(std::move(link), item_path);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy_trunc(curr_find->infoPath.contentPath, item_path);
|
|
|
|
|
}
|
2021-06-17 22:44:06 +02:00
|
|
|
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
// TODO - curr_find.infoPath.thumbnailPath
|
2021-06-17 22:44:06 +02:00
|
|
|
|
2022-02-20 10:10:35 +01:00
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_MUSIC_ALL:
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_MUSIC;
|
|
|
|
|
|
2021-06-17 22:44:06 +02:00
|
|
|
const std::string path = vfs::get(vpath) + "/" + item.name;
|
|
|
|
|
const auto [success, mi] = utils::get_media_info(path, 1); // AVMEDIA_TYPE_AUDIO
|
|
|
|
|
if (!success)
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-17 22:44:06 +02:00
|
|
|
populate_music_info(curr_find->data.music, mi, item);
|
2022-02-20 10:10:35 +01:00
|
|
|
break;
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_PHOTO_ALL:
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_PHOTO;
|
2022-02-20 10:10:35 +01:00
|
|
|
|
|
|
|
|
populate_photo_info(curr_find->data.photo, {}, item);
|
|
|
|
|
break;
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_VIDEO_ALL:
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_VIDEO;
|
2021-06-24 21:26:40 +02:00
|
|
|
|
|
|
|
|
const std::string path = vfs::get(vpath) + "/" + item.name;
|
|
|
|
|
const auto [success, mi] = utils::get_media_info(path, 0); // AVMEDIA_TYPE_VIDEO
|
|
|
|
|
if (!success)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
populate_video_info(curr_find->data.video, mi, item);
|
2022-02-20 10:10:35 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_NONE:
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
// Should be unreachable, because it is already handled in the main function
|
|
|
|
|
break;
|
|
|
|
|
}
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
|
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
content_map.map.emplace(hash, curr_find);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
curr_search->content_ids.emplace_back(hash, curr_find); // place this file's "ID" into the list of found types
|
|
|
|
|
|
2022-02-20 15:22:41 +01:00
|
|
|
cellSearch.notice("cellSearchStartContentSearchInList(): CellSearchId: 0x%x, Content ID: %08X, Path: \"%s\"", id, hash, item_path);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
|
|
|
|
else // file is already stored and tracked
|
|
|
|
|
{
|
|
|
|
|
// TODO
|
|
|
|
|
// Perform checks to see if the identified file has been modified since last checked
|
|
|
|
|
// In which case, update the stored content's properties
|
|
|
|
|
// auto content_found = &content_map->at(content_id);
|
|
|
|
|
curr_search->content_ids.emplace_back(found->first, found->second);
|
2022-02-20 10:10:35 +01:00
|
|
|
|
2022-02-20 15:22:41 +01:00
|
|
|
cellSearch.notice("cellSearchStartContentSearchInList(): Already Tracked: CellSearchId: 0x%x, Content ID: %08X, Path: \"%s\"", id, hash, item_path);
|
Initial playlist-based custom soundtracks support (#9362)
* Initial playlist-based custom soundtracks support
This is the initial implementation of playlist-based (cellSearch) custom soundtracks support.
It is based on the initial work by @Megamouse and currently uses a directory-based approach to manage albums and utilizes FFMPEG to read audio metadata.
Background: The real PS3 can import music in XMB from USB into its internal storage (/dev_hdd0/music) and additionally stores metadata (artist, trackname, tracknumber, ...) in a database (/dev_hdd0/mms/db/metadata_db_hdd). Games can make use of imported music via cellSearch.
For the time being, this implementation does NOT make use of metadata_db_hdd as the db-format is not well understood and a folder-based approch is easier to use. Users only have to create folders inside /dev_hdd0/music and add music to it to create a "playlist". This playlists contents will be sorted alphabetically. As a result, users could prefix numbers to the audio-files to force a specific order.
The only really supported audio format is MP3. I also added support for AAC, AC3, WMA, ATRAC3 and ATRAC3 plus, however, non of these formats were successfully tested for several reasons. AC3 and WMA are not enabled in the current FFMPEG build which makes reading codec-specific data impossible. We could enable these later if we want to. AAC actually could work but I was not able to get it working in WipeOut HD Fury. My guess is that the game does not support AAC. Finally, I could not find any ATRAC3 (or Plus) music to test with.
This implementation currently only implements parts of cellSearchStartListSearch() and cellSearchStartContentSearchInList(). There are several other functions which are still completely unimplemented and will probably be needed by other games. However, this implementation is a starting-point and is enough for WipeOut and maybe a few other games.
A video which showcases this custom soundtrack support is available here: https://www.youtube.com/watch?v=4nu1OCtONTY
Next steps:
- Utilize sortKey in cellSearchStartContentSearchInList()
- Eliminate TODOs
- Implement the missing other functions
- Test on more games - I do not own many that support custom soundtracks
Signed-off-by: gladiac1337 <gladiac@gmail.com>
Co-authored-by: Megamouse <studienricky89@googlemail.com>
Co-authored-by: Ani <ani-leo@outlook.com>
Co-authored-by: Ivan <nekotekina@gmail.com>
2020-12-31 20:47:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
searchInFolder(list_path);
|
|
|
|
|
resultParam->resultNum = ::narrow<s32>(curr_search->content_ids.size());
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
search.state.store(search_state::idle);
|
|
|
|
|
search.func(ppu, CELL_SEARCH_EVENT_CONTENTSEARCH_INLIST_RESULT, CELL_OK, vm::cast(resultParam.addr()), search.userData);
|
2017-12-28 22:38:29 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
});
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchStartContentSearch(CellSearchContentSearchType type, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2019-12-02 22:31:34 +01:00
|
|
|
cellSearch.todo("cellSearchStartContentSearch(type=0x%x, sortKey=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", +type, +sortKey, +sortOrder, outSearchId);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!outSearchId)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
switch (sortKey)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_SORTKEY_DEFAULT:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_TITLE:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_ALBUMTITLE:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_GENRENAME:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_ARTISTNAME:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_IMPORTEDDATE:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_TRACKNUMBER:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_TAKENDATE:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_USERDEFINED:
|
|
|
|
|
case CELL_SEARCH_SORTKEY_MODIFIEDDATE:
|
|
|
|
|
break;
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_SORTKEY_NONE:
|
2020-02-08 11:07:18 +01:00
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sortOrder != CELL_SEARCH_SORTORDER_ASCENDING && sortOrder != CELL_SEARCH_SORTORDER_DESCENDING)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* media_dir;
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_MUSIC_ALL: media_dir = "music"; break;
|
|
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_PHOTO_ALL: media_dir = "photo"; break;
|
|
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_VIDEO_ALL: media_dir = "video"; break;
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_NONE:
|
2020-02-08 11:07:18 +01:00
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
2020-02-08 21:40:21 +01:00
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2019-08-21 21:51:48 +02:00
|
|
|
|
2020-02-12 16:17:45 +01:00
|
|
|
const u32 id = *outSearchId = idm::make<search_object_t>();
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
sysutil_register_cb([=, &content_map = g_fxo->get<content_id_map>(), &search](ppu_thread& ppu) -> s32
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
2020-02-12 17:33:13 +01:00
|
|
|
auto curr_search = idm::get<search_object_t>(id);
|
2017-12-28 22:38:29 +01:00
|
|
|
vm::var<CellSearchResultParam> resultParam;
|
2020-02-12 16:17:45 +01:00
|
|
|
resultParam->searchId = id;
|
2020-02-08 11:07:18 +01:00
|
|
|
resultParam->resultNum = 0; // Set again later
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
std::function<void(const std::string&, const std::string&)> searchInFolder = [&, type](const std::string& vpath, const std::string& prev)
|
|
|
|
|
{
|
|
|
|
|
const std::string relative_vpath = (!prev.empty() ? prev + "/" : "") + vpath;
|
|
|
|
|
|
|
|
|
|
for (auto&& item : fs::dir(vfs::get(relative_vpath)))
|
|
|
|
|
{
|
|
|
|
|
item.name = vfs::unescape(item.name);
|
|
|
|
|
|
|
|
|
|
if (item.name == "." || item.name == "..")
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.is_directory)
|
|
|
|
|
{
|
|
|
|
|
searchInFolder(item.name, relative_vpath);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO
|
|
|
|
|
// Perform first check that file is of desired type. For example, don't wanna go
|
|
|
|
|
// identifying "AlbumArt.jpg" as an MP3. Hrm... Postpone this thought. Do games
|
|
|
|
|
// perform their own checks? DIVA ignores anything without the MP3 extension.
|
|
|
|
|
|
|
|
|
|
// TODO - Identify sorting method and insert the appropriate values where applicable
|
|
|
|
|
const std::string item_path(relative_vpath + "/" + item.name);
|
|
|
|
|
|
2020-09-26 18:28:19 +02:00
|
|
|
const u64 hash = std::hash<std::string>()(item_path);
|
2021-03-02 17:22:39 +01:00
|
|
|
auto found = content_map.map.find(hash);
|
|
|
|
|
if (found == content_map.map.end()) // content isn't yet being tracked
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
|
|
|
|
std::shared_ptr<search_content_t> curr_find = std::make_shared<search_content_t>();
|
2021-06-17 22:44:06 +02:00
|
|
|
if (item_path.length() > CELL_SEARCH_PATH_LEN_MAX)
|
2020-02-08 18:07:18 +01:00
|
|
|
{
|
|
|
|
|
// Create mapping which will be resolved to an actual hard link in VFS by cellSearchPrepareFile
|
2022-02-20 10:10:35 +01:00
|
|
|
const size_t ext_offset = item.name.find_last_of('.');
|
2022-02-20 19:01:21 +01:00
|
|
|
std::string link = "/.tmp/" + std::to_string(hash) + item.name.substr(ext_offset);
|
2020-02-08 18:07:18 +01:00
|
|
|
strcpy_trunc(curr_find->infoPath.contentPath, link);
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
std::lock_guard lock(search.links_mutex);
|
|
|
|
|
search.content_links.emplace(std::move(link), item_path);
|
2020-02-08 18:07:18 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy_trunc(curr_find->infoPath.contentPath, item_path);
|
|
|
|
|
}
|
2021-06-17 22:44:06 +02:00
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
// TODO - curr_find.infoPath.thumbnailPath
|
2021-06-17 22:44:06 +02:00
|
|
|
|
2022-02-20 10:10:35 +01:00
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_MUSIC_ALL:
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_MUSIC;
|
2021-06-17 22:44:06 +02:00
|
|
|
|
|
|
|
|
const std::string path = vfs::get(vpath) + "/" + item.name;
|
|
|
|
|
const auto [success, mi] = utils::get_media_info(path, 1); // AVMEDIA_TYPE_AUDIO
|
|
|
|
|
if (!success)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
populate_music_info(curr_find->data.music, mi, item);
|
2022-02-20 10:10:35 +01:00
|
|
|
break;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_PHOTO_ALL:
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_PHOTO;
|
2022-02-20 10:10:35 +01:00
|
|
|
|
|
|
|
|
populate_photo_info(curr_find->data.photo, {}, item);
|
|
|
|
|
break;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2022-02-20 10:10:35 +01:00
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_VIDEO_ALL:
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_VIDEO;
|
2021-06-24 21:26:40 +02:00
|
|
|
|
|
|
|
|
const std::string path = vfs::get(vpath) + "/" + item.name;
|
|
|
|
|
const auto [success, mi] = utils::get_media_info(path, 0); // AVMEDIA_TYPE_VIDEO
|
|
|
|
|
if (!success)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
populate_video_info(curr_find->data.video, mi, item);
|
2022-02-20 10:10:35 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CELL_SEARCH_CONTENTSEARCHTYPE_NONE:
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
// Should be unreachable, because it is already handled in the main function
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
content_map.map.emplace(hash, curr_find);
|
2020-02-08 11:07:18 +01:00
|
|
|
curr_search->content_ids.emplace_back(hash, curr_find); // place this file's "ID" into the list of found types
|
|
|
|
|
|
2022-02-20 15:22:41 +01:00
|
|
|
cellSearch.notice("cellSearchStartContentSearch(): CellSearchId: 0x%x, Content ID: %08X, Path: \"%s\"", id, hash, item_path);
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
else // file is already stored and tracked
|
|
|
|
|
{ // TODO
|
|
|
|
|
// Perform checks to see if the identified file has been modified since last checked
|
|
|
|
|
// In which case, update the stored content's properties
|
|
|
|
|
// auto content_found = &content_map->at(content_id);
|
|
|
|
|
curr_search->content_ids.emplace_back(found->first, found->second);
|
2022-02-20 10:10:35 +01:00
|
|
|
|
2022-02-20 15:22:41 +01:00
|
|
|
cellSearch.notice("cellSearchStartContentSearch(): Already Tracked: CellSearchId: 0x%x, Content ID: %08X, Path: \"%s\"", id, hash, item_path);
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
searchInFolder(fmt::format("/dev_hdd0/%s", media_dir), "");
|
|
|
|
|
resultParam->resultNum = ::narrow<s32>(curr_search->content_ids.size());
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
search.state.store(search_state::idle);
|
|
|
|
|
search.func(ppu, CELL_SEARCH_EVENT_CONTENTSEARCH_RESULT, CELL_OK, vm::cast(resultParam.addr()), search.userData);
|
2017-12-28 22:38:29 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
});
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchStartSceneSearchInVideo(vm::cptr<CellSearchContentId> videoId, CellSearchSceneSearchType searchType, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2019-12-02 22:31:34 +01:00
|
|
|
cellSearch.todo("cellSearchStartSceneSearchInVideo(videoId=*0x%x, searchType=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", videoId, +searchType, +sortOrder, outSearchId);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!videoId || !outSearchId)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
switch (searchType)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_NONE:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_CHAPTER:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_CLIP_HIGHLIGHT:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_CLIP_USER:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_CLIP:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_ALL:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sortOrder != CELL_SEARCH_SORTORDER_ASCENDING && sortOrder != CELL_SEARCH_SORTORDER_DESCENDING)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
2020-02-08 21:40:21 +01:00
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(*reinterpret_cast<const u64*>(videoId->data));
|
|
|
|
|
if (found == content_map.map.end())
|
|
|
|
|
{
|
|
|
|
|
// content ID not found, perform a search first
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& content_info = found->second;
|
|
|
|
|
if (content_info->type != CELL_SEARCH_CONTENTTYPE_VIDEO)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_CONTENTTYPE;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2019-08-21 21:51:48 +02:00
|
|
|
|
2020-02-12 16:17:45 +01:00
|
|
|
const u32 id = *outSearchId = idm::make<search_object_t>();
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
sysutil_register_cb([=, &search](ppu_thread& ppu) -> s32
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
|
|
|
|
vm::var<CellSearchResultParam> resultParam;
|
2020-02-12 16:17:45 +01:00
|
|
|
resultParam->searchId = id;
|
2017-12-28 22:38:29 +01:00
|
|
|
resultParam->resultNum = 0; // TODO
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
search.state.store(search_state::idle);
|
|
|
|
|
search.func(ppu, CELL_SEARCH_EVENT_SCENESEARCH_INVIDEO_RESULT, CELL_OK, vm::cast(resultParam.addr()), search.userData);
|
2017-12-28 22:38:29 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
});
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchStartSceneSearch(CellSearchSceneSearchType searchType, vm::cptr<char> gameTitle, vm::cpptr<char> tags, u32 tagNum, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2019-12-02 22:31:34 +01:00
|
|
|
cellSearch.todo("cellSearchStartSceneSearch(searchType=0x%x, gameTitle=%s, tags=**0x%x, tagNum=0x%x, sortKey=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", +searchType, gameTitle, tags, tagNum, +sortKey, +sortOrder, outSearchId);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!gameTitle || !outSearchId)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
switch (searchType)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_NONE:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_CHAPTER:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_CLIP_HIGHLIGHT:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_CLIP_USER:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_CLIP:
|
|
|
|
|
case CELL_SEARCH_SCENESEARCHTYPE_ALL:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (tagNum) // TODO: find out if this is the correct location for these checks
|
|
|
|
|
{
|
|
|
|
|
if (tagNum > CELL_SEARCH_TAG_NUM_MAX || !tags)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_TAG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u32 n = 0; n < tagNum; n++)
|
|
|
|
|
{
|
|
|
|
|
if (!tags[tagNum] || !memchr(&tags[tagNum], '\0', CELL_SEARCH_TAG_LEN_MAX))
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_TAG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
2020-02-08 21:40:21 +01:00
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2019-08-21 21:51:48 +02:00
|
|
|
|
2020-02-12 16:17:45 +01:00
|
|
|
const u32 id = *outSearchId = idm::make<search_object_t>();
|
2017-12-28 22:38:29 +01:00
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
sysutil_register_cb([=, &search](ppu_thread& ppu) -> s32
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
|
|
|
|
vm::var<CellSearchResultParam> resultParam;
|
2020-02-12 16:17:45 +01:00
|
|
|
resultParam->searchId = id;
|
2017-12-28 22:38:29 +01:00
|
|
|
resultParam->resultNum = 0; // TODO
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
search.state.store(search_state::idle);
|
|
|
|
|
search.func(ppu, CELL_SEARCH_EVENT_SCENESEARCH_RESULT, CELL_OK, vm::cast(resultParam.addr()), search.userData);
|
2017-12-28 22:38:29 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
});
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetContentInfoByOffset(CellSearchId searchId, s32 offset, vm::ptr<void> infoBuffer, vm::ptr<CellSearchContentType> outContentType, vm::ptr<CellSearchContentId> outContentId)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2020-02-08 11:07:18 +01:00
|
|
|
cellSearch.warning("cellSearchGetContentInfoByOffset(searchId=0x%x, offset=0x%x, infoBuffer=*0x%x, outContentType=*0x%x, outContentId=*0x%x)", searchId, offset, infoBuffer, outContentType, outContentId);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!outContentType)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto searchObject = idm::get<search_object_t>(searchId);
|
|
|
|
|
|
|
|
|
|
if (!searchObject)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
2020-02-19 18:03:59 +01:00
|
|
|
if (offset >= 0 && offset + 0u < searchObject->content_ids.size())
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
|
|
|
|
const auto& content_id = searchObject->content_ids[offset];
|
|
|
|
|
const auto& content_info = content_id.second;
|
2021-09-16 23:05:29 +02:00
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
switch (content_info->type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_MUSIC:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.music, sizeof(content_info->data.music));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_PHOTO:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo, sizeof(content_info->data.photo));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_VIDEO:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.video, sizeof(content_info->data.photo));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_MUSICLIST:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.music_list, sizeof(content_info->data.music_list));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_PHOTOLIST:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo_list, sizeof(content_info->data.photo_list));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_VIDEOLIST:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.video_list, sizeof(content_info->data.video_list));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_SCENE:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.scene, sizeof(content_info->data.scene));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_GENERIC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u128 content_id_128 = content_id.first;
|
|
|
|
|
*outContentType = content_info->type;
|
|
|
|
|
std::memcpy(outContentId->data, &content_id_128, CELL_SEARCH_CONTENT_ID_SIZE);
|
|
|
|
|
}
|
|
|
|
|
else // content ID not found, perform a search first
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_OUT_OF_RANGE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetContentInfoByContentId(vm::cptr<CellSearchContentId> contentId, vm::ptr<void> infoBuffer, vm::ptr<CellSearchContentType> outContentType)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2020-02-08 11:07:18 +01:00
|
|
|
cellSearch.warning("cellSearchGetContentInfoByContentId(contentId=*0x%x, infoBuffer=*0x%x, outContentType=*0x%x)", contentId, infoBuffer, outContentType);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!outContentType)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
2021-03-02 17:22:39 +01:00
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(*reinterpret_cast<const u64*>(contentId->data));
|
|
|
|
|
if (found != content_map.map.end())
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
|
|
|
|
const auto& content_info = found->second;
|
|
|
|
|
switch (content_info->type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_MUSIC:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.music, sizeof(content_info->data.music));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_PHOTO:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo, sizeof(content_info->data.photo));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_VIDEO:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.video, sizeof(content_info->data.photo));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_MUSICLIST:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.music_list, sizeof(content_info->data.music_list));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_PHOTOLIST:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo_list, sizeof(content_info->data.photo_list));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_VIDEOLIST:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.video_list, sizeof(content_info->data.video_list));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_SCENE:
|
2021-09-16 23:05:29 +02:00
|
|
|
if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.scene, sizeof(content_info->data.scene));
|
2020-02-08 11:07:18 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_GENERIC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*outContentType = content_info->type;
|
|
|
|
|
}
|
|
|
|
|
else // content ID not found, perform a search first
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetOffsetByContentId(CellSearchId searchId, vm::cptr<CellSearchContentId> contentId, vm::ptr<s32> outOffset)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2020-02-08 11:07:18 +01:00
|
|
|
cellSearch.warning("cellSearchGetOffsetByContentId(searchId=0x%x, contentId=*0x%x, outOffset=*0x%x)", searchId, contentId, outOffset);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!outOffset)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
const auto searchObject = idm::get<search_object_t>(searchId);
|
|
|
|
|
|
|
|
|
|
if (!searchObject)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 11:07:18 +01:00
|
|
|
s32 i = 0;
|
|
|
|
|
const u64 content_hash = *reinterpret_cast<const u64*>(contentId->data);
|
|
|
|
|
for (auto& content_id : searchObject->content_ids)
|
|
|
|
|
{
|
|
|
|
|
if (content_id.first == content_hash)
|
|
|
|
|
{
|
|
|
|
|
*outOffset = i;
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
2013-09-28 04:36:57 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetContentIdByOffset(CellSearchId searchId, s32 offset, vm::ptr<CellSearchContentType> outContentType, vm::ptr<CellSearchContentId> outContentId, vm::ptr<CellSearchTimeInfo> outTimeInfo)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchGetContentIdByOffset(searchId=0x%x, offset=0x%x, outContentType=*0x%x, outContentId=*0x%x, outTimeInfo=*0x%x)", searchId, offset, outContentType, outContentId, outTimeInfo);
|
|
|
|
|
|
|
|
|
|
if (!outContentType || !outContentId)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto searchObject = idm::get<search_object_t>(searchId);
|
|
|
|
|
|
|
|
|
|
if (!searchObject)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
2020-02-19 18:03:59 +01:00
|
|
|
if (offset >= 0 && offset + 0u < searchObject->content_ids.size())
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
|
|
|
|
auto& content_id = searchObject->content_ids.at(offset);
|
|
|
|
|
const u128 content_id_128 = content_id.first;
|
|
|
|
|
*outContentType = content_id.second->type;
|
|
|
|
|
std::memcpy(outContentId->data, &content_id_128, CELL_SEARCH_CONTENT_ID_SIZE);
|
|
|
|
|
|
|
|
|
|
if (outTimeInfo)
|
|
|
|
|
{
|
|
|
|
|
std::memcpy(outTimeInfo.get_ptr(), &content_id.second->timeInfo, sizeof(content_id.second->timeInfo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else // content ID not found, perform a search first
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_OUT_OF_RANGE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetContentInfoGameComment(vm::cptr<CellSearchContentId> contentId, vm::ptr<char> gameComment)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchGetContentInfoGameComment(contentId=*0x%x, gameComment=*0x%x)", contentId, gameComment);
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (!contentId || !gameComment)
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
// TODO: find out if this check is correct
|
|
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
|
|
|
|
{
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(*reinterpret_cast<const u64*>(contentId->data));
|
|
|
|
|
if (found == content_map.map.end())
|
|
|
|
|
{
|
|
|
|
|
// content ID not found, perform a search first
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& content_info = found->second;
|
|
|
|
|
switch (content_info->type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_MUSIC:
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_PHOTO:
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_VIDEO:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_CONTENTTYPE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: retrieve gameComment
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptr<CellSearchContentId> contentId, CellSearchRepeatMode repeatMode, CellSearchContextOption option, vm::ptr<CellMusicSelectionContext> outContext)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2019-12-02 22:31:34 +01:00
|
|
|
cellSearch.todo("cellSearchGetMusicSelectionContext(searchId=0x%x, contentId=*0x%x, repeatMode=0x%x, option=0x%x, outContext=*0x%x)", searchId, contentId, +repeatMode, +option, outContext);
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
if (!outContext)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto searchObject = idm::get<search_object_t>(searchId);
|
|
|
|
|
|
|
|
|
|
if (!searchObject)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-20 19:01:21 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
// TODO: find out if this check is correct
|
2022-02-20 19:01:21 +01:00
|
|
|
if (error_code error = check_search_state(search.state.load(), search_state::in_progress))
|
2021-09-16 23:05:29 +02:00
|
|
|
{
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (searchObject->content_ids.empty())
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-20 19:01:21 +01:00
|
|
|
music_selection_context context;
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
// Use the first track in order to get info about this search
|
|
|
|
|
const auto& first_content_id = searchObject->content_ids[0];
|
|
|
|
|
const auto& first_content = first_content_id.second;
|
|
|
|
|
ensure(first_content);
|
|
|
|
|
|
|
|
|
|
if (contentId)
|
|
|
|
|
{
|
|
|
|
|
// Try to find the specified content
|
|
|
|
|
const u64 content_hash = *reinterpret_cast<const u64*>(contentId->data);
|
|
|
|
|
auto content = std::find_if(searchObject->content_ids.begin(), searchObject->content_ids.end(), [&content_hash](const content_id_type& cid){ return cid.first == content_hash; });
|
|
|
|
|
if (content != searchObject->content_ids.cend() && content->second)
|
|
|
|
|
{
|
|
|
|
|
// Check if the type of the found content is correct
|
2022-02-20 15:22:41 +01:00
|
|
|
if (content->second->type != CELL_SEARCH_CONTENTTYPE_MUSIC)
|
|
|
|
|
{
|
|
|
|
|
return { CELL_SEARCH_ERROR_INVALID_CONTENTTYPE, fmt::format("Type: %d, Expected: CELL_SEARCH_CONTENTTYPE_MUSIC")};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if the type of the found content matches our search content type
|
2021-09-16 23:05:29 +02:00
|
|
|
if (content->second->type != first_content->type)
|
|
|
|
|
{
|
2022-02-20 15:22:41 +01:00
|
|
|
return { CELL_SEARCH_ERROR_NOT_SUPPORTED_CONTEXT, fmt::format("Type: %d, Expected: %d", +content->second->type, +first_content->type) };
|
2021-09-16 23:05:29 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-20 19:01:21 +01:00
|
|
|
// Use the found content
|
|
|
|
|
context.path = content->second->infoPath.contentPath;
|
|
|
|
|
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning found track: Type=0x%x, Path=%s", content_hash, +content->second->type, context.path);
|
2021-09-16 23:05:29 +02:00
|
|
|
}
|
|
|
|
|
else if (first_content->type == CELL_SEARCH_CONTENTTYPE_MUSICLIST)
|
|
|
|
|
{
|
|
|
|
|
// Abort if we can't find the playlist.
|
2022-02-20 15:22:41 +01:00
|
|
|
return { CELL_SEARCH_ERROR_CONTENT_NOT_FOUND, "Type: CELL_SEARCH_CONTENTTYPE_MUSICLIST" };
|
2021-09-16 23:05:29 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-02-20 19:01:21 +01:00
|
|
|
// Select the first track by default
|
|
|
|
|
context.path = first_content->infoPath.contentPath;
|
|
|
|
|
cellSearch.notice("cellSearchGetMusicSelectionContext(): Hash=%08X, Assigning first track: Type=0x%x, Path=%s", content_hash, +first_content->type, context.path);
|
2021-09-16 23:05:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (first_content->type == CELL_SEARCH_CONTENTTYPE_MUSICLIST)
|
|
|
|
|
{
|
|
|
|
|
// Abort if we don't have the necessary info to select a playlist.
|
2022-02-20 15:22:41 +01:00
|
|
|
return { CELL_SEARCH_ERROR_NOT_SUPPORTED_CONTEXT, "Type: CELL_SEARCH_CONTENTTYPE_MUSICLIST" };
|
2021-09-16 23:05:29 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-02-20 19:01:21 +01:00
|
|
|
// Select the first track by default
|
|
|
|
|
context.path = first_content->infoPath.contentPath;
|
|
|
|
|
cellSearch.notice("cellSearchGetMusicSelectionContext(): Assigning first track: Type=0x%x, Path=%s", +first_content->type, context.path);
|
2021-09-16 23:05:29 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-20 19:01:21 +01:00
|
|
|
context.content_type = first_content->type;
|
|
|
|
|
context.repeat_mode = repeatMode;
|
|
|
|
|
context.context_option = option;
|
|
|
|
|
|
|
|
|
|
// Resolve hashed paths
|
|
|
|
|
if (auto found = search.content_links.find(context.path); found != search.content_links.end())
|
|
|
|
|
{
|
|
|
|
|
context.path = found->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*outContext = context.get();
|
|
|
|
|
|
|
|
|
|
cellSearch.success("cellSearchGetMusicSelectionContext: found selection context: %d", context.to_string());
|
2021-09-16 23:05:29 +02:00
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetMusicSelectionContextOfSingleTrack(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellMusicSelectionContext> outContext)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchGetMusicSelectionContextOfSingleTrack(contentId=*0x%x, outContext=*0x%x)", contentId, outContext);
|
|
|
|
|
|
|
|
|
|
if (!contentId || !outContext)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
// TODO: find out if this check is correct
|
|
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
|
|
|
|
{
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(*reinterpret_cast<const u64*>(contentId->data));
|
|
|
|
|
if (found == content_map.map.end())
|
|
|
|
|
{
|
|
|
|
|
// content ID not found, perform a search first
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& content_info = found->second;
|
|
|
|
|
if (content_info->type != CELL_SEARCH_CONTENTTYPE_MUSIC)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_CONTENTTYPE;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-20 19:01:21 +01:00
|
|
|
music_selection_context context;
|
|
|
|
|
context.path = content_info->infoPath.contentPath;
|
|
|
|
|
|
|
|
|
|
*outContext = context.get();
|
|
|
|
|
|
|
|
|
|
cellSearch.success("cellSearchGetMusicSelectionContextOfSingleTrack: found selection context: %s", context.to_string());
|
2021-09-16 23:05:29 +02:00
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetContentInfoPath(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchContentInfoPath> infoPath)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchGetContentInfoPath(contentId=*0x%x, infoPath=*0x%x)", contentId, infoPath);
|
|
|
|
|
|
|
|
|
|
if (!infoPath)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u64 id = *reinterpret_cast<const u64*>(contentId->data);
|
2021-03-02 17:22:39 +01:00
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(id);
|
|
|
|
|
if(found != content_map.map.end())
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
|
|
|
|
std::memcpy(infoPath.get_ptr(), &found->second->infoPath, sizeof(found->second->infoPath));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cellSearch.error("cellSearchGetContentInfoPath(): ID not found : 0x%08X", id);
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-20 19:01:21 +01:00
|
|
|
cellSearch.success("contentId=%08X, contentPath=\"%s\"", id, infoPath->contentPath);
|
2020-02-08 11:07:18 +01:00
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetContentInfoPathMovieThumb(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchContentInfoPathMovieThumb> infoMt)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchGetContentInfoPathMovieThumb(contentId=*0x%x, infoMt=*0x%x)", contentId, infoMt);
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (!contentId || !infoMt)
|
2017-12-28 22:38:29 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
// TODO: find out if this check is correct
|
|
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
|
|
|
|
{
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(*reinterpret_cast<const u64*>(contentId->data));
|
|
|
|
|
if (found == content_map.map.end())
|
|
|
|
|
{
|
|
|
|
|
// content ID not found, perform a search first
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& content_info = found->second;
|
|
|
|
|
if (content_info->type != CELL_SEARCH_CONTENTTYPE_VIDEO)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_CONTENTTYPE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strcpy_trunc(infoMt->movieThumbnailPath, content_info->infoPath.thumbnailPath);
|
|
|
|
|
// TODO: set infoMt->movieThumbnailOption
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchPrepareFile(vm::cptr<char> path)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchPrepareFile(path=%s)", path);
|
|
|
|
|
|
|
|
|
|
if (!path)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
auto& search = g_fxo->get<search_info>();
|
2021-09-16 23:05:29 +02:00
|
|
|
|
|
|
|
|
if (error_code error = check_search_state(search.state.load(), search_state::in_progress))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
reader_lock lock(search.links_mutex);
|
|
|
|
|
auto found = search.content_links.find(path.get_ptr());
|
|
|
|
|
if (found != search.content_links.end())
|
2020-02-08 18:07:18 +01:00
|
|
|
{
|
|
|
|
|
vfs::mount(found->first, vfs::get(found->second));
|
|
|
|
|
}
|
2020-02-08 11:07:18 +01:00
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetContentInfoDeveloperData(vm::cptr<CellSearchContentId> contentId, vm::ptr<char> developerData)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchGetContentInfoDeveloperData(contentId=*0x%x, developerData=*0x%x)", contentId, developerData);
|
|
|
|
|
|
|
|
|
|
if (!contentId || !developerData)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
// TODO: find out if this check is correct
|
|
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
|
|
|
|
{
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(*reinterpret_cast<const u64*>(contentId->data));
|
|
|
|
|
if (found == content_map.map.end())
|
|
|
|
|
{
|
|
|
|
|
// content ID not found, perform a search first
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& content_info = found->second;
|
|
|
|
|
switch (content_info->type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_VIDEO:
|
|
|
|
|
case CELL_SEARCH_CONTENTTYPE_SCENE:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_CONTENTTYPE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: retrieve developerData
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchGetContentInfoSharable(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchSharableType> sharable)
|
2017-08-09 18:41:09 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchGetContentInfoSharable(contentId=*0x%x, sharable=*0x%x)", contentId, sharable);
|
|
|
|
|
|
|
|
|
|
if (!contentId || !sharable)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
// TODO: find out if this check is correct
|
|
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
|
|
|
|
|
{
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
auto found = content_map.map.find(*reinterpret_cast<const u64*>(contentId->data));
|
|
|
|
|
if (found == content_map.map.end())
|
|
|
|
|
{
|
|
|
|
|
// content ID not found, perform a search first
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& content_info = found->second;
|
|
|
|
|
if (content_info->type != CELL_SEARCH_CONTENTTYPE_VIDEO)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_CONTENTTYPE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: retrieve sharable
|
|
|
|
|
*sharable = CELL_SEARCH_SHARABLETYPE_PROHIBITED;
|
|
|
|
|
|
2017-08-09 18:41:09 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchCancel(CellSearchId searchId)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2017-12-28 22:38:29 +01:00
|
|
|
cellSearch.todo("cellSearchCancel(searchId=0x%x)", searchId);
|
|
|
|
|
|
|
|
|
|
const auto searchObject = idm::get<search_object_t>(searchId);
|
|
|
|
|
|
|
|
|
|
if (!searchObject)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::canceling))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 22:38:29 +01:00
|
|
|
error_code cellSearchEnd(CellSearchId searchId)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2020-02-08 11:07:18 +01:00
|
|
|
cellSearch.todo("cellSearchEnd(searchId=0x%x)", searchId);
|
|
|
|
|
|
2021-09-16 23:05:29 +02:00
|
|
|
if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::finalizing))
|
2020-02-08 11:07:18 +01:00
|
|
|
{
|
2021-09-16 23:05:29 +02:00
|
|
|
return error;
|
2020-02-08 11:07:18 +01:00
|
|
|
}
|
2017-12-28 22:38:29 +01:00
|
|
|
|
|
|
|
|
const auto searchObject = idm::get<search_object_t>(searchId);
|
|
|
|
|
|
|
|
|
|
if (!searchObject)
|
|
|
|
|
{
|
|
|
|
|
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
idm::remove<search_object_t>(searchId);
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-21 20:43:03 +01:00
|
|
|
DECLARE(ppu_module_manager::cellSearch)("cellSearchUtility", []()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2016-03-21 20:43:03 +01:00
|
|
|
REG_FUNC(cellSearchUtility, cellSearchInitialize);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchFinalize);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchStartListSearch);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchStartContentSearchInList);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchStartContentSearch);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchStartSceneSearchInVideo);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchStartSceneSearch);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoByOffset);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoByContentId);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetOffsetByContentId);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetContentIdByOffset);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoGameComment);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetMusicSelectionContext);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetMusicSelectionContextOfSingleTrack);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoPath);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoPathMovieThumb);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchPrepareFile);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoDeveloperData);
|
2017-08-09 18:41:09 +02:00
|
|
|
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoSharable);
|
2016-03-21 20:43:03 +01:00
|
|
|
REG_FUNC(cellSearchUtility, cellSearchCancel);
|
|
|
|
|
REG_FUNC(cellSearchUtility, cellSearchEnd);
|
2015-02-22 12:38:14 +01:00
|
|
|
});
|
2022-02-20 19:01:21 +01:00
|
|
|
|
|
|
|
|
// Helper
|
|
|
|
|
error_code music_selection_context::find_content_id(vm::ptr<CellSearchContentId> contents_id)
|
|
|
|
|
{
|
|
|
|
|
if (!contents_id)
|
|
|
|
|
return CELL_MUSIC_ERROR_PARAM;
|
|
|
|
|
|
|
|
|
|
// Search for the content that matches our current selection
|
|
|
|
|
auto& content_map = g_fxo->get<content_id_map>();
|
|
|
|
|
const u64 hash = std::hash<std::string>()(this->path);
|
|
|
|
|
auto found = content_map.map.find(hash);
|
|
|
|
|
if (found != content_map.map.end())
|
|
|
|
|
{
|
|
|
|
|
// TODO: check if the content type is correct
|
|
|
|
|
const u128 content_id_128 = found->first;
|
|
|
|
|
std::memcpy(contents_id->data, &content_id_128, CELL_SEARCH_CONTENT_ID_SIZE);
|
|
|
|
|
cellSearch.warning("find_content_id: found existing content for %s (path control: '%s')", to_string(), found->second->infoPath.contentPath);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Try to find the content manually
|
|
|
|
|
const std::string vpath = vfs::get("/dev_hdd0/music/");
|
|
|
|
|
for (auto&& entry : fs::dir(vpath))
|
|
|
|
|
{
|
|
|
|
|
entry.name = vfs::unescape(entry.name);
|
|
|
|
|
|
|
|
|
|
if (!entry.is_directory || entry.name == "." || entry.name == "..")
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string dir_path = vpath + entry.name;
|
|
|
|
|
|
|
|
|
|
if (content_type == CELL_SEARCH_CONTENTTYPE_MUSICLIST)
|
|
|
|
|
{
|
|
|
|
|
const u64 dir_hash = std::hash<std::string>()(dir_path);
|
|
|
|
|
|
|
|
|
|
if (hash == dir_hash)
|
|
|
|
|
{
|
|
|
|
|
u32 num_of_items = 0;
|
|
|
|
|
for (auto&& file : fs::dir(dir_path))
|
|
|
|
|
{
|
|
|
|
|
file.name = vfs::unescape(file.name);
|
|
|
|
|
|
|
|
|
|
if (file.is_directory || file.name == "." || file.name == "..")
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
num_of_items++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: check for actual content inside the directory
|
|
|
|
|
std::shared_ptr<search_content_t> curr_find = std::make_shared<search_content_t>();
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_MUSICLIST;
|
|
|
|
|
strcpy_trunc(curr_find->infoPath.contentPath, entry.name); // only save dir name due to 63 character limit
|
|
|
|
|
CellSearchMusicListInfo& info = curr_find->data.music_list;
|
|
|
|
|
info.listType = CELL_SEARCH_LISTSEARCHTYPE_MUSIC_ALBUM;
|
|
|
|
|
info.numOfItems = num_of_items;
|
|
|
|
|
info.duration = 0;
|
|
|
|
|
strcpy_trunc(info.title, entry.name);
|
|
|
|
|
strcpy_trunc(info.artistName, "ARTIST NAME");
|
|
|
|
|
content_map.map.emplace(dir_hash, curr_find);
|
|
|
|
|
const u128 content_id_128 = dir_hash;
|
|
|
|
|
std::memcpy(contents_id->data, &content_id_128, CELL_SEARCH_CONTENT_ID_SIZE);
|
|
|
|
|
cellSearch.warning("find_content_id: found music list %s (path control: '%s')", to_string(), dir_path);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Search the subfolders. We assume all music is located in a depth of 2 (max_depth, root + 1 folder + file).
|
|
|
|
|
for (auto&& item : fs::dir(dir_path))
|
|
|
|
|
{
|
|
|
|
|
if (item.is_directory || item.name == "." || item.name == "..")
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string file_path = dir_path + "/" + item.name;
|
|
|
|
|
const u64 file_hash = std::hash<std::string>()(file_path);
|
|
|
|
|
|
|
|
|
|
if (hash == file_hash)
|
|
|
|
|
{
|
|
|
|
|
const auto [success, mi] = utils::get_media_info(path, 1); // AVMEDIA_TYPE_AUDIO
|
|
|
|
|
if (!success)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::shared_ptr<search_content_t> curr_find = std::make_shared<search_content_t>();
|
|
|
|
|
curr_find->type = CELL_SEARCH_CONTENTTYPE_MUSIC;
|
|
|
|
|
const std::string short_path = entry.name + "/" + item.name; // only save dir name and item name due to 63 character limit
|
|
|
|
|
strcpy_trunc(curr_find->infoPath.contentPath, short_path);
|
|
|
|
|
populate_music_info(curr_find->data.music, mi, item);
|
|
|
|
|
content_map.map.emplace(file_hash, curr_find);
|
|
|
|
|
const u128 content_id_128 = file_hash;
|
|
|
|
|
std::memcpy(contents_id->data, &content_id_128, CELL_SEARCH_CONTENT_ID_SIZE);
|
|
|
|
|
cellSearch.warning("find_content_id: found music track %s (path control: '%s')", to_string(), file_path);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// content ID not found
|
|
|
|
|
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
|
|
|
|
|
}
|