bool CDatabaseQueryRuleCombination::Save(CVariant &obj) const { if (!obj.isObject() || (m_combinations.empty() && m_rules.empty())) return false; CVariant comboArray(CVariant::VariantTypeArray); if (!m_combinations.empty()) { for (CDatabaseQueryRuleCombinations::const_iterator combo = m_combinations.begin(); combo != m_combinations.end(); combo++) { CVariant comboObj(CVariant::VariantTypeObject); if ((*combo)->Save(comboObj)) comboArray.push_back(comboObj); } } if (!m_rules.empty()) { for (CDatabaseQueryRules::const_iterator rule = m_rules.begin(); rule != m_rules.end(); rule++) { CVariant ruleObj(CVariant::VariantTypeObject); if ((*rule)->Save(ruleObj)) comboArray.push_back(ruleObj); } } obj[TranslateCombinationType()] = comboArray; return true; }
TEST_F(TestWebServer, CanGetJsonRpcResponse) { // initialized JSON-RPC JSONRPC::CJSONRPC::Initialize(); std::string result; CCurlFile curl; curl.SetMimeType("application/json"); ASSERT_TRUE(curl.Post(GetUrl(TEST_URL_JSONRPC), "{ \"jsonrpc\": \"2.0\", \"method\": \"JSONRPC.Version\", \"id\": 1 }", result)); ASSERT_FALSE(result.empty()); // parse the JSON-RPC response CVariant resultObj = CJSONVariantParser::Parse(reinterpret_cast<const unsigned char*>(result.c_str()), result.size()); // make sure it's an object ASSERT_TRUE(resultObj.isObject()); // get the HTTP header details const CHttpHeader& httpHeader = curl.GetHttpHeader(); // Content-Type must be "application/json" EXPECT_STREQ("application/json", httpHeader.GetMimeType().c_str()); // Accept-Ranges must be "none" EXPECT_STREQ("none", httpHeader.GetValue(MHD_HTTP_HEADER_ACCEPT_RANGES).c_str()); // Cache-Control must contain "mag-age=0" and "no-cache" std::string cacheControl = httpHeader.GetValue(MHD_HTTP_HEADER_CACHE_CONTROL); EXPECT_TRUE(cacheControl.find("max-age=0") != std::string::npos); EXPECT_TRUE(cacheControl.find("no-cache") != std::string::npos); // uninitialize JSON-RPC JSONRPC::CJSONRPC::Cleanup(); }
void CJSONVariantParser::PushObject(CVariant variant) { if (m_status == ParseObject) { (*m_parse[m_parse.size() - 1])[m_key] = variant; m_parse.push_back(&(*m_parse[m_parse.size() - 1])[m_key]); } else if (m_status == ParseArray) { CVariant *temp = m_parse[m_parse.size() - 1]; temp->push_back(variant); m_parse.push_back(&(*temp)[temp->size() - 1]); } else if (m_parse.size() == 0) { m_parse.push_back(new CVariant(variant)); } if (variant.isObject()) m_status = ParseObject; else if (variant.isArray()) m_status = ParseArray; else m_status = ParseVariable; }
void CAnnouncementManager::Announce(EAnnouncementFlag flag, const char *sender, const char *message, CFileItemPtr item, CVariant &data) { // Extract db id of item CVariant object = data.isNull() || data.isObject() ? data : CVariant::VariantTypeObject; CStdString type; int id = 0; if (item->HasVideoInfoTag()) { CVideoDatabase::VideoContentTypeToString((VIDEODB_CONTENT_TYPE)item->GetVideoContentType(), type); id = item->GetVideoInfoTag()->m_iDbId; } else if (item->HasMusicInfoTag()) { if (item->IsAlbum()) type = "album"; else type = "song"; id = item->GetMusicInfoTag()->GetDatabaseId(); } else type = "unknown"; object["type"] = type; if (id > 0) object["id"] = id; Announce(flag, sender, message, object); }
bool CDatabaseQueryRule::Load(const CVariant &obj) { if (!obj.isObject() || !obj.isMember("field") || !obj["field"].isString() || !obj.isMember("operator") || !obj["operator"].isString()) return false; m_field = TranslateField(obj["field"].asString().c_str()); m_operator = TranslateOperator(obj["operator"].asString().c_str()); if (m_operator == OPERATOR_TRUE || m_operator == OPERATOR_FALSE) return true; if (!obj.isMember("value") || (!obj["value"].isString() && !obj["value"].isArray())) return false; const CVariant &value = obj["value"]; if (value.isString()) m_parameter.push_back(value.asString()); else if (value.isArray()) { for (CVariant::const_iterator_array val = value.begin_array(); val != value.end_array(); val++) { if (val->isString() && !val->asString().empty()) m_parameter.push_back(val->asString()); } if (m_parameter.empty()) m_parameter.push_back(""); } else return false; return true; }
void CAnnouncementManager::Announce(EAnnouncementFlag flag, const char *sender, const char *message, CFileItemPtr item, CVariant &data) { // Extract db id of item CVariant object = data.isNull() || data.isObject() ? data : CVariant::VariantTypeObject; CStdString type; int id = 0; if (item->HasVideoInfoTag()) { CVideoDatabase::VideoContentTypeToString(item->GetVideoContentType(), type); id = item->GetVideoInfoTag()->m_iDbId; } else if (item->HasMusicInfoTag()) { type = "music"; id = item->GetMusicInfoTag()->GetDatabaseId(); } if (id > 0) { type += "id"; object[type] = id; } Announce(flag, sender, message, object); }
TEST(TestVariant, VariantTypeObject) { CVariant a; a["key"] = "value"; EXPECT_TRUE(a.isObject()); EXPECT_EQ(CVariant::VariantTypeObject, a.type()); }
bool CDatabaseQueryRuleCombination::Load(const CVariant &obj, const IDatabaseQueryRuleFactory *factory) { if (!obj.isObject() && !obj.isArray()) return false; CVariant child; if (obj.isObject()) { if (obj.isMember("and") && obj["and"].isArray()) { m_type = CombinationAnd; child = obj["and"]; } else if (obj.isMember("or") && obj["or"].isArray()) { m_type = CombinationOr; child = obj["or"]; } else return false; } else child = obj; for (CVariant::const_iterator_array it = child.begin_array(); it != child.end_array(); it++) { if (!it->isObject()) continue; if (it->isMember("and") || it->isMember("or")) { boost::shared_ptr<CDatabaseQueryRuleCombination> combo(factory->CreateCombination()); if (combo && combo->Load(*it, factory)) m_combinations.push_back(combo); } else { boost::shared_ptr<CDatabaseQueryRule> rule(factory->CreateRule()); if (rule && rule->Load(*it)) m_rules.push_back(rule); } } return true; }
TEST(TestVariant, VariantFromMap) { std::map<std::string, std::string> strMap; strMap["key"] = "value"; CVariant a = strMap; EXPECT_TRUE(a.isObject()); EXPECT_TRUE(a.size() == 1); EXPECT_EQ(CVariant::VariantTypeObject, a.type()); EXPECT_TRUE(a.isMember("key")); EXPECT_TRUE(a["key"].isString()); EXPECT_STREQ(a["key"].asString().c_str(), "value"); std::map<std::string, CVariant> variantMap; variantMap["key"] = CVariant("value"); CVariant b = variantMap; EXPECT_TRUE(b.isObject()); EXPECT_TRUE(b.size() == 1); EXPECT_EQ(CVariant::VariantTypeObject, b.type()); EXPECT_TRUE(b.isMember("key")); EXPECT_TRUE(b["key"].isString()); EXPECT_STREQ(b["key"].asString().c_str(), "value"); }
JSONRPC_STATUS CAddonsOperations::ExecuteAddon(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { std::string id = parameterObject["addonid"].asString(); AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon) || addon.get() == NULL || addon->Type() < ADDON_VIZ || addon->Type() >= ADDON_MAX) return InvalidParams; std::string argv; CVariant params = parameterObject["params"]; if (params.isObject()) { for (CVariant::const_iterator_map it = params.begin_map(); it != params.end_map(); it++) { if (it != params.begin_map()) argv += ","; argv += it->first + "=" + it->second.asString(); } } else if (params.isArray()) { for (CVariant::const_iterator_array it = params.begin_array(); it != params.end_array(); it++) { if (it != params.begin_array()) argv += ","; argv += StringUtils::Paramify(it->asString()); } } else if (params.isString()) { if (!params.empty()) argv = StringUtils::Paramify(params.asString()); } std::string cmd; if (params.empty()) cmd = StringUtils::Format("RunAddon(%s)", id.c_str()); else cmd = StringUtils::Format("RunAddon(%s, %s)", id.c_str(), argv.c_str()); if (params["wait"].asBoolean()) CApplicationMessenger::GetInstance().SendMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, cmd); else CApplicationMessenger::GetInstance().PostMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, cmd); return ACK; }
double CPlayerOperations::ParseTimeInSeconds(const CVariant &time) { double seconds = 0.0; if (time.isObject()) { if (time.isMember("hours")) seconds += time["hours"].asInteger() * 60 * 60; if (time.isMember("minutes")) seconds += time["minutes"].asInteger() * 60; if (time.isMember("seconds")) seconds += time["seconds"].asInteger(); if (time.isMember("milliseconds")) seconds += time["milliseconds"].asDouble() / 1000.0; } return seconds; }
inline void CJSONRPC::BuildResponse(const CVariant& request, JSON_STATUS code, const CVariant& result, CVariant& response) { response["jsonrpc"] = "2.0"; response["id"] = request.isObject() && request.isMember("id") ? request["id"] : CVariant(); switch (code) { case OK: response["result"] = result; break; case ACK: response["result"] = "OK"; break; case InvalidRequest: response["error"]["code"] = InvalidRequest; response["error"]["message"] = "Invalid request."; break; case InvalidParams: response["error"]["code"] = InvalidParams; response["error"]["message"] = "Invalid params."; if (!result.isNull()) response["error"]["data"] = result; break; case MethodNotFound: response["error"]["code"] = MethodNotFound; response["error"]["message"] = "Method not found."; break; case ParseError: response["error"]["code"] = ParseError; response["error"]["message"] = "Parse error."; break; case BadPermission: response["error"]["code"] = BadPermission; response["error"]["message"] = "Bad client permission."; break; case FailedToExecute: response["error"]["code"] = FailedToExecute; response["error"]["message"] = "Failed to execute method."; break; default: response["error"]["code"] = InternalError; response["error"]["message"] = "Internal error."; break; } }
bool CSmartPlaylist::Load(const CVariant &obj) { if (!obj.isObject() || !obj.isMember("match") || !obj["match"].isString() || !obj.isMember("rules") || !obj["rules"].isArray()) return false; // load the playlist type if (obj.isMember("type") && obj["type"].isString()) m_playlistType = obj["type"].asString(); // backward compatibility: if (m_playlistType == "music") m_playlistType = "songs"; if (m_playlistType == "video") m_playlistType = "musicvideos"; // load the playlist name if (obj.isMember("name") && obj["name"].isString()) m_playlistName = obj["name"].asString(); m_matchAllRules = strcmpi(obj["match"].asString().c_str(), "all") == 0; // now the rules for (CVariant::const_iterator_array it = obj["rules"].begin_array(); it != obj["rules"].end_array(); it++) { CSmartPlaylistRule rule; if (rule.Load(*it)) m_playlistRules.push_back(rule); } // now any limits if (obj.isMember("limit") && (obj["limit"].isInteger() || obj["limit"].isUnsignedInteger()) && obj["limit"].asUnsignedInteger() > 0) m_limit = (unsigned int)obj["limit"].asUnsignedInteger(); // and order if (obj.isMember("order") && obj["order"].isMember("method") && obj["order"]["method"].isString()) { if (obj["order"].isMember("direction") && obj["order"]["direction"].isString()) m_orderAscending = strcmpi(obj["order"]["direction"].asString().c_str(), "ascending") == 0; m_orderField = CSmartPlaylistRule::TranslateOrder(obj["order"]["method"].asString().c_str()); } return true; }
TEST(TestVariant, iterator_map) { CVariant a; a["key1"] = "string"; a["key2"] = "string"; a["key3"] = "string"; a["key4"] = "string"; EXPECT_TRUE(a.isObject()); EXPECT_EQ(CVariant::VariantTypeObject, a.type()); CVariant::iterator_map it; for (it = a.begin_map(); it != a.end_map(); it++) { EXPECT_STREQ("string", it->second.c_str()); } CVariant::const_iterator_map const_it; for (const_it = a.begin_map(); const_it != a.end_map(); const_it++) { EXPECT_STREQ("string", const_it->second.c_str()); } }
void CJSONVariantParser::PopObject() { CVariant *variant = m_parse[m_parse.size() - 1]; m_parse.pop_back(); if (m_parse.size()) { variant = m_parse[m_parse.size() - 1]; if (variant->isObject()) m_status = ParseObject; else if (variant->isArray()) m_status = ParseArray; else m_status = ParseVariable; } else if (m_callback) { m_callback->onParsed(variant); delete variant; m_parse.clear(); m_status = ParseVariable; } }
bool CMusicDbUrl::validateOption(const std::string &key, const CVariant &value) { if (!CDbUrl::validateOption(key, value)) return false; // if the value is empty it will remove the option which is ok // otherwise we only care about the "filter" option here if (value.empty() || !StringUtils::EqualsNoCase(key, "filter")) return true; if (!value.isString()) return false; if (!value.isObject()) return false; // load type CStdString type; if (value.isMember("type") && value["type"].isString()) type = value["type"].asString(); // check if the filter playlist matches the item type return type == m_type; }
void CAnnouncementManager::Announce(AnnouncementFlag flag, const char *sender, const char *message, CFileItemPtr item, CVariant &data) { if (!item.get()) { Announce(flag, sender, message, data); return; } // Extract db id of item CVariant object = data.isNull() || data.isObject() ? data : CVariant::VariantTypeObject; CStdString type; int id = 0; if(item->HasPVRChannelInfoTag()) { const PVR::CPVRChannel *channel = item->GetPVRChannelInfoTag(); id = channel->ChannelID(); type = "channel"; object["item"]["title"] = channel->ChannelName(); object["item"]["channeltype"] = channel->IsRadio() ? "radio" : "tv"; if (data.isMember("player") && data["player"].isMember("playerid")) object["player"]["playerid"] = channel->IsRadio() ? PLAYLIST_MUSIC : PLAYLIST_VIDEO; } else if (item->HasVideoInfoTag()) { id = item->GetVideoInfoTag()->m_iDbId; // TODO: Can be removed once this is properly handled when starting playback of a file if (id <= 0 && !item->GetPath().empty() && (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean())) { CVideoDatabase videodatabase; if (videodatabase.Open()) { if (videodatabase.LoadVideoInfo(item->GetPath(), *item->GetVideoInfoTag())) id = item->GetVideoInfoTag()->m_iDbId; videodatabase.Close(); } } if (!item->GetVideoInfoTag()->m_type.empty()) type = item->GetVideoInfoTag()->m_type; else CVideoDatabase::VideoContentTypeToString((VIDEODB_CONTENT_TYPE)item->GetVideoContentType(), type); if (id <= 0) { // TODO: Can be removed once this is properly handled when starting playback of a file item->SetProperty(LOOKUP_PROPERTY, false); object["item"]["title"] = item->GetVideoInfoTag()->m_strTitle; switch (item->GetVideoContentType()) { case VIDEODB_CONTENT_MOVIES: if (item->GetVideoInfoTag()->m_iYear > 0) object["item"]["year"] = item->GetVideoInfoTag()->m_iYear; break; case VIDEODB_CONTENT_EPISODES: if (item->GetVideoInfoTag()->m_iEpisode >= 0) object["item"]["episode"] = item->GetVideoInfoTag()->m_iEpisode; if (item->GetVideoInfoTag()->m_iSeason >= 0) object["item"]["season"] = item->GetVideoInfoTag()->m_iSeason; if (!item->GetVideoInfoTag()->m_strShowTitle.empty()) object["item"]["showtitle"] = item->GetVideoInfoTag()->m_strShowTitle; break; case VIDEODB_CONTENT_MUSICVIDEOS: if (!item->GetVideoInfoTag()->m_strAlbum.empty()) object["item"]["album"] = item->GetVideoInfoTag()->m_strAlbum; if (!item->GetVideoInfoTag()->m_artist.empty()) object["item"]["artist"] = StringUtils::Join(item->GetVideoInfoTag()->m_artist, " / "); break; } } } else if (item->HasMusicInfoTag()) { id = item->GetMusicInfoTag()->GetDatabaseId(); type = "song"; // TODO: Can be removed once this is properly handled when starting playback of a file if (id <= 0 && !item->GetPath().empty() && (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean())) { CMusicDatabase musicdatabase; if (musicdatabase.Open()) { CSong song; if (musicdatabase.GetSongByFileName(item->GetPath(), song, item->m_lStartOffset)) { item->GetMusicInfoTag()->SetSong(song); id = item->GetMusicInfoTag()->GetDatabaseId(); } musicdatabase.Close(); } } if (id <= 0) { // TODO: Can be removed once this is properly handled when starting playback of a file item->SetProperty(LOOKUP_PROPERTY, false); CStdString title = item->GetMusicInfoTag()->GetTitle(); if (title.IsEmpty()) title = item->GetLabel(); object["item"]["title"] = title; if (item->GetMusicInfoTag()->GetTrackNumber() > 0) object["item"]["track"] = item->GetMusicInfoTag()->GetTrackNumber(); if (!item->GetMusicInfoTag()->GetAlbum().empty()) object["item"]["album"] = item->GetMusicInfoTag()->GetAlbum(); if (!item->GetMusicInfoTag()->GetArtist().empty()) object["item"]["artist"] = item->GetMusicInfoTag()->GetArtist(); } } else if (item->HasPictureInfoTag()) { type = "picture"; object["item"]["file"] = item->GetPath(); } else type = "unknown"; object["item"]["type"] = type; if (id > 0) object["item"]["id"] = id; Announce(flag, sender, message, object); }
JSONRPC_STATUS CPlayerOperations::Open(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { CVariant optionShuffled = parameterObject["options"]["shuffled"]; CVariant optionRepeat = parameterObject["options"]["repeat"]; CVariant optionResume = parameterObject["options"]["resume"]; if (parameterObject["item"].isObject() && parameterObject["item"].isMember("playlistid")) { int playlistid = (int)parameterObject["item"]["playlistid"].asInteger(); if (playlistid < PLAYLIST_PICTURE) { // Apply the "shuffled" option if available if (optionShuffled.isBoolean()) g_playlistPlayer.SetShuffle(playlistid, optionShuffled.asBoolean(), false); // Apply the "repeat" option if available if (!optionRepeat.isNull()) g_playlistPlayer.SetRepeat(playlistid, (REPEAT_STATE)ParseRepeatState(optionRepeat), false); } switch (playlistid) { case PLAYLIST_MUSIC: case PLAYLIST_VIDEO: g_application.getApplicationMessenger().MediaPlay(playlistid, (int)parameterObject["item"]["position"].asInteger()); OnPlaylistChanged(); break; case PLAYLIST_PICTURE: return StartSlideshow(); break; } return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("path")) { CStdString exec = "slideShow("; exec += parameterObject["item"]["path"].asString(); if ((optionShuffled.isBoolean() && optionShuffled.asBoolean()) || (!optionShuffled.isBoolean() && parameterObject["item"]["random"].asBoolean())) exec += ", random"; else exec += ", notrandom"; if (parameterObject["item"]["recursive"].asBoolean()) exec += ", recursive"; exec += ")"; ThreadMessage msg = { TMSG_EXECUTE_BUILT_IN, (DWORD)0, (DWORD)0, exec }; g_application.getApplicationMessenger().SendMessage(msg); return ACK; } else { CFileItemList list; if (FillFileItemList(parameterObject["item"], list) && list.Size() > 0) { bool slideshow = true; for (int index = 0; index < list.Size(); index++) { if (!list[index]->IsPicture()) { slideshow = false; break; } } if (slideshow) { CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!slideshow) return FailedToExecute; SendSlideshowAction(ACTION_STOP); slideshow->Reset(); for (int index = 0; index < list.Size(); index++) slideshow->Add(list[index].get()); if (optionShuffled.isBoolean() && optionShuffled.asBoolean()) slideshow->Shuffle(); return StartSlideshow(); } else { // Handle "shuffled" option if (optionShuffled.isBoolean()) list.SetProperty("shuffled", optionShuffled); // Handle "repeat" option if (!optionRepeat.isNull()) list.SetProperty("repeat", ParseRepeatState(optionRepeat)); // Handle "resume" option if (list.Size() == 1) { if (optionResume.isBoolean() && optionResume.asBoolean()) list[0]->m_lStartOffset = STARTOFFSET_RESUME; else if (optionResume.isDouble()) list[0]->SetProperty("StartPercent", optionResume); else if (optionResume.isObject()) list[0]->m_lStartOffset = (int)(ParseTimeInSeconds(optionResume) * 75.0); } g_application.getApplicationMessenger().MediaPlay(list); } return ACK; } else return InvalidParams; } return InvalidParams; }
inline bool CJSONRPC::IsProperJSONRPC(const CVariant& inputroot) { return inputroot.isObject() && inputroot.isMember("jsonrpc") && inputroot["jsonrpc"].isString() && inputroot["jsonrpc"] == CVariant("2.0") && inputroot.isMember("method") && inputroot["method"].isString() && (!inputroot.isMember("params") || inputroot["params"].isArray() || inputroot["params"].isObject()); }
JSONRPC_STATUS CPlayerOperations::Open(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { CVariant options = parameterObject["options"]; CVariant optionShuffled = options["shuffled"]; CVariant optionRepeat = options["repeat"]; CVariant optionResume = options["resume"]; CVariant optionPlayer = options["playername"]; if (parameterObject["item"].isObject() && parameterObject["item"].isMember("playlistid")) { int playlistid = (int)parameterObject["item"]["playlistid"].asInteger(); if (playlistid < PLAYLIST_PICTURE) { // Apply the "shuffled" option if available if (optionShuffled.isBoolean()) g_playlistPlayer.SetShuffle(playlistid, optionShuffled.asBoolean(), false); // Apply the "repeat" option if available if (!optionRepeat.isNull()) g_playlistPlayer.SetRepeat(playlistid, (REPEAT_STATE)ParseRepeatState(optionRepeat), false); } int playlistStartPosition = (int)parameterObject["item"]["position"].asInteger(); switch (playlistid) { case PLAYLIST_MUSIC: case PLAYLIST_VIDEO: CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_PLAY, playlistid, playlistStartPosition); OnPlaylistChanged(); break; case PLAYLIST_PICTURE: { std::string firstPicturePath; if (playlistStartPosition > 0) { CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (slideshow != NULL) { CFileItemList list; slideshow->GetSlideShowContents(list); if (playlistStartPosition < list.Size()) firstPicturePath = list.Get(playlistStartPosition)->GetPath(); } } return StartSlideshow("", false, optionShuffled.isBoolean() && optionShuffled.asBoolean(), firstPicturePath); break; } } return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("path")) { bool random = (optionShuffled.isBoolean() && optionShuffled.asBoolean()) || (!optionShuffled.isBoolean() && parameterObject["item"]["random"].asBoolean()); return StartSlideshow(parameterObject["item"]["path"].asString(), parameterObject["item"]["recursive"].asBoolean(), random); } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("partymode")) { if (g_partyModeManager.IsEnabled()) g_partyModeManager.Disable(); CApplicationMessenger::GetInstance().SendMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, "playercontrol(partymode(" + parameterObject["item"]["partymode"].asString() + "))"); return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("channelid")) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRChannelGroupsContainer *channelGroupContainer = g_PVRChannelGroups; if (channelGroupContainer == NULL) return FailedToExecute; CPVRChannelPtr channel = channelGroupContainer->GetChannelById((int)parameterObject["item"]["channelid"].asInteger()); if (channel == NULL) return InvalidParams; if ((g_PVRManager.IsPlayingRadio() && channel->IsRadio()) || (g_PVRManager.IsPlayingTV() && !channel->IsRadio())) g_application.m_pPlayer->SwitchChannel(channel); else { CFileItemList *l = new CFileItemList; //don't delete, l->Add(std::make_shared<CFileItem>(channel)); CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, -1, -1, static_cast<void*>(l)); } return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("recordingid")) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRRecordings *recordingsContainer = g_PVRRecordings; if (recordingsContainer == NULL) return FailedToExecute; CFileItemPtr fileItem = recordingsContainer->GetById((int)parameterObject["item"]["recordingid"].asInteger()); if (fileItem == NULL) return InvalidParams; CFileItemList *l = new CFileItemList; //don't delete, l->Add(std::make_shared<CFileItem>(*fileItem)); CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, -1, -1, static_cast<void*>(l)); return ACK; } else { CFileItemList list; if (FillFileItemList(parameterObject["item"], list) && list.Size() > 0) { bool slideshow = true; for (int index = 0; index < list.Size(); index++) { if (!list[index]->IsPicture()) { slideshow = false; break; } } if (slideshow) { CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!slideshow) return FailedToExecute; SendSlideshowAction(ACTION_STOP); slideshow->Reset(); for (int index = 0; index < list.Size(); index++) slideshow->Add(list[index].get()); return StartSlideshow("", false, optionShuffled.isBoolean() && optionShuffled.asBoolean()); } else { std::string playername; // Handle the "playerid" option if (!optionPlayer.isNull()) { if (optionPlayer.isString()) { playername = optionPlayer.asString(); if (playername != "default") { // check if the there's actually a player with the given name if (CPlayerCoreFactory::GetInstance().GetPlayerType(playername).empty()) return InvalidParams; // check if the player can handle at least the first item in the list std::vector<std::string> possiblePlayers; CPlayerCoreFactory::GetInstance().GetPlayers(*list.Get(0).get(), possiblePlayers); bool match = false; for (auto entry : possiblePlayers) { if (StringUtils::CompareNoCase(entry, playername)) { match = true; break; } } if (!match) return InvalidParams; } } else return InvalidParams; } // Handle "shuffled" option if (optionShuffled.isBoolean()) list.SetProperty("shuffled", optionShuffled); // Handle "repeat" option if (!optionRepeat.isNull()) list.SetProperty("repeat", ParseRepeatState(optionRepeat)); // Handle "resume" option if (list.Size() == 1) { if (optionResume.isBoolean() && optionResume.asBoolean()) list[0]->m_lStartOffset = STARTOFFSET_RESUME; else if (optionResume.isDouble()) list[0]->SetProperty("StartPercent", optionResume); else if (optionResume.isObject()) list[0]->m_lStartOffset = (int)(ParseTimeInSeconds(optionResume) * 75.0); } auto l = new CFileItemList(); //don't delete l->Copy(list); CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_PLAY, -1, -1, static_cast<void*>(l), playername); } return ACK; } else return InvalidParams; } return InvalidParams; }
void CAnnouncementManager::Announce(EAnnouncementFlag flag, const char *sender, const char *message, CFileItemPtr item, CVariant &data) { if (!item.get()) { Announce(flag, sender, message, data); return; } // Extract db id of item CVariant object = data.isNull() || data.isObject() ? data : CVariant::VariantTypeObject; CStdString type; int id = 0; if (item->HasVideoInfoTag()) { id = item->GetVideoInfoTag()->m_iDbId; // TODO: Can be removed once this is properly handled when starting playback of a file if (id <= 0 && !item->GetPath().empty() && (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean())) { CVideoDatabase videodatabase; if (videodatabase.Open()) { if (videodatabase.LoadVideoInfo(item->GetPath(), *item->GetVideoInfoTag())) id = item->GetVideoInfoTag()->m_iDbId; videodatabase.Close(); } } CVideoDatabase::VideoContentTypeToString((VIDEODB_CONTENT_TYPE)item->GetVideoContentType(), type); if (id <= 0) { // TODO: Can be removed once this is properly handled when starting playback of a file item->SetProperty(LOOKUP_PROPERTY, false); object["title"] = item->GetVideoInfoTag()->m_strTitle; switch (item->GetVideoContentType()) { case VIDEODB_CONTENT_MOVIES: if (item->GetVideoInfoTag()->m_iYear > 0) object["year"] = item->GetVideoInfoTag()->m_iYear; break; case VIDEODB_CONTENT_EPISODES: if (item->GetVideoInfoTag()->m_iEpisode >= 0) object["episode"] = item->GetVideoInfoTag()->m_iEpisode; if (item->GetVideoInfoTag()->m_iSeason >= 0) object["season"] = item->GetVideoInfoTag()->m_iSeason; if (!item->GetVideoInfoTag()->m_strShowTitle.empty()) object["showtitle"] = item->GetVideoInfoTag()->m_strShowTitle; break; case VIDEODB_CONTENT_MUSICVIDEOS: if (!item->GetVideoInfoTag()->m_strAlbum.empty()) object["album"] = item->GetVideoInfoTag()->m_strAlbum; if (!item->GetVideoInfoTag()->m_strArtist.empty()) object["artist"] = item->GetVideoInfoTag()->m_strArtist; break; } } } else if (item->HasMusicInfoTag()) { id = item->GetMusicInfoTag()->GetDatabaseId(); type = "song"; // TODO: Can be removed once this is properly handled when starting playback of a file if (id <= 0 && !item->GetPath().empty() && (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean())) { CMusicDatabase musicdatabase; if (musicdatabase.Open()) { CSong song; if (musicdatabase.GetSongByFileName(item->GetPath(), song)) { item->GetMusicInfoTag()->SetSong(song); item->SetMusicThumb(); id = item->GetMusicInfoTag()->GetDatabaseId(); } musicdatabase.Close(); } } if (id <= 0) { // TODO: Can be removed once this is properly handled when starting playback of a file item->SetProperty(LOOKUP_PROPERTY, false); object["title"] = item->GetMusicInfoTag()->GetTitle(); if (item->GetMusicInfoTag()->GetTrackNumber() > 0) object["track"] = item->GetMusicInfoTag()->GetTrackNumber(); if (!item->GetMusicInfoTag()->GetAlbum().empty()) object["album"] = item->GetMusicInfoTag()->GetAlbum(); if (!item->GetMusicInfoTag()->GetArtist().empty()) object["artist"] = item->GetMusicInfoTag()->GetArtist(); } } else type = "unknown"; object["item"]["type"] = type; if (id > 0) object["item"]["id"] = id; Announce(flag, sender, message, object); }
JSONRPC_STATUS CPlayerOperations::Open(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { CVariant optionShuffled = parameterObject["options"]["shuffled"]; CVariant optionRepeat = parameterObject["options"]["repeat"]; CVariant optionResume = parameterObject["options"]["resume"]; if (parameterObject["item"].isObject() && parameterObject["item"].isMember("playlistid")) { int playlistid = (int)parameterObject["item"]["playlistid"].asInteger(); if (playlistid < PLAYLIST_PICTURE) { // Apply the "shuffled" option if available if (optionShuffled.isBoolean()) g_playlistPlayer.SetShuffle(playlistid, optionShuffled.asBoolean(), false); // Apply the "repeat" option if available if (!optionRepeat.isNull()) g_playlistPlayer.SetRepeat(playlistid, (REPEAT_STATE)ParseRepeatState(optionRepeat), false); } switch (playlistid) { case PLAYLIST_MUSIC: case PLAYLIST_VIDEO: CApplicationMessenger::Get().MediaPlay(playlistid, (int)parameterObject["item"]["position"].asInteger()); OnPlaylistChanged(); break; case PLAYLIST_PICTURE: return StartSlideshow("", false, optionShuffled.isBoolean() && optionShuffled.asBoolean()); break; } return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("path")) { bool random = (optionShuffled.isBoolean() && optionShuffled.asBoolean()) || (!optionShuffled.isBoolean() && parameterObject["item"]["random"].asBoolean()); return StartSlideshow(parameterObject["item"]["path"].asString(), parameterObject["item"]["recursive"].asBoolean(), random); } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("partymode")) { if (g_partyModeManager.IsEnabled()) g_partyModeManager.Disable(); CApplicationMessenger::Get().ExecBuiltIn("playercontrol(partymode(" + parameterObject["item"]["partymode"].asString() + "))"); return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("channelid")) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRChannelGroupsContainer *channelGroupContainer = g_PVRChannelGroups; if (channelGroupContainer == NULL) return FailedToExecute; CPVRChannelPtr channel = channelGroupContainer->GetChannelById((int)parameterObject["item"]["channelid"].asInteger()); if (channel == NULL) return InvalidParams; CApplicationMessenger::Get().MediaPlay(CFileItem(*channel.get())); return ACK; } else { CFileItemList list; if (FillFileItemList(parameterObject["item"], list) && list.Size() > 0) { bool slideshow = true; for (int index = 0; index < list.Size(); index++) { if (!list[index]->IsPicture()) { slideshow = false; break; } } if (slideshow) { CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!slideshow) return FailedToExecute; SendSlideshowAction(ACTION_STOP); slideshow->Reset(); for (int index = 0; index < list.Size(); index++) slideshow->Add(list[index].get()); return StartSlideshow("", false, optionShuffled.isBoolean() && optionShuffled.asBoolean()); } else { // Handle "shuffled" option if (optionShuffled.isBoolean()) list.SetProperty("shuffled", optionShuffled); // Handle "repeat" option if (!optionRepeat.isNull()) list.SetProperty("repeat", ParseRepeatState(optionRepeat)); // Handle "resume" option if (list.Size() == 1) { if (optionResume.isBoolean() && optionResume.asBoolean()) list[0]->m_lStartOffset = STARTOFFSET_RESUME; else if (optionResume.isDouble()) list[0]->SetProperty("StartPercent", optionResume); else if (optionResume.isObject()) list[0]->m_lStartOffset = (int)(ParseTimeInSeconds(optionResume) * 75.0); } CApplicationMessenger::Get().MediaPlay(list); } return ACK; } else return InvalidParams; } return InvalidParams; }
JSONRPC_STATUS CPlayerOperations::Open(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { CVariant options = parameterObject["options"]; CVariant optionShuffled = options["shuffled"]; CVariant optionRepeat = options["repeat"]; CVariant optionResume = options["resume"]; CVariant optionPlayer = options["playercoreid"]; if (parameterObject["item"].isObject() && parameterObject["item"].isMember("playlistid")) { int playlistid = (int)parameterObject["item"]["playlistid"].asInteger(); if (playlistid < PLAYLIST_PICTURE) { // Apply the "shuffled" option if available if (optionShuffled.isBoolean()) g_playlistPlayer.SetShuffle(playlistid, optionShuffled.asBoolean(), false); // Apply the "repeat" option if available if (!optionRepeat.isNull()) g_playlistPlayer.SetRepeat(playlistid, (REPEAT_STATE)ParseRepeatState(optionRepeat), false); } int playlistStartPosition = (int)parameterObject["item"]["position"].asInteger(); switch (playlistid) { case PLAYLIST_MUSIC: case PLAYLIST_VIDEO: CApplicationMessenger::Get().MediaPlay(playlistid, playlistStartPosition); OnPlaylistChanged(); break; case PLAYLIST_PICTURE: { std::string firstPicturePath; if (playlistStartPosition > 0) { CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (slideshow != NULL) { CFileItemList list; slideshow->GetSlideShowContents(list); if (playlistStartPosition < list.Size()) firstPicturePath = list.Get(playlistStartPosition)->GetPath(); } } return StartSlideshow("", false, optionShuffled.isBoolean() && optionShuffled.asBoolean(), firstPicturePath); break; } } return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("path")) { bool random = (optionShuffled.isBoolean() && optionShuffled.asBoolean()) || (!optionShuffled.isBoolean() && parameterObject["item"]["random"].asBoolean()); return StartSlideshow(parameterObject["item"]["path"].asString(), parameterObject["item"]["recursive"].asBoolean(), random); } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("partymode")) { if (g_partyModeManager.IsEnabled()) g_partyModeManager.Disable(); CApplicationMessenger::Get().ExecBuiltIn("playercontrol(partymode(" + parameterObject["item"]["partymode"].asString() + "))"); return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("channelid")) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRChannelGroupsContainer *channelGroupContainer = g_PVRChannelGroups; if (channelGroupContainer == NULL) return FailedToExecute; CPVRChannelPtr channel = channelGroupContainer->GetChannelById((int)parameterObject["item"]["channelid"].asInteger()); if (channel == NULL) return InvalidParams; if ((g_PVRManager.IsPlayingRadio() && channel->IsRadio()) || (g_PVRManager.IsPlayingTV() && !channel->IsRadio())) g_application.m_pPlayer->SwitchChannel(channel); else CApplicationMessenger::Get().MediaPlay(CFileItem(channel)); return ACK; } else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("recordingid")) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRRecordings *recordingsContainer = g_PVRRecordings; if (recordingsContainer == NULL) return FailedToExecute; CFileItemPtr fileItem = recordingsContainer->GetById((int)parameterObject["item"]["recordingid"].asInteger()); if (fileItem == NULL) return InvalidParams; CApplicationMessenger::Get().MediaPlay(*fileItem); return ACK; } else { CFileItemList list; if (FillFileItemList(parameterObject["item"], list) && list.Size() > 0) { bool slideshow = true; for (int index = 0; index < list.Size(); index++) { if (!list[index]->IsPicture()) { slideshow = false; break; } } if (slideshow) { CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!slideshow) return FailedToExecute; SendSlideshowAction(ACTION_STOP); slideshow->Reset(); for (int index = 0; index < list.Size(); index++) slideshow->Add(list[index].get()); return StartSlideshow("", false, optionShuffled.isBoolean() && optionShuffled.asBoolean()); } else { // Handle the "playerid" option if (!optionPlayer.isNull()) { PLAYERCOREID playerId = EPC_NONE; if (optionPlayer.isInteger()) { playerId = (PLAYERCOREID)optionPlayer.asInteger(); // check if the there's actually a player with the given player ID if (CPlayerCoreFactory::Get().GetPlayerConfig(playerId) == NULL) return InvalidParams; // check if the player can handle at least the first item in the list VECPLAYERCORES possiblePlayers; CPlayerCoreFactory::Get().GetPlayers(*list.Get(0).get(), possiblePlayers); VECPLAYERCORES::const_iterator matchingPlayer = std::find(possiblePlayers.begin(), possiblePlayers.end(), playerId); if (matchingPlayer == possiblePlayers.end()) return InvalidParams; } else if (!optionPlayer.isString() || optionPlayer.asString().compare("default") != 0) return InvalidParams; // set the next player to be used g_application.m_eForcedNextPlayer = playerId; } // Handle "shuffled" option if (optionShuffled.isBoolean()) list.SetProperty("shuffled", optionShuffled); // Handle "repeat" option if (!optionRepeat.isNull()) list.SetProperty("repeat", ParseRepeatState(optionRepeat)); // Handle "resume" option if (list.Size() == 1) { if (optionResume.isBoolean() && optionResume.asBoolean()) list[0]->m_lStartOffset = STARTOFFSET_RESUME; else if (optionResume.isDouble()) list[0]->SetProperty("StartPercent", optionResume); else if (optionResume.isObject()) list[0]->m_lStartOffset = (int)(ParseTimeInSeconds(optionResume) * 75.0); } CApplicationMessenger::Get().MediaPlay(list); } return ACK; } else return InvalidParams; } return InvalidParams; }