gui/movieplayer.cpp: add subtitle display support for file playback

This commit is contained in:
[CST] Focus
2013-04-30 12:28:15 +04:00
parent 708e018994
commit 7a0c1e9674
2 changed files with 248 additions and 6 deletions

View File

@@ -27,6 +27,7 @@
#include <config.h>
#endif
#define __STDC_CONSTANT_MACROS
#include <global.h>
#include <neutrino.h>
@@ -38,6 +39,7 @@
#include <gui/plugins.h>
#include <driver/screenshot.h>
#include <driver/volume.h>
#include <driver/abstime.h>
#include <system/helpers.h>
#include <unistd.h>
@@ -304,6 +306,8 @@ bool CMoviePlayerGui::SelectFile()
language[i].clear();
}
numpida = 0; currentapid = 0;
currentspid = -1;
numsubs = 0;
is_file_player = false;
p_movie_info = NULL;
@@ -356,7 +360,7 @@ bool CMoviePlayerGui::SelectFile()
}
} else
menu_ret = moviebrowser->getMenuRet();
}
}
else { // filebrowser
if (filebrowser->exec(Path_local.c_str()) == true) {
Path_local = filebrowser->getCurrentDir();
@@ -430,6 +434,8 @@ void CMoviePlayerGui::PlayFile(void)
handleMovieBrowser(CRCInput::RC_nokey, position);
cutNeutrino();
clearSubtitle();
playback->Open(is_file_player ? PLAYMODE_FILE : PLAYMODE_TS);
printf("IS FILE PLAYER: %s\n", is_file_player ? "true": "false" );
@@ -528,6 +534,7 @@ void CMoviePlayerGui::PlayFile(void)
handleMovieBrowser(0, position);
FileTime.update(position, duration);
}
showSubtitle(0);
if (msg == (neutrino_msg_t) g_settings.mpkey_plugin) {
//g_PluginList->start_plugin_by_name (g_settings.movieplayer_plugin.c_str (), pidt);
@@ -569,10 +576,15 @@ void CMoviePlayerGui::PlayFile(void)
} else if (msg == (neutrino_msg_t) g_settings.mpkey_audio) {
selectAudioPid(is_file_player);
update_lcd = true;
clearSubtitle();
} else if ( msg == (neutrino_msg_t) g_settings.mpkey_subtitle) {
selectSubtitle(is_file_player);
clearSubtitle();
update_lcd = true;
} else if (msg == (neutrino_msg_t) g_settings.mpkey_time) {
FileTime.switchMode(position, duration);
} else if ((msg == (neutrino_msg_t) g_settings.mpkey_rewind) ||
(msg == (neutrino_msg_t) g_settings.mpkey_forward)) {
} else if (!is_file_player && ((msg == (neutrino_msg_t) g_settings.mpkey_rewind) ||
(msg == (neutrino_msg_t) g_settings.mpkey_forward))) {
int newspeed;
if (msg == (neutrino_msg_t) g_settings.mpkey_rewind) {
@@ -600,32 +612,44 @@ void CMoviePlayerGui::PlayFile(void)
time_forced = true;
}
} else if (msg == CRCInput::RC_1) { // Jump Backwards 1 minute
clearSubtitle();
playback->SetPosition(-60 * 1000);
} else if (msg == CRCInput::RC_3) { // Jump Forward 1 minute
clearSubtitle();
playback->SetPosition(60 * 1000);
} else if (msg == CRCInput::RC_4) { // Jump Backwards 5 minutes
clearSubtitle();
playback->SetPosition(-5 * 60 * 1000);
} else if (msg == CRCInput::RC_6) { // Jump Forward 5 minutes
clearSubtitle();
playback->SetPosition(5 * 60 * 1000);
} else if (msg == CRCInput::RC_7) { // Jump Backwards 10 minutes
clearSubtitle();
playback->SetPosition(-10 * 60 * 1000);
} else if (msg == CRCInput::RC_9) { // Jump Forward 10 minutes
clearSubtitle();
playback->SetPosition(10 * 60 * 1000);
} else if (msg == CRCInput::RC_2) { // goto start
clearSubtitle();
playback->SetPosition(0, true);
} else if (msg == CRCInput::RC_5) { // goto middle
clearSubtitle();
playback->SetPosition(duration/2, true);
} else if (msg == CRCInput::RC_8) { // goto end
clearSubtitle();
playback->SetPosition(duration - 60 * 1000, true);
} else if (msg == CRCInput::RC_page_up) {
clearSubtitle();
playback->SetPosition(10 * 1000);
} else if (msg == CRCInput::RC_page_down) {
clearSubtitle();
playback->SetPosition(-10 * 1000);
} else if (msg == CRCInput::RC_0) { // cancel bookmark jump
handleMovieBrowser(CRCInput::RC_0, position);
} else if (msg == CRCInput::RC_help || msg == CRCInput::RC_info) {
callInfoViewer(/*duration, position*/);
update_lcd = true;
clearSubtitle();
//showHelpTS();
} else if(timeshift && (msg == CRCInput::RC_text || msg == CRCInput::RC_epg || msg == NeutrinoMessages::SHOW_EPG)) {
bool restore = FileTime.IsVisible();
@@ -672,6 +696,8 @@ void CMoviePlayerGui::PlayFile(void)
sc->EnableVideo(true);
sc->Start();
} else if ( msg == NeutrinoMessages::EVT_SUBT_MESSAGE) {
showSubtitle(data);
} else if ( msg == NeutrinoMessages::ANNOUNCE_RECORD ||
msg == NeutrinoMessages::RECORD_START) {
CNeutrinoApp::getInstance()->handleMsg(msg, data);
@@ -697,6 +723,7 @@ void CMoviePlayerGui::PlayFile(void)
}
else if ( msg <= CRCInput::RC_MaxRC ) {
update_lcd = true;
clearSubtitle();
}
}
@@ -708,6 +735,7 @@ void CMoviePlayerGui::PlayFile(void)
}
FileTime.hide();
clearSubtitle();
playback->SetSpeed(1);
playback->Close();
@@ -802,7 +830,6 @@ void CMoviePlayerGui::getCurrentAudioName( bool file_player, std::string &audion
}
bool dumm = true;
for (unsigned int count = 0; count < numpida; count++) {
if(currentapid == apids[count]){
if(!file_player){
getAudioName(apids[count], audioname);
@@ -1052,7 +1079,7 @@ void CMoviePlayerGui::handleMovieBrowser(neutrino_msg_t msg, int /*position*/)
jump_not_until = (position / 1000) + 10; // avoid bookmark jumping for the next 10 seconds, , TODO: might be moved to another key
}
return;
}
}
else if (msg == (neutrino_msg_t) g_settings.mpkey_bookmark) {
if (newComHintBox.isPainted() == true) {
// yes, let's get the end pos of the jump forward
@@ -1112,7 +1139,7 @@ void CMoviePlayerGui::handleMovieBrowser(neutrino_msg_t msg, int /*position*/)
DisplayErrorMessage(g_Locale->getText(LOCALE_MOVIEPLAYER_TOOMANYBOOKMARKS)); // UTF-8
}
cSelectedMenuBookStart[0].selected = false; // clear for next bookmark menu
} else
} else
#endif
if (cSelectedMenuBookStart[1].selected == true) {
/* Moviebrowser plain bookmark */
@@ -1181,3 +1208,205 @@ void CMoviePlayerGui::showHelpTS()
helpbox.addLine(g_Locale->getText(LOCALE_MOVIEPLAYER_TSHELP12));
helpbox.show(LOCALE_MESSAGEBOX_INFO);
}
void CMoviePlayerGui::selectSubtitle(bool file_player)
{
if (!file_player)
return;
CMenuWidget APIDSelector(LOCALE_SUBTITLES_HEAD, NEUTRINO_ICON_AUDIO);
APIDSelector.addIntroItems();
int select = -1;
CMenuSelectorTarget * selector = new CMenuSelectorTarget(&select);
if(!numsubs) {
playback->FindAllSubs(spids, sub_supported, &numsubs, slanguage);
}
char cnt[5];
unsigned int count;
for (count = 0; count < numsubs; count++) {
bool enabled = sub_supported[count];
bool defpid = currentspid >= 0 ? (currentspid == spids[count]) : (count == 0);
std::string title = slanguage[count];
if (title.empty()) {
char pidnumber[20];
sprintf(pidnumber, "Stream %d %X", count + 1, spids[count]);
title = pidnumber;
}
sprintf(cnt, "%d", count);
CMenuForwarderNonLocalized * item = new CMenuForwarderNonLocalized(title.c_str(), enabled, NULL, selector, cnt, CRCInput::convertDigitToKey(count + 1));
APIDSelector.addItem(item, defpid);
}
sprintf(cnt, "%d", count);
APIDSelector.addItem(new CMenuForwarder(LOCALE_SUBTITLES_STOP, true, NULL, selector, cnt, CRCInput::RC_stop), currentspid < 0);
APIDSelector.exec(NULL, "");
delete selector;
printf("CMoviePlayerGui::selectSubtitle: selected %d (%x) current %x\n", select, (select >= 0) ? spids[select] : -1, currentspid);
if((select >= 0) && (select < numsubs) && (currentspid != spids[select])) {
currentspid = spids[select];
playback->SelectSubtitles(currentspid);
printf("[movieplayer] spid changed to %d\n", currentspid);
} else if ( select > 0) {
currentspid = -1;
playback->SelectSubtitles(currentspid);
printf("[movieplayer] spid changed to %d\n", currentspid);
}
}
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
void CMoviePlayerGui::clearSubtitle()
{
if ((max_x-min_x > 0) && (max_y-min_y > 0))
frameBuffer->paintBackgroundBoxRel(min_x, min_y, max_x-min_x, max_y-min_y);
min_x = CFrameBuffer::getInstance()->getScreenWidth();
min_y = CFrameBuffer::getInstance()->getScreenHeight();
max_x = CFrameBuffer::getInstance()->getScreenX();
max_y = CFrameBuffer::getInstance()->getScreenY();
end_time = 0;
}
fb_pixel_t * simple_resize32(uint8_t * orgin, uint32_t * colors, int nb_colors, int ox, int oy, int dx, int dy);
void CMoviePlayerGui::showSubtitle(neutrino_msg_data_t data)
{
if (!data) {
if (end_time && time_monotonic_ms() > end_time) {
printf("************************* hide subs *************************\n");
clearSubtitle();
}
return;
}
AVSubtitle * sub = (AVSubtitle *) data;
printf("************************* EVT_SUBT_MESSAGE: num_rects %d fmt %d *************************\n", sub->num_rects, sub->format);
if (!sub->num_rects)
return;
if (sub->format == 0) {
int xres = 0, yres = 0, framerate;
videoDecoder->getPictureInfo(xres, yres, framerate);
double xc = (double) CFrameBuffer::getInstance()->getScreenWidth(/*true*/)/(double) xres;
double yc = (double) CFrameBuffer::getInstance()->getScreenHeight(/*true*/)/(double) yres;
clearSubtitle();
for (unsigned i = 0; i < sub->num_rects; i++) {
uint32_t * colors = (uint32_t *) sub->rects[i]->pict.data[1];
int nw = (double) sub->rects[i]->w * xc;
int nh = (double) sub->rects[i]->h * yc;
int xoff = (double) sub->rects[i]->x * xc;
int yoff = (double) sub->rects[i]->y * yc;
printf("Draw: #%d at %d,%d size %dx%d colors %d (x=%d y=%d w=%d h=%d) \n", i+1,
sub->rects[i]->x, sub->rects[i]->y, sub->rects[i]->w, sub->rects[i]->h,
sub->rects[i]->nb_colors, xoff, yoff, nw, nh);
fb_pixel_t * newdata = simple_resize32 (sub->rects[i]->pict.data[0], colors,
sub->rects[i]->nb_colors, sub->rects[i]->w, sub->rects[i]->h, nw, nh);
frameBuffer->blit2FB(newdata, nw, nh, xoff, yoff);
free(newdata);
min_x = std::min(min_x, xoff);
max_x = std::max(max_x, xoff + nw);
min_y = std::min(min_y, yoff);
max_y = std::max(max_y, yoff + nh);
}
end_time = sub->end_display_time + time_monotonic_ms();
avsubtitle_free(sub);
delete sub;
return;
}
std::vector<std::string> subtext;
for (unsigned i = 0; i < sub->num_rects; i++) {
char * txt = NULL;
if (sub->rects[i]->type == SUBTITLE_TEXT)
txt = sub->rects[i]->text;
else if (sub->rects[i]->type == SUBTITLE_ASS)
txt = sub->rects[i]->ass;
printf("subt[%d] type %d [%s]\n", i, sub->rects[i]->type, txt ? txt : "");
if (txt) {
int len = strlen(txt);
if (len > 10 && memcmp(txt, "Dialogue: ", 10) == 0) {
char* p = txt;
int skip_commas = 4;
/* skip ass times */
for (int j = 0; j < skip_commas && *p != '\0'; p++)
if (*p == ',')
j++;
/* skip ass tags */
if (*p == '{') {
char * d = strchr(p, '}');
if (d)
p += d - p + 1;
}
char * d = strchr(p, '{');
if (d && strchr(d, '}'))
*d = 0;
len = strlen(p);
/* remove newline */
for (int j = len-1; j > 0; j--) {
if (p[j] == '\n' || p[j] == '\r')
p[j] = 0;
else
break;
}
if (*p == '\0')
continue;
txt = p;
}
//printf("title: [%s]\n", txt);
std::string str(txt);
int start = 0, end = 0;
/* split string with \N as newline */
std::string delim("\\N");
while ((end = str.find(delim, start)) != string::npos) {
subtext.push_back(str.substr(start, end - start));
start = end + 2;
}
subtext.push_back(str.substr(start));
}
}
for (unsigned i = 0; i < subtext.size(); i++)
printf("subtext %d: [%s]\n", i, subtext[i].c_str());
printf("********************************************************************\n");
if (!subtext.empty()) {
int sh = frameBuffer->getScreenHeight();
int sw = frameBuffer->getScreenWidth();
int h = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getHeight();
int height = h*subtext.size();
clearSubtitle();
int x[subtext.size()];
int y[subtext.size()];
for (unsigned i = 0; i < subtext.size(); i++) {
int w = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth (subtext[i].c_str(), true);
x[i] = (sw - w) / 2;
y[i] = sh - height + h*(i + 1);
min_x = std::min(min_x, x[i]);
max_x = std::max(max_x, x[i]+w);
min_y = std::min(min_y, y[i]-h);
max_y = std::max(max_y, y[i]);
}
frameBuffer->paintBoxRel(min_x, min_y, max_x - min_x, max_y-min_y, COL_MENUCONTENT_PLUS_0);
for (unsigned i = 0; i < subtext.size(); i++)
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(x[i], y[i], sw, subtext[i].c_str(), COL_MENUCONTENT, 0, true);
end_time = sub->end_display_time + time_monotonic_ms();
}
avsubtitle_free(sub);
delete sub;
}