Index: themes/defaultosd/osd.xml
===================================================================
--- themes/defaultosd/osd.xml (revision 16344)
+++ themes/defaultosd/osd.xml (working copy)
@@ -345,4 +345,16 @@
+
+
+ now_playing.png
+ 85,124
+
+
+
+
Index: themes/blueosd/osd.xml
===================================================================
--- themes/blueosd/osd.xml (revision 16344)
+++ themes/blueosd/osd.xml (working copy)
@@ -349,6 +349,17 @@
-
+
+
+ now_playing.png
+ 85,124
+
+
+
+
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp (revision 16344)
+++ libs/libmythtv/NuppelVideoPlayer.cpp (working copy)
@@ -198,6 +198,10 @@
interactiveTV(NULL),
itvEnabled(false),
+ // Now Playing visible in OSD
+ has_now_playing(false),
+ now_playing_changed(false),
+
// OSD stuff
osd(NULL), timedisplay(NULL),
dialogname(""), dialogtype(0),
@@ -272,8 +276,11 @@
commnotifyamount = gContext->GetNumSetting("CommNotifyAmount",0);
decode_extra_audio=gContext->GetNumSetting("DecodeExtraAudio", 0);
itvEnabled = gContext->GetNumSetting("EnableMHEG", 0);
+ nowPlayEnabled = gContext->GetNumSetting("EnableNowPlaying", 0);
db_prefer708 = gContext->GetNumSetting("Prefer708Captions", 1);
+ osd_now_play_timeout = gContext->GetNumSetting("OSDNowPlayingTimeout", 10);
+
lastIgnoredManualSkip = QDateTime::currentDateTime().addSecs(-10);
bzero(&txtbuffers, sizeof(txtbuffers));
@@ -2710,6 +2717,9 @@
ExpireSubtitles();
}
+ if (has_now_playing && nowPlayEnabled)
+ DisplayNowPlaying();
+
// handle scan type changes
AutoDeint(frame);
@@ -3150,6 +3160,11 @@
ringBuffer->Pause();
ringBuffer->WaitForPause();
+ SetHasNowPlaying(false);
+
+ if (osd)
+ osd->ResetNowPlaying();
+
ClearSubtitles();
livetvchain->SetProgram(pginfo);
@@ -6821,6 +6836,62 @@
osd->ClearTextSubtitles();
}
+/** \fn NuppelVideoPlayer::SetHasNowPlaying(void)
+ * \brief Enables displaying of Now Playing content
+ */
+void NuppelVideoPlayer::SetHasNowPlaying(bool has)
+{
+ if (nowPlayEnabled)
+ {
+ has_now_playing = has;
+
+ if (has_now_playing != has)
+ {
+ QString which = has ? "Enabling" : "Disabling";
+ VERBOSE(VB_PLAYBACK, LOC + QString("%1 Now Playing processing")
+ .arg(which));
+ }
+ }
+}
+
+/** \fn NuppelVideoPlayer::HasNowPlaying(void)
+ * \brief Returns bool stream has Now Playing
+ */
+bool NuppelVideoPlayer::HasNowPlaying(void)
+{
+ return has_now_playing;
+}
+
+/** \fn NuppelVideoPlayer::DisplayNowPlaying(void)
+ * \brief Displays Now Playing text
+ */
+void NuppelVideoPlayer::DisplayNowPlaying()
+{
+ QMutexLocker locker(&nowPlayingLock);
+
+ if (!nowPlayEnabled ||
+ !has_now_playing ||
+ !now_playing_changed)
+ return;
+
+ QString text = "Now Playing:\n\n";
+
+ // Skip if the first section is empty
+ QString t = now_playing[0].simplifyWhiteSpace();
+ if (t.isEmpty())
+ return;
+
+ int i = 0;
+
+ for (QStringList::Iterator it = now_playing.begin();
+ it != now_playing.end(); ++it )
+ text.append(*it + "\n");
+
+ osd->SetNowPlaying(text, osd_now_play_timeout);
+
+ now_playing_changed = false;
+}
+
/** \fn NuppelVideoPlayer::ExpireSubtitles(void)
* \brief Discard non-displayed subtitles.
*/
@@ -6910,6 +6981,18 @@
subtitleLock.unlock();
}
+/** \fn void NuppelVideoPlayer::SetNowPlaying(const QStringList playing&)
+ * \brief Set the Now Playing text in the OSD.
+ */
+void NuppelVideoPlayer::SetNowPlaying(const QStringList &playing)
+{
+ nowPlayingLock.lock();
+ now_playing = QDeepCopy(playing);
+ nowPlayingLock.unlock();
+
+ now_playing_changed = true;
+}
+
/** \fn NuppelVideoPlayer::SetDecoder(DecoderBase*)
* \brief Sets the stream decoder, deleting any existing recorder.
*/
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp (revision 16344)
+++ libs/libmythtv/avformatdecoder.cpp (working copy)
@@ -437,6 +437,8 @@
allow_dts_passthru = gContext->GetNumSetting("DTSPassThru", false);
max_channels = (uint) gContext->GetNumSetting("MaxChannels", 2);
+ nowPlayEnabled = gContext->GetNumSetting("EnableNowPlaying", 0);
+
audioIn.sample_size = -32; // force SetupAudioStream to run once
itv = GetNVP()->GetInteractiveTV();
@@ -1430,6 +1432,8 @@
tracks[kTrackTypeTeletextCaptions].clear();
selectedVideoIndex = -1;
+ GetNVP()->SetHasNowPlaying(false);
+
map lang_sub_cnt;
map lang_aud_cnt;
@@ -1655,8 +1659,21 @@
}
case CODEC_TYPE_DATA:
{
- ScanTeletextCaptions(i);
- bitrate += enc->bit_rate;
+ switch(enc->codec_id)
+ {
+ case CODEC_ID_DSMCC_B:
+ bitrate += enc->bit_rate;
+ break;
+ case CODEC_ID_DVB_VBI:
+ ScanTeletextCaptions(i);
+ bitrate += enc->bit_rate;
+ break;
+ case CODEC_ID_DVB_PRIVSEC:
+ if (enc->bit_rate == 0)
+ enc->bit_rate = 175; // 1 TS packet - 13 byte header
+ break;
+ }
+
VERBOSE(VB_PLAYBACK, LOC + QString("data codec (%1)")
.arg(codec_type_string(enc->codec_type)));
break;
@@ -2423,6 +2440,64 @@
}
}
+void AvFormatDecoder::ProcessPrivSecDataPacket(const AVPacket *pkt)
+{
+ if (!GetNVP())
+ return;
+
+ if (nowPlayEnabled)
+ {
+ QStringList sections;
+ bool changed = false;
+ uint non_ascii = 0;
+ uint end = 0;
+
+ uint8_t *buf = pkt->data;
+ uint len = pkt->size;
+
+ if (!len || len > 188)
+ return;
+
+ // Sanity checks
+ for (uint x = 0; x < len; x++)
+ if (buf[x] == 0x00)
+ len = end = x;
+ else if (buf[x] > 0x7f)
+ non_ascii++;
+
+ if ((non_ascii / len) > .4)
+ return;
+
+ if (!end)
+ return;
+
+ QString text = (const char*)buf;
+
+ if (text.contains(0x0a) > 10)
+ return;
+
+ GetNVP()->SetHasNowPlaying(true);
+
+ for (int i = 0; i < text.contains(0x0a); i++) {
+ QString section = text.section(0x0a, i, i);
+ if (section == "") section = " ";
+
+ if ((i > now_playing.size()) ||
+ now_playing[i].compare(section))
+ {
+ sections << section;
+ changed = true;
+ }
+ }
+
+ if (changed)
+ {
+ now_playing = sections;
+ GetNVP()->SetNowPlaying(sections);
+ }
+ }
+}
+
/** \fn AvFormatDecoder::ProcessVBIDataPacket(const AVStream*, const AVPacket*)
* \brief Process ivtv proprietary embedded vertical blanking
* interval captions.
@@ -3314,6 +3389,16 @@
continue;
}
+ if (len > 0 &&
+ curstream->codec->codec_type == CODEC_TYPE_DATA &&
+ curstream->codec->codec_id == CODEC_ID_DVB_PRIVSEC)
+ {
+ ProcessPrivSecDataPacket(pkt);
+
+ av_free_packet(pkt);
+ continue;
+ }
+
// we don't care about other data streams
if (curstream->codec->codec_type == CODEC_TYPE_DATA)
{
Index: libs/libmythtv/tv_play.h
===================================================================
--- libs/libmythtv/tv_play.h (revision 16344)
+++ libs/libmythtv/tv_play.h (working copy)
@@ -444,6 +444,7 @@
bool arrowAccel;
int osd_general_timeout;
int osd_prog_info_timeout;
+ int osd_now_play_timeout;
enum commSkipMode autoCommercialSkip;
bool tryUnflaggedSkip;
@@ -683,6 +684,9 @@
// Network Control stuff
QValueList networkControlCommands;
QMutex ncLock;
+
+ // Now Playing
+ bool nowPlayEnabled;
};
#endif
Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.h (revision 16344)
+++ libs/libmythtv/NuppelVideoPlayer.h (working copy)
@@ -299,6 +299,12 @@
long long timecode, char type);
void AddAVSubtitle(const AVSubtitle& subtitle);
+ // Now Playing data
+ void SetHasNowPlaying(bool has);
+ void SetNowPlaying(const QStringList &playing);
+ void DisplayNowPlaying();
+ bool HasNowPlaying(void);
+
// Closed caption and teletext stuff
uint GetCaptionMode(void) const { return textDisplayMode; }
void ResetCaptions(uint mode_override = 0);
@@ -640,6 +646,7 @@
// Support for captions, teletext, etc. decoded by libav
QMutex subtitleLock;
+ QMutex nowPlayingLock;
/// This allows us to enable captions/subtitles later if the streams
/// are not immediately available when the video starts playing.
bool textDesired;
@@ -671,6 +678,12 @@
bool itvEnabled;
QMutex itvLock;
+ // Support for Now Playing
+ bool nowPlayEnabled;
+ QStringList now_playing;
+ bool has_now_playing;
+ bool now_playing_changed;
+
// OSD stuff
OSD *osd;
OSDSet *timedisplay;
@@ -727,6 +740,8 @@
long long lastCommSkipStart;
time_t lastSkipTime;
+ int osd_now_play_timeout;
+
long long deleteframe;
bool hasdeletetable;
bool hasblanktable;
Index: libs/libmythtv/osd.h
===================================================================
--- libs/libmythtv/osd.h (revision 16344)
+++ libs/libmythtv/osd.h (working copy)
@@ -80,6 +80,8 @@
const QString &callsign, const QString &iconpath,
int length);
void SetChannumText(const QString &text, int length);
+ void SetNowPlaying(const QString &playing, int length);
+ void ResetNowPlaying(void);
// CC-608 and DVB text captions (not DVB/DVD subtitles).
void AddCCText(const QString &text, int x, int y, int color,
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp (revision 16344)
+++ libs/libmythtv/tv_play.cpp (working copy)
@@ -508,6 +508,7 @@
jumptime(0), smartChannelChange(false),
MuteIndividualChannels(false), arrowAccel(false),
osd_general_timeout(2), osd_prog_info_timeout(3),
+ osd_now_play_timeout(10),
autoCommercialSkip(CommSkipOff), tryUnflaggedSkip(false),
smartForward(false), stickykeys(0),
ff_rew_repos(1.0f), ff_rew_reverse(false),
@@ -635,6 +636,7 @@
persistentbrowsemode = gContext->GetNumSetting("PersistentBrowseMode", 0);
osd_general_timeout = gContext->GetNumSetting("OSDGeneralTimeout", 2);
osd_prog_info_timeout= gContext->GetNumSetting("OSDProgramInfoTimeout", 3);
+ osd_now_play_timeout = gContext->GetNumSetting("OSDNowPlayingTimeout", 10);
autoCommercialSkip = (enum commSkipMode)gContext->GetNumSetting(
"AutoCommercialSkip", CommSkipOff);
tryUnflaggedSkip = gContext->GetNumSetting("TryUnflaggedSkip", 0);
@@ -642,6 +644,7 @@
stickykeys = gContext->GetNumSetting("StickyKeys");
ff_rew_repos = gContext->GetNumSetting("FFRewReposTime", 100)/100.0;
ff_rew_reverse = gContext->GetNumSetting("FFRewReverse", 1);
+ nowPlayEnabled = gContext->GetNumSetting("EnableNowPlaying", 0);
int def[8] = { 3, 5, 10, 20, 30, 60, 120, 180 };
for (uint i = 0; i < sizeof(def)/sizeof(def[0]); i++)
ff_rew_speeds.push_back(
@@ -5263,6 +5266,9 @@
osd->ClearAllText(whichInfo);
osd->HideAll();
osd->SetText(whichInfo, infoMap, osd_prog_info_timeout);
+
+ if (nowPlayEnabled && nvp->HasNowPlaying())
+ osd->SetNowPlaying("", osd_now_play_timeout);
}
void TV::UpdateOSDSeekMessage(const QString &mesg, int disptime)
Index: libs/libmythtv/avformatdecoder.h
===================================================================
--- libs/libmythtv/avformatdecoder.h (revision 16344)
+++ libs/libmythtv/avformatdecoder.h (working copy)
@@ -187,6 +187,7 @@
void MpegPreProcessPkt(AVStream *stream, AVPacket *pkt);
void H264PreProcessPkt(AVStream *stream, AVPacket *pkt);
+ void ProcessPrivSecDataPacket(const AVPacket *pkt);
void ProcessVBIDataPacket(const AVStream *stream, const AVPacket *pkt);
void ProcessDVBDataPacket(const AVStream *stream, const AVPacket *pkt);
void ProcessDSMCCPacket(const AVStream *stream, const AVPacket *pkt);
@@ -278,6 +279,10 @@
bool mpeg_seq_end_seen;
/// \brief contains last dvd still frame decoded
AVPacket *lastDVDStillFrame;
+
+ // Now Playing
+ QStringList now_playing;
+ bool nowPlayEnabled;
};
#endif
Index: libs/libmythtv/osd.cpp
===================================================================
--- libs/libmythtv/osd.cpp (revision 16344)
+++ libs/libmythtv/osd.cpp (working copy)
@@ -1939,6 +1939,75 @@
osdlock.unlock();
}
+void OSD::ResetNowPlaying(void)
+{
+ osdlock.lock();
+
+ QString my_name = "now_playing";
+
+ OSDSet *container = GetSet(my_name);
+ if (container)
+ {
+ container->Hide();
+
+ OSDTypeText *text = (OSDTypeText *)container->GetType("playing");
+ if (text)
+ text->SetText("");
+
+ m_setsvisible = false;
+ changed = true;
+ }
+
+ osdlock.unlock();
+}
+
+void OSD::SetNowPlaying(const QString &playing, int length)
+{
+ osdlock.lock();
+
+ QString my_name = "now_playing";
+
+ OSDSet *container = GetSet(my_name);
+ if (!container)
+ {
+ OSDSet *set = GetSet("now_playing");
+ if (!set)
+ {
+ VERBOSE(VB_IMPORTANT, "couldn't find now_playing dialog");
+ osdlock.unlock();
+ return;
+ }
+
+ container = new OSDSet(*set);
+ container->SetName(my_name);
+ container->SetCache(true);
+ container->SetPriority(20);
+ container->SetAllowFade(true);
+ AddSet(container, my_name, false);
+ }
+
+ if (container)
+ {
+ OSDTypeText *text = (OSDTypeText *)container->GetType("playing");
+
+ if (!playing.isNull() && !playing.isEmpty())
+ if (text)
+ text->SetText(playing);
+
+ if (length > 0)
+ container->DisplayFor(length * 1000000);
+ else
+ container->Display();
+
+ m_setsvisible = true;
+ changed = true;
+
+ //VERBOSE(VB_PLAYBACK, QString("NOW PLAYING: '%1'").arg(text->GetText()));
+ }
+
+ osdlock.unlock();
+}
+
void OSD::SetChannumText(const QString &text, int length)
{
osdlock.lock();
Index: libs/libavcodec/myth_utils.c
===================================================================
--- libs/libavcodec/myth_utils.c (revision 16344)
+++ libs/libavcodec/myth_utils.c (working copy)
@@ -203,6 +203,9 @@
case CODEC_ID_DSMCC_B: return "DSMCC_B";
+ /* private data codecs */
+ case CODEC_ID_DVB_PRIVSEC: return "DVB_PRIVSEC";
+
case CODEC_ID_MPEG2TS: return "MPEG2TS";
}
return "Unknown Codec ID";
Index: libs/libavcodec/avcodec.h
===================================================================
--- libs/libavcodec/avcodec.h (revision 16344)
+++ libs/libavcodec/avcodec.h (working copy)
@@ -289,6 +289,9 @@
/* DSMCC codec */
CODEC_ID_DSMCC_B,
+ /* Private Data */
+ CODEC_ID_DVB_PRIVSEC= 0x19000,
+
CODEC_ID_MPEG2TS= 0x20000, /* _FAKE_ codec to indicate a raw MPEG-2 TS
* stream (only used by libavformat) */
};
Index: libs/libavformat/mpegts.c
===================================================================
--- libs/libavformat/mpegts.c (revision 16344)
+++ libs/libavformat/mpegts.c (working copy)
@@ -866,6 +866,7 @@
case STREAM_TYPE_AUDIO_AAC:
case STREAM_TYPE_AUDIO_AC3:
case STREAM_TYPE_AUDIO_DTS:
+ case STREAM_TYPE_PRIVATE_SECTION:
case STREAM_TYPE_PRIVATE_DATA:
case STREAM_TYPE_VBI_DVB:
case STREAM_TYPE_SUBTITLE_DVB:
@@ -1454,6 +1455,10 @@
codec_type = CODEC_TYPE_DATA;
codec_id = CODEC_ID_DSMCC_B;
break;
+ case STREAM_TYPE_PRIVATE_SECTION:
+ codec_type = CODEC_TYPE_DATA;
+ codec_id = CODEC_ID_DVB_PRIVSEC;
+ break;
case STREAM_TYPE_PRIVATE_DATA:
default:
if (code >= 0x1c0 && code <= 0x1df) {
@@ -1553,6 +1558,17 @@
if (pes->total_size)
pes->total_size += 6;
pes->pes_header_size = pes->header[8] + 9;
+ } else if (pes->header[0] == 0x00 && pes->header[1] == 0xd3 &&
+ pes->header[2] == 0xb0) {
+ /* private sections */
+ if (!pes->st) {
+ /* allocate stream */
+ new_pes_av_stream(pes, code);
+ }
+ if (pes->header[7] != 0x00 && pes->header[7] != 0x01)
+ pes->state = MPEGTS_PESHEADER_FILL;
+ else
+ pes->state = MPEGTS_PAYLOAD; /* No PTS/DTS info */
} else {
/* otherwise, it should be a table */
/* skip packet */
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
--- programs/mythfrontend/globalsettings.cpp (revision 16344)
+++ programs/mythfrontend/globalsettings.cpp (working copy)
@@ -1571,6 +1571,16 @@
return gs;
}
+static HostSpinBox *OSDNowPlayingTimeout()
+{
+ HostSpinBox *gs = new HostSpinBox("OSDNowPlayingTimeout", 1, 60, 1);
+ gs->setLabel(QObject::tr("Now Playing OSD time-out"));
+ gs->setValue(10);
+ gs->setHelpText(QObject::tr("If available, length of time the on-screen "
+ "display will display Now Playing information."));
+ return gs;
+}
+
static HostSpinBox *ThemeCacheSize()
{
HostSpinBox *gs = new HostSpinBox("ThemeCacheSize", 1, 1000, 1, true);
@@ -1898,6 +1908,18 @@
return gc;
}
+static HostCheckBox *EnableNowPlaying()
+{
+ HostCheckBox *gc = new HostCheckBox("EnableNowPlaying");
+ gc->setLabel(QObject::tr("Enable Now Playing Information"));
+ gc->setValue(false);
+ gc->setHelpText(QObject::tr(
+ "If enabled and available, Now Playing "
+ "information will be activated. This is used for "
+ "some DVB radio channels."));
+ return gc;
+}
+
static HostCheckBox *PersistentBrowseMode()
{
HostCheckBox *gc = new HostCheckBox("PersistentBrowseMode");
@@ -4694,9 +4716,11 @@
osd->addChild(new ThemeSelector("OSDTheme"));
osd->addChild(OSDGeneralTimeout());
osd->addChild(OSDProgramInfoTimeout());
+ osd->addChild(OSDNowPlayingTimeout());
osd->addChild(OSDFont());
osd->addChild(OSDThemeFontSizeType());
osd->addChild(EnableMHEG());
+ osd->addChild(EnableNowPlaying());
osd->addChild(PersistentBrowseMode());
addChild(osd);