/* * Copyright (C) 2005-2018 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ #include "Player.h" #include "AddonUtils.h" #include "GUIInfoManager.h" #include "GUIUserMessages.h" #include "ListItem.h" #include "PlayList.h" #include "PlayListPlayer.h" #include "ServiceBroker.h" #include "application/Application.h" #include "application/ApplicationComponents.h" #include "application/ApplicationPlayer.h" #include "cores/IPlayer.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "messaging/ApplicationMessenger.h" #include "settings/MediaSettings.h" namespace { std::shared_ptr getAppPlayer() { const auto& components = CServiceBroker::GetAppComponents(); auto res = components.GetComponent(); return res; } std::shared_ptr getAppPlayerMut() { auto& components = CServiceBroker::GetAppComponents(); auto res = components.GetComponent(); return res; } } // namespace namespace XBMCAddon { namespace xbmc { PlayParameter Player::defaultPlayParameter; Player::Player() { iPlayList = PLAYLIST::TYPE_MUSIC; // now that we're done, register hook me into the system if (languageHook) { DelayedCallGuard dc(languageHook); languageHook->RegisterPlayerCallback(this); } } Player::~Player() { deallocating(); // we're shutting down so unregister me. if (languageHook) { DelayedCallGuard dc(languageHook); languageHook->UnregisterPlayerCallback(this); } } void Player::play(const Alternative & item, const XBMCAddon::xbmcgui::ListItem* listitem, bool windowed, int startpos) { XBMC_TRACE; if (&item == &defaultPlayParameter) playCurrent(windowed); else if (item.which() == XBMCAddon::first) playStream(item.former(), listitem, windowed); else // item is a PlayListItem playPlaylist(item.later(),windowed,startpos); } void Player::playStream(const String& item, const xbmcgui::ListItem* plistitem, bool windowed) { XBMC_TRACE; DelayedCallGuard dc(languageHook); if (!item.empty()) { // set fullscreen or windowed CMediaSettings::GetInstance().SetMediaStartWindowed(windowed); const AddonClass::Ref listitem(plistitem); if (listitem.isSet()) { // set m_strPath to the passed url listitem->item->SetPath(item.c_str()); CServiceBroker::GetAppMessenger()->PostMsg( TMSG_MEDIA_PLAY, 0, 0, static_cast(new CFileItem(*listitem->item))); } else { CFileItemList *l = new CFileItemList; //don't delete, l->Add(std::make_shared(item, false)); CServiceBroker::GetAppMessenger()->PostMsg(TMSG_MEDIA_PLAY, -1, -1, static_cast(l)); } } else playCurrent(windowed); } void Player::playCurrent(bool windowed) { XBMC_TRACE; DelayedCallGuard dc(languageHook); // set fullscreen or windowed CMediaSettings::GetInstance().SetMediaStartWindowed(windowed); // play current file in playlist if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() != iPlayList) CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(iPlayList); CServiceBroker::GetAppMessenger()->SendMsg( TMSG_PLAYLISTPLAYER_PLAY, CServiceBroker::GetPlaylistPlayer().GetCurrentSong()); } void Player::playPlaylist(const PlayList* playlist, bool windowed, int startpos) { XBMC_TRACE; DelayedCallGuard dc(languageHook); if (playlist != NULL) { // set fullscreen or windowed CMediaSettings::GetInstance().SetMediaStartWindowed(windowed); // play a python playlist (a playlist from playlistplayer.cpp) iPlayList = playlist->getPlayListId(); CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(iPlayList); if (startpos > -1) CServiceBroker::GetPlaylistPlayer().SetCurrentSong(startpos); CServiceBroker::GetAppMessenger()->SendMsg(TMSG_PLAYLISTPLAYER_PLAY, startpos); } else playCurrent(windowed); } void Player::stop() { XBMC_TRACE; CServiceBroker::GetAppMessenger()->SendMsg(TMSG_MEDIA_STOP); } void Player::pause() { XBMC_TRACE; CServiceBroker::GetAppMessenger()->SendMsg(TMSG_MEDIA_PAUSE); } void Player::playnext() { XBMC_TRACE; DelayedCallGuard dc(languageHook); CServiceBroker::GetAppMessenger()->SendMsg(TMSG_PLAYLISTPLAYER_NEXT); } void Player::playprevious() { XBMC_TRACE; DelayedCallGuard dc(languageHook); CServiceBroker::GetAppMessenger()->SendMsg(TMSG_PLAYLISTPLAYER_PREV); } void Player::playselected(int selected) { XBMC_TRACE; DelayedCallGuard dc(languageHook); if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() != iPlayList) { CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(iPlayList); } CServiceBroker::GetPlaylistPlayer().SetCurrentSong(selected); CServiceBroker::GetAppMessenger()->SendMsg(TMSG_PLAYLISTPLAYER_PLAY, selected); //CServiceBroker::GetPlaylistPlayer().Play(selected); //CLog::Log(LOGINFO, "Current Song After Play: {}", CServiceBroker::GetPlaylistPlayer().GetCurrentSong()); } void Player::OnPlayBackStarted(const CFileItem &file) { // We only have fileItem due to us having to // implement the interface, we can't send it to python // as we're not able to serialize it. XBMC_TRACE; invokeCallback(new CallbackFunction(this, &Player::onPlayBackStarted)); } void Player::OnAVStarted(const CFileItem &file) { // We only have fileItem due to us having to // implement the interface, we can't send it to python // as we're not able to serialize it. XBMC_TRACE; invokeCallback(new CallbackFunction(this, &Player::onAVStarted)); } void Player::OnAVChange() { XBMC_TRACE; invokeCallback(new CallbackFunction(this, &Player::onAVChange)); } void Player::OnPlayBackEnded() { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onPlayBackEnded)); } void Player::OnPlayBackStopped() { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onPlayBackStopped)); } void Player::OnPlayBackError() { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onPlayBackError)); } void Player::OnPlayBackPaused() { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onPlayBackPaused)); } void Player::OnPlayBackResumed() { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onPlayBackResumed)); } void Player::OnQueueNextItem() { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onQueueNextItem)); } void Player::OnPlayBackSpeedChanged(int speed) { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onPlayBackSpeedChanged,speed)); } void Player::OnPlayBackSeek(int64_t time, int64_t seekOffset) { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onPlayBackSeek,static_cast(time),static_cast(seekOffset))); } void Player::OnPlayBackSeekChapter(int chapter) { XBMC_TRACE; invokeCallback(new CallbackFunction(this,&Player::onPlayBackSeekChapter,chapter)); } void Player::onPlayBackStarted() { XBMC_TRACE; } void Player::onAVStarted() { XBMC_TRACE; } void Player::onAVChange() { XBMC_TRACE; } void Player::onPlayBackEnded() { XBMC_TRACE; } void Player::onPlayBackStopped() { XBMC_TRACE; } void Player::onPlayBackError() { XBMC_TRACE; } void Player::onPlayBackPaused() { XBMC_TRACE; } void Player::onPlayBackResumed() { XBMC_TRACE; } void Player::onQueueNextItem() { XBMC_TRACE; } void Player::onPlayBackSpeedChanged(int speed) { XBMC_TRACE; } void Player::onPlayBackSeek(int time, int seekOffset) { XBMC_TRACE; } void Player::onPlayBackSeekChapter(int chapter) { XBMC_TRACE; } bool Player::isPlaying() { XBMC_TRACE; return getAppPlayer()->IsPlaying(); } bool Player::isPlayingAudio() { XBMC_TRACE; return getAppPlayer()->IsPlayingAudio(); } bool Player::isPlayingVideo() { XBMC_TRACE; return getAppPlayer()->IsPlayingVideo(); } bool Player::isPlayingRDS() { XBMC_TRACE; return getAppPlayer()->IsPlayingRDS(); } bool Player::isPlayingGame() { XBMC_TRACE; return getAppPlayer()->IsPlayingGame(); } bool Player::isExternalPlayer() { XBMC_TRACE; return getAppPlayer()->IsExternalPlaying(); } String Player::getPlayingFile() { XBMC_TRACE; if (!getAppPlayer()->IsPlaying()) throw PlayerException("Kodi is not playing any file"); return g_application.CurrentFileItem().GetDynPath(); } XBMCAddon::xbmcgui::ListItem* Player::getPlayingItem() { XBMC_TRACE; if (!getAppPlayer()->IsPlaying()) throw PlayerException("Kodi is not playing any item"); CFileItemPtr itemPtr = std::make_shared(g_application.CurrentFileItem()); return new XBMCAddon::xbmcgui::ListItem(itemPtr); } InfoTagVideo* Player::getVideoInfoTag() { XBMC_TRACE; if (!getAppPlayer()->IsPlayingVideo()) throw PlayerException("Kodi is not playing any videofile"); const CVideoInfoTag* movie = CServiceBroker::GetGUI()->GetInfoManager().GetCurrentMovieTag(); if (movie) return new InfoTagVideo(movie); return new InfoTagVideo(true); } InfoTagMusic* Player::getMusicInfoTag() { XBMC_TRACE; if (getAppPlayer()->IsPlayingVideo() || !getAppPlayer()->IsPlayingAudio()) throw PlayerException("Kodi is not playing any music file"); const MUSIC_INFO::CMusicInfoTag* tag = CServiceBroker::GetGUI()->GetInfoManager().GetCurrentSongTag(); if (tag) return new InfoTagMusic(tag); return new InfoTagMusic(true); } void Player::updateInfoTag(const XBMCAddon::xbmcgui::ListItem* item) { XBMC_TRACE; if (!getAppPlayer()->IsPlaying()) throw PlayerException("Kodi is not playing any file"); CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, item->item); CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); } InfoTagGame* Player::getGameInfoTag() { XBMC_TRACE; if (!getAppPlayer()->IsPlayingGame()) throw PlayerException("Kodi is not playing any game file"); const KODI::GAME::CGameInfoTag* game = CServiceBroker::GetGUI()->GetInfoManager().GetCurrentGameTag(); if (game) return new InfoTagGame(game); return new InfoTagGame(); } InfoTagRadioRDS* Player::getRadioRDSInfoTag() { XBMC_TRACE; if (getAppPlayer()->IsPlayingVideo() || !getAppPlayer()->IsPlayingRDS()) throw PlayerException("Kodi is not playing any music file with RDS"); std::shared_ptr item = g_application.CurrentFileItemPtr(); if (item && item->HasPVRChannelInfoTag()) return new InfoTagRadioRDS(item->GetPVRChannelInfoTag()); return new InfoTagRadioRDS(); } double Player::getTotalTime() { XBMC_TRACE; if (!getAppPlayer()->IsPlaying()) throw PlayerException("Kodi is not playing any media file"); return g_application.GetTotalTime(); } double Player::getTime() { XBMC_TRACE; if (!getAppPlayer()->IsPlaying()) throw PlayerException("Kodi is not playing any media file"); return g_application.GetTime(); } void Player::seekTime(double pTime) { XBMC_TRACE; if (!getAppPlayer()->IsPlaying()) throw PlayerException("Kodi is not playing any media file"); g_application.SeekTime( pTime ); } void Player::setSubtitles(const char* cLine) { XBMC_TRACE; if (getAppPlayer()->HasPlayer()) { getAppPlayerMut()->AddSubtitle(cLine); } } void Player::showSubtitles(bool bVisible) { XBMC_TRACE; if (getAppPlayer()->HasPlayer()) { getAppPlayerMut()->SetSubtitleVisible(bVisible != 0); } } String Player::getSubtitles() { XBMC_TRACE; if (getAppPlayer()->HasPlayer()) { SubtitleStreamInfo info; getAppPlayerMut()->GetSubtitleStreamInfo(CURRENT_STREAM, info); if (info.language.length() > 0) return info.language; else return info.name; } return ""; } std::vector Player::getAvailableSubtitleStreams() { if (getAppPlayer()->HasPlayer()) { int subtitleCount = getAppPlayer()->GetSubtitleCount(); std::vector ret(subtitleCount); for (int iStream=0; iStream < subtitleCount; iStream++) { SubtitleStreamInfo info; getAppPlayer()->GetSubtitleStreamInfo(iStream, info); if (info.language.length() > 0) ret[iStream] = info.language; else ret[iStream] = info.name; } return ret; } return std::vector(); } void Player::setSubtitleStream(int iStream) { if (getAppPlayer()->HasPlayer()) { int streamCount = getAppPlayer()->GetSubtitleCount(); if(iStream < streamCount) { getAppPlayerMut()->SetSubtitle(iStream); getAppPlayerMut()->SetSubtitleVisible(true); } } } std::vector Player::getAvailableAudioStreams() { if (getAppPlayer()->HasPlayer()) { int streamCount = getAppPlayer()->GetAudioStreamCount(); std::vector ret(streamCount); for (int iStream=0; iStream < streamCount; iStream++) { AudioStreamInfo info; getAppPlayerMut()->GetAudioStreamInfo(iStream, info); if (info.language.length() > 0) ret[iStream] = info.language; else ret[iStream] = info.name; } return ret; } return std::vector(); } void Player::setAudioStream(int iStream) { if (getAppPlayer()->HasPlayer()) { int streamCount = getAppPlayer()->GetAudioStreamCount(); if (iStream < streamCount) getAppPlayerMut()->SetAudioStream(iStream); } } std::vector Player::getAvailableVideoStreams() { int streamCount = getAppPlayer()->GetVideoStreamCount(); std::vector ret(streamCount); for (int iStream = 0; iStream < streamCount; ++iStream) { VideoStreamInfo info; getAppPlayer()->GetVideoStreamInfo(iStream, info); if (info.language.length() > 0) ret[iStream] = info.language; else ret[iStream] = info.name; } return ret; } void Player::setVideoStream(int iStream) { int streamCount = getAppPlayer()->GetVideoStreamCount(); if (iStream < streamCount) getAppPlayerMut()->SetVideoStream(iStream); } } }