Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add LiveTV support to Player interface in JSON Player #626

Closed
wants to merge 13 commits into from

2 participants

@RobertMe

Add proper LiveTV support to the Player.X methods of the JSON-RPC API.

Some changes include:
GoNext/GoPrevious act as channel up/down
GoTo(position) switches to channel number position
GetItem integration, exposes Epg data, so getting genre, plot, ... work, includes new starttime, endtime and channel properties
Added a new "islive" property on the Player which is true for live tv and false otherwise
Send OnStop and OnStart to notify client about channel switch (sounds odd, but it's the same as a playlist does when it switches to another item)

Most of these are implemented in a backwards compatible manner. So clients which don't know PVR would still get some/most of the new "features". So for one there is no need to add some special "channel up" handling as it's the "old" Player.GoNext etc.

What's currently missing is the OnStop & OnStart notification when one program is finished and the other starts. So this needs to be added before it can be merged (will add this in the upcomming day(s)).

@RobertMe

About the announcement, which we've yesterday also talked about on IRC. I agree that not all code which is needed for the JSON API should be in the Epg/Pvr code. But, I do think the announcements are a required part of the code. As the announcements are not only for JSON, but are also being used for the Python add-on API. So my guess would be they still should be integrated where needed, the same as NotifyObserver is being called where the event needs to be triggered. That's also how it's currently implemented (I know, not always a good guideline). Application.PlayFile sends the OnPlay announcement (I guess, didn't look it up right now) and it isn't implemented as an observer for a notification which then sends out the announcement.

Please let me know what you think about it.

@opdenkamp
Owner

Now that PVR support has been merged into mainline XBMC, every pull request must be sent as a pull request to mainline XBMC too: https://github.com/xbmc/xbmc/pulls

That's why I am closing this one. Sorry for the trouble.

@opdenkamp opdenkamp closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 26, 2012
  1. @RobertMe
  2. @RobertMe
  3. @RobertMe
  4. @RobertMe
  5. @RobertMe
  6. @RobertMe
  7. @RobertMe
  8. @RobertMe
  9. @RobertMe
  10. @RobertMe

    json-rpc: handle pvr live tv items in announcements

    RobertMe authored
    Set item type and id
    Update player.playerid to show as music and video
  11. @RobertMe

    json-rpc: add Player.SetSubtitle support for live tv

    RobertMe authored
    Returns fails to execute in case of a radio channel instead of tv channel.
Commits on Aug 27, 2012
  1. @RobertMe

    json-rpc: add Player.SetAudioStream support for live tv

    RobertMe authored
    Returns fails to execute in case of a radio channel instead of tv channel.
  2. @RobertMe
This page is out of date. Refresh to see the latest.
View
18 xbmc/epg/EpgInfoTag.cpp
@@ -31,6 +31,8 @@
#include "settings/GUISettings.h"
#include "utils/log.h"
#include "addons/include/xbmc_pvr_types.h"
+#include "utils/Variant.h"
+#include "interfaces/json-rpc/JSONUtils.h"
using namespace std;
using namespace EPG;
@@ -201,6 +203,22 @@ CEpgInfoTag &CEpgInfoTag::operator =(const CEpgInfoTag &other)
return *this;
}
+void CEpgInfoTag::Serialize(CVariant& value)
+{
+ value["title"] = m_strTitle;
+ value["genre"] = m_genre;
+ value["plot"] = m_strPlot;
+ value["plotoutline"] = m_strPlotOutline;
+ value["duration"] = GetDuration();
+ JSONRPC::CJSONUtils::DateTimeToDateTimeObject(m_startTime, value["starttime"]);
+ JSONRPC::CJSONUtils::DateTimeToDateTimeObject(m_endTime, value["endtime"]);
+ CVariant channel = CVariant(CVariant::VariantTypeObject);
+ channel["id"] = m_pvrChannel->ChannelID();
+ channel["name"] = m_pvrChannel->ChannelName();
+ channel["type"] = m_pvrChannel->IsRadio() ? "radio" : "tv";
+ value["channel"] = channel;
+}
+
bool CEpgInfoTag::Changed(void) const
{
CSingleLock lock(m_critSection);
View
4 xbmc/epg/EpgInfoTag.h
@@ -37,7 +37,7 @@ namespace EPG
class CEpgInfoTag;
typedef boost::shared_ptr<EPG::CEpgInfoTag> CEpgInfoTagPtr;
- class CEpgInfoTag
+ class CEpgInfoTag : public ISerializable
{
friend class CEpg;
friend class CEpgDatabase;
@@ -68,6 +68,8 @@ namespace EPG
bool operator !=(const CEpgInfoTag& right) const;
CEpgInfoTag &operator =(const CEpgInfoTag &other);
+ virtual void Serialize(CVariant& value);
+
/*!
* @brief Check whether this tag has changed and unsaved values.
* @return True if it has unsaved values, false otherwise.
View
10 xbmc/interfaces/AnnouncementManager.cpp
@@ -29,6 +29,8 @@
#include "music/tags/MusicInfoTag.h"
#include "music/MusicDatabase.h"
#include "video/VideoDatabase.h"
+#include "pvr/channels/PVRChannel.h"
+#include "PlayListPlayer.h"
#define LOOKUP_PROPERTY "database-lookup"
@@ -184,6 +186,14 @@ void CAnnouncementManager::Announce(AnnouncementFlag flag, const char *sender, c
object["artist"] = item->GetMusicInfoTag()->GetArtist();
}
}
+ else if(item->HasPVRChannelInfoTag())
+ {
+ PVR::CPVRChannel *channel = item->GetPVRChannelInfoTag();
+ id = channel->ChannelID();
+ type = channel->IsRadio() ? "radio" : "tv";
+ if(data.isMember("player") && data["player"].isMember("playerid"))
+ object["player"]["playerid"] = channel->IsRadio() ? PLAYLIST_MUSIC : PLAYLIST_VIDEO;
+ }
else
type = "unknown";
View
17 xbmc/interfaces/json-rpc/FileItemHandler.cpp
@@ -37,6 +37,8 @@
#include "TextureCache.h"
#include "ThumbLoader.h"
#include "Util.h"
+#include "epg/EpgInfoTag.h"
+#include "pvr/channels/PVRChannel.h"
using namespace MUSIC_INFO;
using namespace JSONRPC;
@@ -242,6 +244,8 @@ void CFileItemHandler::HandleFileItem(const char *ID, bool allowFile, const char
object[ID] = (int)item->GetMusicInfoTag()->GetDatabaseId();
else if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > 0)
object[ID] = item->GetVideoInfoTag()->m_iDbId;
+ else if (item->HasPVRChannelInfoTag() && item->GetPVRChannelInfoTag()->ChannelID() > 0)
+ object[ID] = item->GetPVRChannelInfoTag()->ChannelID();
if (stricmp(ID, "id") == 0)
{
@@ -278,6 +282,13 @@ void CFileItemHandler::HandleFileItem(const char *ID, bool allowFile, const char
}
else if (item->HasPictureInfoTag())
object["type"] = "picture";
+ else if (item->HasPVRChannelInfoTag())
+ {
+ if (item->GetPVRChannelInfoTag()->IsRadio())
+ object["type"] = "radio";
+ else
+ object["type"] = "tv";
+ }
if (!object.isMember("type"))
object["type"] = "unknown";
@@ -292,6 +303,12 @@ void CFileItemHandler::HandleFileItem(const char *ID, bool allowFile, const char
FillDetails(item->GetMusicInfoTag(), item, validFields, object);
if (item->HasPictureInfoTag())
FillDetails(item->GetPictureInfoTag(), item, validFields, object);
+ if (item->HasPVRChannelInfoTag())
+ {
+ EPG::CEpgInfoTag epgTag;
+ if(item->GetPVRChannelInfoTag()->GetEPGNow(epgTag))
+ FillDetails(&epgTag, item, validFields, object);
+ }
object["label"] = item->GetLabel().c_str();
}
View
11 xbmc/interfaces/json-rpc/JSONUtils.h
@@ -27,6 +27,7 @@
#include "interfaces/IAnnouncer.h"
#include "utils/JSONVariantWriter.h"
#include "utils/JSONVariantParser.h"
+#include "XBDateTime.h"
namespace JSONRPC
{
@@ -69,6 +70,16 @@ namespace JSONRPC
result["hours"] = time;
}
+ static void DateTimeToDateTimeObject(CDateTime &time, CVariant &result)
+ {
+ result["second"] = time.GetSecond();
+ result["minute"] = time.GetMinute();
+ result["hour"] = time.GetHour();
+ result["day"] = time.GetDay();
+ result["month"] = time.GetMonth();
+ result["year"] = time.GetYear();
+ }
+
protected:
/*!
\brief Checks if the given object contains a parameter
View
99 xbmc/interfaces/json-rpc/PlayerOperations.cpp
@@ -35,9 +35,11 @@
#include "video/VideoDatabase.h"
#include "AudioLibrary.h"
#include "GUIInfoManager.h"
+#include "pvr/PVRManager.h"
using namespace JSONRPC;
using namespace PLAYLIST;
+using namespace PVR;
JSONRPC_STATUS CPlayerOperations::GetActivePlayers(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
{
@@ -99,6 +101,7 @@ JSONRPC_STATUS CPlayerOperations::GetItem(const CStdString &method, ITransportLa
{
case Video:
case Audio:
+ case LiveTV:
{
if (g_application.CurrentFileItem().GetLabel().empty())
{
@@ -111,7 +114,7 @@ JSONRPC_STATUS CPlayerOperations::GetItem(const CStdString &method, ITransportLa
tmpItem.SetPath(g_application.CurrentFileItem().GetPath());
}
}
- else
+ else if (player == Audio)
{
if (!CAudioLibrary::FillFileItem(g_application.CurrentFile(), tmpItem))
{
@@ -218,6 +221,7 @@ JSONRPC_STATUS CPlayerOperations::PlayPause(const CStdString &method, ITransport
result["speed"] = 0;
return OK;
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -230,6 +234,7 @@ JSONRPC_STATUS CPlayerOperations::Stop(const CStdString &method, ITransportLayer
{
case Video:
case Audio:
+ case LiveTV:
CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP));
return ACK;
@@ -278,6 +283,7 @@ JSONRPC_STATUS CPlayerOperations::SetSpeed(const CStdString &method, ITransportL
return OK;
case Picture:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -318,6 +324,7 @@ JSONRPC_STATUS CPlayerOperations::Seek(const CStdString &method, ITransportLayer
return OK;
case Picture:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -334,6 +341,7 @@ JSONRPC_STATUS CPlayerOperations::MoveLeft(const CStdString &method, ITransportL
case Video:
case Audio:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -350,6 +358,7 @@ JSONRPC_STATUS CPlayerOperations::MoveRight(const CStdString &method, ITransport
case Video:
case Audio:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -366,6 +375,7 @@ JSONRPC_STATUS CPlayerOperations::MoveDown(const CStdString &method, ITransportL
case Video:
case Audio:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -382,6 +392,7 @@ JSONRPC_STATUS CPlayerOperations::MoveUp(const CStdString &method, ITransportLay
case Video:
case Audio:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -398,6 +409,7 @@ JSONRPC_STATUS CPlayerOperations::ZoomOut(const CStdString &method, ITransportLa
case Video:
case Audio:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -414,6 +426,7 @@ JSONRPC_STATUS CPlayerOperations::ZoomIn(const CStdString &method, ITransportLay
case Video:
case Audio:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -430,6 +443,7 @@ JSONRPC_STATUS CPlayerOperations::Zoom(const CStdString &method, ITransportLayer
case Video:
case Audio:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -446,6 +460,7 @@ JSONRPC_STATUS CPlayerOperations::Rotate(const CStdString &method, ITransportLay
case Video:
case Audio:
+ case LiveTV:
case None:
default:
return FailedToExecute;
@@ -565,6 +580,11 @@ JSONRPC_STATUS CPlayerOperations::GoPrevious(const CStdString &method, ITranspor
SendSlideshowAction(ACTION_PREV_PICTURE);
return ACK;
+ case LiveTV:
+ unsigned int newChannelNumber;
+ g_PVRManager.ChannelDown(&newChannelNumber);
+ return ACK;
+
case None:
default:
return FailedToExecute;
@@ -584,6 +604,11 @@ JSONRPC_STATUS CPlayerOperations::GoNext(const CStdString &method, ITransportLay
SendSlideshowAction(ACTION_NEXT_PICTURE);
return ACK;
+ case LiveTV:
+ unsigned int newChannelNumber;
+ g_PVRManager.ChannelUp(&newChannelNumber);
+ return ACK;
+
case None:
default:
return FailedToExecute;
@@ -600,6 +625,11 @@ JSONRPC_STATUS CPlayerOperations::GoTo(const CStdString &method, ITransportLayer
CApplicationMessenger::Get().PlayListPlayerPlay(position);
break;
+ case LiveTV:
+ if (!g_PVRManager.ChannelSwitch(position))
+ return FailedToExecute;
+ break;
+
case Picture:
case None:
default:
@@ -629,6 +659,7 @@ JSONRPC_STATUS CPlayerOperations::Shuffle(const CStdString &method, ITransportLa
return FailedToExecute;
break;
+ case LiveTV:
default:
return FailedToExecute;
}
@@ -646,6 +677,7 @@ JSONRPC_STATUS CPlayerOperations::UnShuffle(const CStdString &method, ITransport
break;
case Picture:
+ case LiveTV:
default:
return FailedToExecute;
}
@@ -663,6 +695,7 @@ JSONRPC_STATUS CPlayerOperations::Repeat(const CStdString &method, ITransportLay
break;
case Picture:
+ case LiveTV:
default:
return FailedToExecute;
}
@@ -672,10 +705,12 @@ JSONRPC_STATUS CPlayerOperations::Repeat(const CStdString &method, ITransportLay
JSONRPC_STATUS CPlayerOperations::SetAudioStream(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
{
- switch (GetPlayer(parameterObject["playerid"]))
+ PlayerType player = GetPlayer(parameterObject["plpayerid"]);
+ switch (player)
{
case Video:
- if (g_application.m_pPlayer)
+ case LiveTV:
+ if (g_application.m_pPlayer && (player != LiveTV || g_PVRManager.IsPlayingTV()))
{
int index = -1;
if (parameterObject["stream"].isString())
@@ -719,10 +754,12 @@ JSONRPC_STATUS CPlayerOperations::SetAudioStream(const CStdString &method, ITran
JSONRPC_STATUS CPlayerOperations::SetSubtitle(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
{
- switch (GetPlayer(parameterObject["playerid"]))
+ PlayerType player = GetPlayer(parameterObject["playerid"]);
+ switch (player)
{
case Video:
- if (g_application.m_pPlayer)
+ case LiveTV:
+ if (g_application.m_pPlayer && (player != LiveTV || g_PVRManager.IsPlayingTV()))
{
int index = -1;
if (parameterObject["subtitle"].isString())
@@ -782,9 +819,9 @@ int CPlayerOperations::GetActivePlayers()
{
int activePlayers = 0;
- if (g_application.IsPlayingVideo())
+ if (g_application.IsPlayingVideo() || g_PVRManager.IsPlayingTV())
activePlayers |= Video;
- if (g_application.IsPlayingAudio())
+ if (g_application.IsPlayingAudio() || g_PVRManager.IsPlayingRadio())
activePlayers |= Audio;
if (g_windowManager.IsWindowActive(WINDOW_SLIDESHOW))
activePlayers |= Picture;
@@ -820,9 +857,15 @@ PlayerType CPlayerOperations::GetPlayer(const CVariant &player)
// Implicit order
if (choosenPlayer & Video)
- return Video;
+ if (g_PVRManager.IsPlayingTV())
+ return LiveTV;
+ else
+ return Video;
else if (choosenPlayer & Audio)
- return Audio;
+ if (g_PVRManager.IsPlayingRadio())
+ return LiveTV;
+ else
+ return Audio;
else if (choosenPlayer & Picture)
return Picture;
else
@@ -898,6 +941,10 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
result = "picture";
break;
+ case LiveTV:
+ result = g_PVRManager.IsPlayingRadio() ? "audio" : "video";
+ break;
+
default:
return FailedToExecute;
}
@@ -912,6 +959,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
break;
case Picture:
+ case LiveTV:
result = false;
break;
@@ -926,6 +974,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
{
case Video:
case Audio:
+ case LiveTV:
result = g_application.IsPaused() ? 0 : g_application.GetPlaySpeed();
break;
@@ -947,6 +996,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
{
case Video:
case Audio:
+ case LiveTV:
MillisecondsToTimeObject((int)(g_application.GetTime() * 1000.0), result);
break;
@@ -965,6 +1015,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
{
case Video:
case Audio:
+ case LiveTV:
result = g_application.GetPercentage();
break;
@@ -986,6 +1037,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
{
case Video:
case Audio:
+ case LiveTV:
MillisecondsToTimeObject((int)(g_application.GetTotalTime() * 1000.0), result);
break;
@@ -1008,6 +1060,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
{
case Video:
case Audio:
+ case LiveTV:
if (g_playlistPlayer.GetCurrentPlaylist() == playlist)
result = g_playlistPlayer.GetCurrentSong();
else
@@ -1048,6 +1101,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
break;
case Picture:
+ case LiveTV:
default:
result = "off";
break;
@@ -1071,6 +1125,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
result = -1;
break;
+ case LiveTV:
default:
result = -1;
break;
@@ -1089,6 +1144,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
break;
case Picture:
+ case LiveTV:
default:
result = false;
break;
@@ -1104,6 +1160,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
break;
case Picture:
+ case LiveTV:
default:
result = false;
break;
@@ -1119,6 +1176,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
case Video:
case Audio:
+ case LiveTV:
default:
result = false;
break;
@@ -1134,6 +1192,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
case Video:
case Audio:
+ case LiveTV:
default:
result = false;
break;
@@ -1164,6 +1223,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
result = true;
break;
+ case LiveTV:
default:
result = false;
break;
@@ -1179,6 +1239,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
break;
case Picture:
+ case LiveTV:
default:
result = false;
break;
@@ -1190,6 +1251,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
{
case Video:
case Audio:
+ case LiveTV:
if (g_application.m_pPlayer)
{
result = CVariant(CVariant::VariantTypeObject);
@@ -1224,6 +1286,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
switch (player)
{
case Video:
+ case LiveTV:
if (g_application.m_pPlayer)
{
for (int index = 0; index < g_application.m_pPlayer->GetAudioStreamCount(); index++)
@@ -1253,6 +1316,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
switch (player)
{
case Video:
+ case LiveTV:
if (g_application.m_pPlayer)
result = g_application.m_pPlayer->GetSubtitleVisible();
break;
@@ -1269,6 +1333,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
switch (player)
{
case Video:
+ case LiveTV:
if (g_application.m_pPlayer)
{
result = CVariant(CVariant::VariantTypeObject);
@@ -1301,6 +1366,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
switch (player)
{
case Video:
+ case LiveTV:
if (g_application.m_pPlayer)
{
for (int index = 0; index < g_application.m_pPlayer->GetSubtitleCount(); index++)
@@ -1325,6 +1391,21 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStd
break;
}
}
+ else if (property.Equals("islive"))
+ {
+ switch (player)
+ {
+ case LiveTV:
+ result = true;
+ break;
+ case Video:
+ case Audio:
+ case Picture:
+ default:
+ result = false;
+ break;
+ }
+ }
else
return InvalidParams;
View
3  xbmc/interfaces/json-rpc/PlayerOperations.h
@@ -31,7 +31,8 @@ namespace JSONRPC
None = 0,
Video = 0x1,
Audio = 0x2,
- Picture = 0x4
+ Picture = 0x4,
+ LiveTV = 0x08
};
static const int PlayerImplicit = (Video | Audio | Picture);
View
29 xbmc/interfaces/json-rpc/ServiceDescription.h
@@ -61,6 +61,17 @@ namespace JSONRPC
"},"
"\"additionalProperties\": false"
"}",
+ "\"Global.DateTime\": {"
+ "\"extends\": \"Global.Time\","
+ "\"properties\": {"
+ "\"year\": { \"type\": \"integer\", \"required\": true },"
+ "\"month\": { \"type\": \"integer\", \"required\": true, \"minimum\": 1, \"maximum\": 12 },"
+ "\"day\": { \"type\": \"integer\", \"required\": true, \"minimum\": 1, \"maximum\": 31 }",
+ "\"hours\": { \"type\": \"integer\", \"required\": true, \"minimum\": 0, \"maximum\": 23 },"
+ "\"minutes\": { \"type\": \"integer\", \"required\": true, \"minimum\": 0, \"maximum\": 59 },"
+ "\"seconds\": { \"type\": \"integer\", \"required\": true, \"minimum\": 0, \"maximum\": 59 },"
+ "}"
+ "},"
"\"Global.IncrementDecrement\": {"
"\"type\": \"string\","
"\"enum\": [ \"increment\", \"decrement\" ]"
@@ -201,7 +212,7 @@ namespace JSONRPC
"\"totaltime\", \"playlistid\", \"position\", \"repeat\", \"shuffled\","
"\"canseek\", \"canchangespeed\", \"canmove\", \"canzoom\", \"canrotate\","
"\"canshuffle\", \"canrepeat\", \"currentaudiostream\", \"audiostreams\","
- "\"subtitleenabled\", \"currentsubtitle\", \"subtitles\" ]"
+ "\"subtitleenabled\", \"currentsubtitle\", \"subtitles\", \"islive\" ]"
"}",
"\"Player.Property.Value\": {"
"\"type\": \"object\","
@@ -227,7 +238,8 @@ namespace JSONRPC
"\"audiostreams\": { \"type\": \"array\", \"items\": { \"$ref\": \"Player.Audio.Stream\" } },"
"\"subtitleenabled\": { \"type\": \"boolean\" },"
"\"currentsubtitle\": { \"$ref\": \"Player.Subtitle\" },"
- "\"subtitles\": { \"type\": \"array\", \"items\": { \"$ref\": \"Player.Subtitle\" } }"
+ "\"subtitles\": { \"type\": \"array\", \"items\": { \"$ref\": \"Player.Subtitle\" } },"
+ "\"islive\": { \"type\": \"boolean\" }"
"}"
"}",
"\"Player.Notifications.Item.Type\": {"
@@ -722,7 +734,7 @@ namespace JSONRPC
"\"runtime\", \"set\", \"showlink\", \"streamdetails\", \"top250\", \"votes\","
"\"firstaired\", \"season\", \"episode\", \"showtitle\", \"thumbnail\", \"file\","
"\"resume\", \"artistid\", \"albumid\", \"tvshowid\", \"setid\", \"watchedepisodes\","
- "\"disc\", \"tag\" ]"
+ "\"disc\", \"tag\", \"starttime\", \"endtime\", \"channel\" ]"
"}"
"}",
"\"List.Item.All\": {"
@@ -763,7 +775,16 @@ namespace JSONRPC
"\"tvshowid\": { \"$ref\": \"Library.Id\" },"
"\"watchedepisodes\": { \"type\": \"integer\" },"
"\"disc\": { \"type\": \"integer\" },"
- "\"tag\": { \"$ref\": \"Array.String\" }"
+ "\"tag\": { \"$ref\": \"Array.String\" },"
+ "\"starttime\": { \"type\": \"Global.DateTime\" },"
+ "\"endtime\": { \"type\": \"Global.DateTime\" },"
+ "\"channel\": { \"type\": \"object\","
+ "\"properties\": {"
+ "\"id\": { \"type\": \"int\" },"
+ "\"name\": { \"type\": \"string\" },"
+ "\"type\": { \"type\": \"string\", \"enum\": [ \"radio\", \"tv\" ] }"
+ "}"
+ "}"
"}"
"}",
"\"List.Fields.Files\": {"
View
29 xbmc/interfaces/json-rpc/types.json
@@ -33,6 +33,17 @@
},
"additionalProperties": false
},
+ "Global.DateTime": {
+ "extends": "Global.Time",
+ "properties": {
+ "year": { "type": "integer", "required": true },
+ "month": { "type": "integer", "required": true, "minimum": 1, "maximum": 12 },
+ "day": { "type": "integer", "required": true, "minimum": 1, "maximum": 31 },
+ "hour": { "type": "integer", "required": true, "minimum": 0, "maximum": 23 },
+ "minute": { "type": "integer", "required": true, "minimum": 0, "maximum": 59 },
+ "second": { "type": "integer", "required": true, "minimum": 0, "maximum": 59 },
+ }
+ },
"Global.IncrementDecrement": {
"type": "string",
"enum": [ "increment", "decrement" ]
@@ -173,7 +184,7 @@
"totaltime", "playlistid", "position", "repeat", "shuffled",
"canseek", "canchangespeed", "canmove", "canzoom", "canrotate",
"canshuffle", "canrepeat", "currentaudiostream", "audiostreams",
- "subtitleenabled", "currentsubtitle", "subtitles" ]
+ "subtitleenabled", "currentsubtitle", "subtitles", "islive" ]
},
"Player.Property.Value": {
"type": "object",
@@ -199,7 +210,8 @@
"audiostreams": { "type": "array", "items": { "$ref": "Player.Audio.Stream" } },
"subtitleenabled": { "type": "boolean" },
"currentsubtitle": { "$ref": "Player.Subtitle" },
- "subtitles": { "type": "array", "items": { "$ref": "Player.Subtitle" } }
+ "subtitles": { "type": "array", "items": { "$ref": "Player.Subtitle" } },
+ "islive": { "type": "boolean" }
}
},
"Player.Notifications.Item.Type": {
@@ -694,7 +706,7 @@
"runtime", "set", "showlink", "streamdetails", "top250", "votes",
"firstaired", "season", "episode", "showtitle", "thumbnail", "file",
"resume", "artistid", "albumid", "tvshowid", "setid", "watchedepisodes",
- "disc", "tag" ]
+ "disc", "tag", "starttime", "endtime", "channel" ]
}
},
"List.Item.All": {
@@ -735,7 +747,16 @@
"tvshowid": { "$ref": "Library.Id" },
"watchedepisodes": { "type": "integer" },
"disc": { "type": "integer" },
- "tag": { "$ref": "Array.String" }
+ "tag": { "$ref": "Array.String" },
+ "starttime": { "type": "Global.DateTime" },
+ "endtime": { "type": "Global.DateTime" },
+ "channel": { "type": "object",
+ "properties": {
+ "id": { "type": "int" },
+ "name": { "type": "string" },
+ "type": { "type": "string", "enum": [ "radio", "tv" ] }
+ }
+ }
}
},
"List.Fields.Files": {
View
16 xbmc/pvr/PVRManager.cpp
@@ -40,6 +40,7 @@
#include "utils/StringUtils.h"
#include "threads/Atomics.h"
#include "windows/GUIWindowPVRCommon.h"
+#include "interfaces/AnnouncementManager.h"
#include "PVRManager.h"
#include "PVRDatabase.h"
@@ -56,6 +57,7 @@ using namespace std;
using namespace MUSIC_INFO;
using namespace PVR;
using namespace EPG;
+using namespace ANNOUNCEMENT;
CPVRManager::CPVRManager(void) :
CThread("PVR manager"),
@@ -991,6 +993,12 @@ bool CPVRManager::PerformChannelSwitch(const CPVRChannel &channel, bool bPreview
if (!bPreview)
SaveCurrentChannelSettings();
+ if (!bPreview && m_currentFile)
+ {
+ CVariant data(CVariant::VariantTypeObject);
+ CAnnouncementManager::Announce(Player, "xbmc", "OnStop", CFileItemPtr(new CFileItem(m_currentFile)), data);
+ }
+
SAFE_DELETE(m_currentFile);
lock.Leave();
@@ -1025,6 +1033,14 @@ bool CPVRManager::PerformChannelSwitch(const CPVRChannel &channel, bool bPreview
g_localizeStrings.Get(19035));
}
+ if (!bPreview && bSwitched)
+ {
+ CVariant param;
+ param["player"]["speed"] = 1;
+ param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
+ CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", CFileItemPtr(new CFileItem(channel)), param);
+ }
+
return bSwitched;
}
Something went wrong with that request. Please try again.