From 1a2fad4eac93590b386f749f3f70498633efb65d Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 16 Sep 2021 23:05:29 +0200 Subject: [PATCH] cellSearch: more stubs and implementations (#10578) --- rpcs3/Emu/Cell/Modules/cellSearch.cpp | 546 ++++++++++++++++---------- 1 file changed, 332 insertions(+), 214 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellSearch.cpp b/rpcs3/Emu/Cell/Modules/cellSearch.cpp index 173ad4a46b..465acbfd66 100644 --- a/rpcs3/Emu/Cell/Modules/cellSearch.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSearch.cpp @@ -113,6 +113,81 @@ void parse_metadata(D& dst, const utils::media_info& mi, const std::string& key, 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) { 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::ptrget(); - 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: - 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; + return error; } search.func = func; @@ -327,20 +395,9 @@ error_code cellSearchFinalize() auto& search = g_fxo->get(); - 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: - 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; + return error; } sysutil_register_cb([&search](ppu_thread& ppu) -> s32 @@ -396,20 +453,9 @@ error_code cellSearchStartListSearch(CellSearchListSearchType type, CellSearchSo auto& search = g_fxo->get(); - 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: - 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; + return error; } const u32 id = *outSearchId = idm::make(); @@ -465,12 +511,7 @@ error_code cellSearchStartListSearch(CellSearchListSearchType type, CellSearchSo { item.name = vfs::unescape(item.name); - if (item.name == "." || item.name == "..") - { - continue; - } - - if (!item.is_directory) + if (item.name == "." || item.name == ".." || !item.is_directory) { continue; } @@ -623,20 +664,9 @@ error_code cellSearchStartContentSearchInList(vm::cptr list auto& search = g_fxo->get(); - 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: - 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; + return error; } auto& content_map = g_fxo->get(); @@ -860,20 +890,9 @@ error_code cellSearchStartContentSearch(CellSearchContentSearchType type, CellSe auto& search = g_fxo->get(); - 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: - 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; + return error; } const u32 id = *outSearchId = idm::make(); @@ -1033,20 +1052,23 @@ error_code cellSearchStartSceneSearchInVideo(vm::cptr video auto& search = g_fxo->get(); - 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: - 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; + return error; + } + + auto& content_map = g_fxo->get(); + auto found = content_map.map.find(*reinterpret_cast(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; } const u32 id = *outSearchId = idm::make(); @@ -1087,22 +1109,27 @@ error_code cellSearchStartSceneSearch(CellSearchSceneSearchType searchType, vm:: 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(); - 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: - 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; + return error; } const u32 id = *outSearchId = idm::make(); @@ -1137,48 +1164,38 @@ error_code cellSearchGetContentInfoByOffset(CellSearchId searchId, s32 offset, v return CELL_SEARCH_ERROR_INVALID_SEARCHID; } - switch (g_fxo->get().state.load()) + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) { - 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; + return error; } if (offset >= 0 && offset + 0u < searchObject->content_ids.size()) { const auto& content_id = searchObject->content_ids[offset]; const auto& content_info = content_id.second; + switch (content_info->type) { 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; 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; 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; 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; 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; 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; 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; default: return CELL_SEARCH_ERROR_GENERIC; @@ -1205,20 +1222,9 @@ error_code cellSearchGetContentInfoByContentId(vm::cptr con return CELL_SEARCH_ERROR_PARAM; } - switch (g_fxo->get().state.load()) + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) { - 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; + return error; } auto& content_map = g_fxo->get(); @@ -1229,25 +1235,25 @@ error_code cellSearchGetContentInfoByContentId(vm::cptr con switch (content_info->type) { 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; 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; 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; 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; 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; 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; 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; default: return CELL_SEARCH_ERROR_GENERIC; @@ -1272,20 +1278,9 @@ error_code cellSearchGetOffsetByContentId(CellSearchId searchId, vm::cptrget().state.load()) + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) { - 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; + return error; } const auto searchObject = idm::get(searchId); @@ -1326,20 +1321,9 @@ error_code cellSearchGetContentIdByOffset(CellSearchId searchId, s32 offset, vm: return CELL_SEARCH_ERROR_INVALID_SEARCHID; } - switch (g_fxo->get().state.load()) + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) { - 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; + return error; } if (offset >= 0 && offset + 0u < searchObject->content_ids.size()) @@ -1367,11 +1351,38 @@ error_code cellSearchGetContentInfoGameComment(vm::cptr con { cellSearch.todo("cellSearchGetContentInfoGameComment(contentId=*0x%x, gameComment=*0x%x)", contentId, gameComment); - if (!gameComment) + if (!contentId || !gameComment) { return CELL_SEARCH_ERROR_PARAM; } + // TODO: find out if this check is correct + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) + { + return error; + } + + auto& content_map = g_fxo->get(); + auto found = content_map.map.find(*reinterpret_cast(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; } @@ -1391,6 +1402,63 @@ error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptrget().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(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; } @@ -1403,6 +1471,28 @@ error_code cellSearchGetMusicSelectionContextOfSingleTrack(vm::cptrget().state.load(), search_state::in_progress)) + { + return error; + } + + auto& content_map = g_fxo->get(); + auto found = content_map.map.find(*reinterpret_cast(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; } @@ -1415,20 +1505,9 @@ error_code cellSearchGetContentInfoPath(vm::cptr contentId, return CELL_SEARCH_ERROR_PARAM; } - switch (g_fxo->get().state.load()) + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) { - 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; + return error; } const u64 id = *reinterpret_cast(contentId->data); @@ -1453,11 +1532,34 @@ error_code cellSearchGetContentInfoPathMovieThumb(vm::cptr { cellSearch.todo("cellSearchGetContentInfoPathMovieThumb(contentId=*0x%x, infoMt=*0x%x)", contentId, infoMt); - if (!infoMt) + if (!contentId || !infoMt) { return CELL_SEARCH_ERROR_PARAM; } + // TODO: find out if this check is correct + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) + { + return error; + } + + auto& content_map = g_fxo->get(); + auto found = content_map.map.find(*reinterpret_cast(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; } @@ -1471,20 +1573,10 @@ error_code cellSearchPrepareFile(vm::cptr path) } auto& search = g_fxo->get(); - switch (search.state.load()) + + if (error_code error = check_search_state(search.state.load(), search_state::in_progress)) { - 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; + return error; } reader_lock lock(search.links_mutex); @@ -1506,6 +1598,32 @@ error_code cellSearchGetContentInfoDeveloperData(vm::cptr c return CELL_SEARCH_ERROR_PARAM; } + // TODO: find out if this check is correct + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) + { + return error; + } + + auto& content_map = g_fxo->get(); + auto found = content_map.map.find(*reinterpret_cast(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; } @@ -1518,6 +1636,29 @@ error_code cellSearchGetContentInfoSharable(vm::cptr conten return CELL_SEARCH_ERROR_PARAM; } + // TODO: find out if this check is correct + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::in_progress)) + { + return error; + } + + auto& content_map = g_fxo->get(); + auto found = content_map.map.find(*reinterpret_cast(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; } @@ -1532,21 +1673,9 @@ error_code cellSearchCancel(CellSearchId searchId) return CELL_SEARCH_ERROR_INVALID_SEARCHID; } - switch (g_fxo->get().state.load()) + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::canceling)) { - 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; + return error; } // TODO @@ -1558,20 +1687,9 @@ error_code cellSearchEnd(CellSearchId searchId) { cellSearch.todo("cellSearchEnd(searchId=0x%x)", searchId); - switch (g_fxo->get().state.load()) + if (error_code error = check_search_state(g_fxo->get().state.load(), search_state::finalizing)) { - 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; + return error; } const auto searchObject = idm::get(searchId);