cellSearch: more stubs and implementations (#10578)

This commit is contained in:
Megamouse 2021-09-16 23:05:29 +02:00 committed by GitHub
parent da4f4dafbd
commit 1a2fad4eac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 332 additions and 214 deletions

View File

@ -113,6 +113,81 @@ void parse_metadata(D& dst, const utils::media_info& mi, const std::string& key,
strcpy_trunc(dst, value); strcpy_trunc(dst, value);
}; };
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;
}
void populate_music_info(CellSearchMusicInfo& info, const utils::media_info& mi, const fs::dir_entry& item) 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.artistName, mi, "artist", "Unknown Artist", CELL_SEARCH_TITLE_LEN_MAX);
@ -296,16 +371,9 @@ error_code cellSearchInitialize(CellSearchMode mode, u32 container, vm::ptr<Cell
auto& search = g_fxo->get<search_info>(); auto& search = g_fxo->get<search_info>();
switch (search.state.compare_and_swap(search_state::not_initialized, search_state::initializing)) if (error_code error = check_search_state(search.state.compare_and_swap(search_state::not_initialized, search_state::initializing), search_state::initializing))
{ {
case search_state::not_initialized: return error;
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;
} }
search.func = func; search.func = func;
@ -327,20 +395,9 @@ error_code cellSearchFinalize()
auto& search = g_fxo->get<search_info>(); auto& search = g_fxo->get<search_info>();
switch (search.state.compare_and_swap(search_state::idle, search_state::finalizing)) if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::finalizing), search_state::finalizing))
{ {
case search_state::idle: return error;
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;
} }
sysutil_register_cb([&search](ppu_thread& ppu) -> s32 sysutil_register_cb([&search](ppu_thread& ppu) -> s32
@ -396,20 +453,9 @@ error_code cellSearchStartListSearch(CellSearchListSearchType type, CellSearchSo
auto& search = g_fxo->get<search_info>(); auto& search = g_fxo->get<search_info>();
switch (search.state.compare_and_swap(search_state::idle, search_state::in_progress)) if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
const u32 id = *outSearchId = idm::make<search_object_t>(); const u32 id = *outSearchId = idm::make<search_object_t>();
@ -465,12 +511,7 @@ error_code cellSearchStartListSearch(CellSearchListSearchType type, CellSearchSo
{ {
item.name = vfs::unescape(item.name); item.name = vfs::unescape(item.name);
if (item.name == "." || item.name == "..") if (item.name == "." || item.name == ".." || !item.is_directory)
{
continue;
}
if (!item.is_directory)
{ {
continue; continue;
} }
@ -623,20 +664,9 @@ error_code cellSearchStartContentSearchInList(vm::cptr<CellSearchContentId> list
auto& search = g_fxo->get<search_info>(); auto& search = g_fxo->get<search_info>();
switch (search.state.compare_and_swap(search_state::idle, search_state::in_progress)) if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
auto& content_map = g_fxo->get<content_id_map>(); auto& content_map = g_fxo->get<content_id_map>();
@ -860,20 +890,9 @@ error_code cellSearchStartContentSearch(CellSearchContentSearchType type, CellSe
auto& search = g_fxo->get<search_info>(); auto& search = g_fxo->get<search_info>();
switch (search.state.compare_and_swap(search_state::idle, search_state::in_progress)) if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
const u32 id = *outSearchId = idm::make<search_object_t>(); const u32 id = *outSearchId = idm::make<search_object_t>();
@ -1033,20 +1052,23 @@ error_code cellSearchStartSceneSearchInVideo(vm::cptr<CellSearchContentId> video
auto& search = g_fxo->get<search_info>(); auto& search = g_fxo->get<search_info>();
switch (search.state.compare_and_swap(search_state::idle, search_state::in_progress)) if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
{ {
case search_state::idle: return error;
break; }
case search_state::not_initialized:
case search_state::initializing: auto& content_map = g_fxo->get<content_id_map>();
return CELL_SEARCH_ERROR_NOT_INITIALIZED; auto found = content_map.map.find(*reinterpret_cast<const u64*>(videoId->data));
case search_state::finalizing: if (found == content_map.map.end())
return CELL_SEARCH_ERROR_FINALIZING; {
case search_state::in_progress: // content ID not found, perform a search first
case search_state::canceling: return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
return CELL_SEARCH_ERROR_BUSY; }
default:
return CELL_SEARCH_ERROR_GENERIC; const auto& content_info = found->second;
if (content_info->type != CELL_SEARCH_CONTENTTYPE_VIDEO)
{
return CELL_SEARCH_ERROR_INVALID_CONTENTTYPE;
} }
const u32 id = *outSearchId = idm::make<search_object_t>(); const u32 id = *outSearchId = idm::make<search_object_t>();
@ -1087,22 +1109,27 @@ error_code cellSearchStartSceneSearch(CellSearchSceneSearchType searchType, vm::
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
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;
}
}
}
auto& search = g_fxo->get<search_info>(); auto& search = g_fxo->get<search_info>();
switch (search.state.compare_and_swap(search_state::idle, search_state::in_progress)) if (error_code error = check_search_state(search.state.compare_and_swap(search_state::idle, search_state::in_progress), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
const u32 id = *outSearchId = idm::make<search_object_t>(); const u32 id = *outSearchId = idm::make<search_object_t>();
@ -1137,48 +1164,38 @@ error_code cellSearchGetContentInfoByOffset(CellSearchId searchId, s32 offset, v
return CELL_SEARCH_ERROR_INVALID_SEARCHID; return CELL_SEARCH_ERROR_INVALID_SEARCHID;
} }
switch (g_fxo->get<search_info>().state.load()) if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
if (offset >= 0 && offset + 0u < searchObject->content_ids.size()) if (offset >= 0 && offset + 0u < searchObject->content_ids.size())
{ {
const auto& content_id = searchObject->content_ids[offset]; const auto& content_id = searchObject->content_ids[offset];
const auto& content_info = content_id.second; const auto& content_info = content_id.second;
switch (content_info->type) switch (content_info->type)
{ {
case CELL_SEARCH_CONTENTTYPE_MUSIC: case CELL_SEARCH_CONTENTTYPE_MUSIC:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.music, sizeof(content_info->data.music)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.music, sizeof(content_info->data.music));
break; break;
case CELL_SEARCH_CONTENTTYPE_PHOTO: case CELL_SEARCH_CONTENTTYPE_PHOTO:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo, sizeof(content_info->data.photo)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo, sizeof(content_info->data.photo));
break; break;
case CELL_SEARCH_CONTENTTYPE_VIDEO: case CELL_SEARCH_CONTENTTYPE_VIDEO:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.video, sizeof(content_info->data.photo)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.video, sizeof(content_info->data.photo));
break; break;
case CELL_SEARCH_CONTENTTYPE_MUSICLIST: case CELL_SEARCH_CONTENTTYPE_MUSICLIST:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.music_list, sizeof(content_info->data.music_list)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.music_list, sizeof(content_info->data.music_list));
break; break;
case CELL_SEARCH_CONTENTTYPE_PHOTOLIST: case CELL_SEARCH_CONTENTTYPE_PHOTOLIST:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo_list, sizeof(content_info->data.photo_list)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo_list, sizeof(content_info->data.photo_list));
break; break;
case CELL_SEARCH_CONTENTTYPE_VIDEOLIST: case CELL_SEARCH_CONTENTTYPE_VIDEOLIST:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.video_list, sizeof(content_info->data.video_list)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.video_list, sizeof(content_info->data.video_list));
break; break;
case CELL_SEARCH_CONTENTTYPE_SCENE: case CELL_SEARCH_CONTENTTYPE_SCENE:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.scene, sizeof(content_info->data.scene)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.scene, sizeof(content_info->data.scene));
break; break;
default: default:
return CELL_SEARCH_ERROR_GENERIC; return CELL_SEARCH_ERROR_GENERIC;
@ -1205,20 +1222,9 @@ error_code cellSearchGetContentInfoByContentId(vm::cptr<CellSearchContentId> con
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
switch (g_fxo->get<search_info>().state.load()) if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
auto& content_map = g_fxo->get<content_id_map>(); auto& content_map = g_fxo->get<content_id_map>();
@ -1229,25 +1235,25 @@ error_code cellSearchGetContentInfoByContentId(vm::cptr<CellSearchContentId> con
switch (content_info->type) switch (content_info->type)
{ {
case CELL_SEARCH_CONTENTTYPE_MUSIC: case CELL_SEARCH_CONTENTTYPE_MUSIC:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.music, sizeof(content_info->data.music)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.music, sizeof(content_info->data.music));
break; break;
case CELL_SEARCH_CONTENTTYPE_PHOTO: case CELL_SEARCH_CONTENTTYPE_PHOTO:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo, sizeof(content_info->data.photo)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo, sizeof(content_info->data.photo));
break; break;
case CELL_SEARCH_CONTENTTYPE_VIDEO: case CELL_SEARCH_CONTENTTYPE_VIDEO:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.video, sizeof(content_info->data.photo)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.video, sizeof(content_info->data.photo));
break; break;
case CELL_SEARCH_CONTENTTYPE_MUSICLIST: case CELL_SEARCH_CONTENTTYPE_MUSICLIST:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.music_list, sizeof(content_info->data.music_list)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.music_list, sizeof(content_info->data.music_list));
break; break;
case CELL_SEARCH_CONTENTTYPE_PHOTOLIST: case CELL_SEARCH_CONTENTTYPE_PHOTOLIST:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo_list, sizeof(content_info->data.photo_list)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.photo_list, sizeof(content_info->data.photo_list));
break; break;
case CELL_SEARCH_CONTENTTYPE_VIDEOLIST: case CELL_SEARCH_CONTENTTYPE_VIDEOLIST:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.video_list, sizeof(content_info->data.video_list)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.video_list, sizeof(content_info->data.video_list));
break; break;
case CELL_SEARCH_CONTENTTYPE_SCENE: case CELL_SEARCH_CONTENTTYPE_SCENE:
std::memcpy(infoBuffer.get_ptr(), &content_info->data.scene, sizeof(content_info->data.scene)); if (infoBuffer) std::memcpy(infoBuffer.get_ptr(), &content_info->data.scene, sizeof(content_info->data.scene));
break; break;
default: default:
return CELL_SEARCH_ERROR_GENERIC; return CELL_SEARCH_ERROR_GENERIC;
@ -1272,20 +1278,9 @@ error_code cellSearchGetOffsetByContentId(CellSearchId searchId, vm::cptr<CellSe
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
switch (g_fxo->get<search_info>().state.load()) if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
const auto searchObject = idm::get<search_object_t>(searchId); const auto searchObject = idm::get<search_object_t>(searchId);
@ -1326,20 +1321,9 @@ error_code cellSearchGetContentIdByOffset(CellSearchId searchId, s32 offset, vm:
return CELL_SEARCH_ERROR_INVALID_SEARCHID; return CELL_SEARCH_ERROR_INVALID_SEARCHID;
} }
switch (g_fxo->get<search_info>().state.load()) if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
if (offset >= 0 && offset + 0u < searchObject->content_ids.size()) if (offset >= 0 && offset + 0u < searchObject->content_ids.size())
@ -1367,11 +1351,38 @@ error_code cellSearchGetContentInfoGameComment(vm::cptr<CellSearchContentId> con
{ {
cellSearch.todo("cellSearchGetContentInfoGameComment(contentId=*0x%x, gameComment=*0x%x)", contentId, gameComment); cellSearch.todo("cellSearchGetContentInfoGameComment(contentId=*0x%x, gameComment=*0x%x)", contentId, gameComment);
if (!gameComment) if (!contentId || !gameComment)
{ {
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
// 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
return CELL_OK; return CELL_OK;
} }
@ -1391,6 +1402,63 @@ error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptr<Ce
return CELL_SEARCH_ERROR_INVALID_SEARCHID; return CELL_SEARCH_ERROR_INVALID_SEARCHID;
} }
// 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;
}
if (searchObject->content_ids.empty())
{
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
}
// 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
if (content->second->type != first_content->type)
{
return CELL_SEARCH_ERROR_NOT_SUPPORTED_CONTEXT;
}
// TODO: Use the found content
// first track/playlist of context = content->second;
}
else if (first_content->type == CELL_SEARCH_CONTENTTYPE_MUSICLIST)
{
// Abort if we can't find the playlist.
return CELL_SEARCH_ERROR_CONTENT_NOT_FOUND;
}
else
{
// TODO: Select the first track by default
// first track of context = first_content;
}
}
else if (first_content->type == CELL_SEARCH_CONTENTTYPE_MUSICLIST)
{
// Abort if we don't have the necessary info to select a playlist.
return CELL_SEARCH_ERROR_NOT_SUPPORTED_CONTEXT;
}
else
{
// TODO: Select the first track by default
// first track of context = first_content;
}
// TODO: Use repeatMode and option in our context, depending on the type (list vs single)
// TODO: assign outContext
return CELL_OK; return CELL_OK;
} }
@ -1403,6 +1471,28 @@ error_code cellSearchGetMusicSelectionContextOfSingleTrack(vm::cptr<CellSearchCo
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
// 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;
}
// TODO: assign outContext
return CELL_OK; return CELL_OK;
} }
@ -1415,20 +1505,9 @@ error_code cellSearchGetContentInfoPath(vm::cptr<CellSearchContentId> contentId,
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
switch (g_fxo->get<search_info>().state.load()) if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
const u64 id = *reinterpret_cast<const u64*>(contentId->data); const u64 id = *reinterpret_cast<const u64*>(contentId->data);
@ -1453,11 +1532,34 @@ error_code cellSearchGetContentInfoPathMovieThumb(vm::cptr<CellSearchContentId>
{ {
cellSearch.todo("cellSearchGetContentInfoPathMovieThumb(contentId=*0x%x, infoMt=*0x%x)", contentId, infoMt); cellSearch.todo("cellSearchGetContentInfoPathMovieThumb(contentId=*0x%x, infoMt=*0x%x)", contentId, infoMt);
if (!infoMt) if (!contentId || !infoMt)
{ {
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
// 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
return CELL_OK; return CELL_OK;
} }
@ -1471,20 +1573,10 @@ error_code cellSearchPrepareFile(vm::cptr<char> path)
} }
auto& search = g_fxo->get<search_info>(); auto& search = g_fxo->get<search_info>();
switch (search.state.load())
if (error_code error = check_search_state(search.state.load(), search_state::in_progress))
{ {
case search_state::idle: return error;
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;
} }
reader_lock lock(search.links_mutex); reader_lock lock(search.links_mutex);
@ -1506,6 +1598,32 @@ error_code cellSearchGetContentInfoDeveloperData(vm::cptr<CellSearchContentId> c
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
// 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
return CELL_OK; return CELL_OK;
} }
@ -1518,6 +1636,29 @@ error_code cellSearchGetContentInfoSharable(vm::cptr<CellSearchContentId> conten
return CELL_SEARCH_ERROR_PARAM; return CELL_SEARCH_ERROR_PARAM;
} }
// 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;
return CELL_OK; return CELL_OK;
} }
@ -1532,21 +1673,9 @@ error_code cellSearchCancel(CellSearchId searchId)
return CELL_SEARCH_ERROR_INVALID_SEARCHID; return CELL_SEARCH_ERROR_INVALID_SEARCHID;
} }
switch (g_fxo->get<search_info>().state.load()) if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::canceling))
{ {
case search_state::in_progress: return error;
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;
} }
// TODO // TODO
@ -1558,20 +1687,9 @@ error_code cellSearchEnd(CellSearchId searchId)
{ {
cellSearch.todo("cellSearchEnd(searchId=0x%x)", searchId); cellSearch.todo("cellSearchEnd(searchId=0x%x)", searchId);
switch (g_fxo->get<search_info>().state.load()) if (error_code error = check_search_state(g_fxo->get<search_info>().state.load(), search_state::finalizing))
{ {
case search_state::idle: return error;
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;
} }
const auto searchObject = idm::get<search_object_t>(searchId); const auto searchObject = idm::get<search_object_t>(searchId);