From: acid-burn Date: Fri, 18 Feb 2011 19:31:01 +0000 (+0100) Subject: Merge remote branch 'origin/acid-burn/bug_670_plugin_restartoption' into experimental X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=commitdiff_plain;h=47eb827c45c6c8637418b64480d518d8553e4ee9;hp=df1a17b12cb9535832a8db9bcbcf213210ddca81 Merge remote branch 'origin/acid-burn/bug_670_plugin_restartoption' into experimental --- diff --git a/RecordTimer.py b/RecordTimer.py index 4ece9c5..1cb7eb3 100755 --- a/RecordTimer.py +++ b/RecordTimer.py @@ -517,7 +517,7 @@ class RecordTimer(timer.Timer): checkit = True for timer in root.findall("timer"): newTimer = createTimer(timer) - if (self.record(newTimer, True, True) is not None) and (checkit == True): + if (self.record(newTimer, True, dosave=False) is not None) and (checkit == True): from Tools.Notifications import AddPopup from Screens.MessageBox import MessageBox AddPopup(_("Timer overlap in timers.xml detected!\nPlease recheck it!"), type = MessageBox.TYPE_ERROR, timeout = 0, id = "TimerLoadFailed") diff --git a/data/encoding.conf b/data/encoding.conf old mode 100644 new mode 100755 index a3cefe6..36f619d --- a/data/encoding.conf +++ b/data/encoding.conf @@ -6,6 +6,7 @@ gre ISO8859-7 pol ISO8859-2 rus ISO8859-5 bul ISO8859-5 +tha ISO8859-11 cze ISO6397 ces ISO6397 slo ISO6397 @@ -31,25 +32,32 @@ slk ISO6397 0xc95 0x3 # Astra 23.5°E 12.109 H - SkyLink 0xbc6 0x3 # Astra 23.5°E 12.525 V - CS Link / SkyLink 0xbc7 0x3 # Astra 23.5°E 12.565 H - SkyLink +200 318 #Hotbird Eutelsat (Eurosport) +300 318 #Hotbird Eutelsat (Eurosport, Animal Pl.HD) 400 318 #Hotbird 13.0 Cyfra+ 1000 318 #Hotbird 13.0 Grupa ITI 1500 318 #Hotbird 13.0 Cyfra+ 1600 318 #Hotbird 13.0 Cyfra+ +2800 318 #Hotbird 13.0 MTV Networks (Comedy Central) 7400 113 #Hotbird 13.0 Cyfrowy Polsat 7800 113 #Hotbird 13.0 Cyfrowy Polsat 7900 113 #Hotbird 13.0 Cyfrowy Polsat 8100 113 #Hotbird 13.0 Universal (Cyfra+) +8100 318 #Hotbird 13.0 Eutelsat (Universal) 11000 318 #Hotbird 13.0 Cyfra+ 11400 318 #Hotbird 13.0 Cyfra+ +11600 318 #Hotbird 13.0 BBC HD, ITI +11700 318 #Hotbird 13.0 Eurosport2 11900 318 #Hotbird 13.0 Cyfra+ 12200 318 #Hotbird 13.0 Disney Channel Polska and other 12800 318 #Hotbird 13.0 Viacom ... MTV / VH1 Polska 13000 318 #Hotbird 13.0 BBC Polska and other +13100 318 #Hotbird 13.0 Crime and Investigation 13200 113 #Hotbird 13.0 Cyfrowy Polsat #Fallback encoding table for single transponders #ISO6397 also enables two byte char encoding #TSID ONID ISO8859-X -12800 318 ISO6397 #Viacom ... MTV / VH1 Polska +#12800 318 ISO6397 #Viacom ... MTV / VH1 Polska 21100 126 ISO8859-9 # Digital Platform 7°E 10.928 H 30.000 2/3 8PSK 41200 126 ISO8859-9 # Digital Platform 7°E 11.451 V 25.066 2/3 50100 126 ISO8859-9 # Digital Platform 7°E 11.471 H 30.000 3/4 diff --git a/data/setup.xml b/data/setup.xml index f5dea73..c5eb07f 100755 --- a/data/setup.xml +++ b/data/setup.xml @@ -47,27 +47,10 @@ config.seek.speeds_forward config.seek.speeds_backward config.seek.speeds_slowmotion - - config.seek.enter_forward - config.seek.enter_backward - - config.seek.stepwise_minspeed - config.seek.stepwise_repeat + + config.seek.enter_forward + config.seek.enter_backward config.seek.on_pause config.usage.pip_zero_button config.usage.alternatives_priority diff --git a/lib/driver/rcconsole.cpp b/lib/driver/rcconsole.cpp index 97a6e7c..77f4322 100644 --- a/lib/driver/rcconsole.cpp +++ b/lib/driver/rcconsole.cpp @@ -103,7 +103,7 @@ class eRCConsoleInit eRCConsoleDriver driver; eRCConsole device; public: - eRCConsoleInit(): driver("/dev/vc/0"), device(&driver) + eRCConsoleInit(): driver("/dev/tty0"), device(&driver) { } }; diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 88cd3ee..a89f72b 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -203,6 +203,9 @@ int eDVBAudio::startPid(int pid, int type) case aLPCM: bypass = 6; break; + case aDTSHD: + bypass = 0x10; + break; } eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass); @@ -1299,9 +1302,10 @@ RESULT eTSMPEGDecoder::showSinglePic(const char *filename) if (f >= 0) { struct stat s; + size_t written=0; fstat(f, &s); if (m_video_clip_fd == -1) - m_video_clip_fd = open("/dev/dvb/adapter0/video0", O_WRONLY|O_NONBLOCK); + m_video_clip_fd = open("/dev/dvb/adapter0/video0", O_WRONLY); if (m_video_clip_fd >= 0) { bool seq_end_avail = false; diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h index 3a0fbac..7610b65 100644 --- a/lib/dvb/decoder.h +++ b/lib/dvb/decoder.h @@ -13,7 +13,7 @@ private: ePtr m_demux; int m_fd, m_fd_demux, m_dev, m_is_freezed; public: - enum { aMPEG, aAC3, aDTS, aAAC, aAACHE, aLPCM }; + enum { aMPEG, aAC3, aDTS, aAAC, aAACHE, aLPCM, aDTSHD }; eDVBAudio(eDVBDemux *demux, int dev); enum { aMonoLeft, aStereo, aMonoRight }; void setChannel(int channel); diff --git a/lib/dvb/demux.cpp b/lib/dvb/demux.cpp index 0c736c5..f4d8618 100644 --- a/lib/dvb/demux.cpp +++ b/lib/dvb/demux.cpp @@ -85,6 +85,13 @@ int eDVBDemux::openDemux(void) return ::open(filename, O_RDWR); } +int eDVBDemux::openDVR(int flags) +{ + char filename[128]; + snprintf(filename, 128, "/dev/dvb/adapter%d/dvr%d", adapter, demux); + return ::open(filename, flags); +} + DEFINE_REF(eDVBDemux) RESULT eDVBDemux::setSourceFrontend(int fenum) diff --git a/lib/dvb/demux.h b/lib/dvb/demux.h index d43c41b..e73982e 100644 --- a/lib/dvb/demux.h +++ b/lib/dvb/demux.h @@ -26,7 +26,8 @@ public: RESULT getCADemuxID(uint8_t &id) { id = demux; return 0; } RESULT flush(); RESULT connectEvent(const Slot1 &event, ePtr &conn); - + int openDVR(int flags); + int getRefCount() { return ref; } private: int adapter, demux, source; diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index c2ddb40..6f9a67f 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -466,7 +466,7 @@ RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr unused; - if (m_boxtype == DM800 || m_boxtype == DM500HD || m_boxtype == DM800SE) // dm800 / 500hd + if (m_boxtype == DM800) // dm800 { cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux for (; i != m_demux.end(); ++i, ++n) @@ -522,7 +522,7 @@ RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr &source, const char *streaminfo_f /* (this codepath needs to be improved anyway.) */ #if HAVE_DVB_API_VERSION < 3 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY); -#else - m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY); -#endif if (m_pvr_fd_dst < 0) { - eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved. + eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved. + return -ENODEV; + } +#else + ePtr &demux = m_demux ? m_demux : m_decoder_demux; + if (demux) + { + m_pvr_fd_dst = demux->get().openDVR(O_WRONLY); + if (m_pvr_fd_dst < 0) + { + eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved. + return -ENODEV; + } + } + else + { + eDebug("no demux allocated yet.. so its not possible to open the dvr device!!"); return -ENODEV; } +#endif } m_pvr_thread = new eDVBChannelFilePush(); diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index ed31903..4d32474 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -366,6 +366,8 @@ void eEPGCache::DVBChannelRunning(iDVBChannel *chan) messages.send(Message(Message::startChannel, chan)); // -> gotMessage -> changedService } + else + data.state=-1; } } } @@ -1187,7 +1189,7 @@ void eEPGCache::save() eEPGCache::channel_data::channel_data(eEPGCache *ml) :cache(ml) - ,abortTimer(eTimer::create(ml)), zapTimer(eTimer::create(ml)), state(-1) + ,abortTimer(eTimer::create(ml)), zapTimer(eTimer::create(ml)), state(-2) ,isRunning(0), haveData(0) #ifdef ENABLE_PRIVATE_EPG ,startPrivateTimer(eTimer::create(ml)) diff --git a/lib/dvb/esection.h b/lib/dvb/esection.h index 833cc93..3e097cc 100644 --- a/lib/dvb/esection.h +++ b/lib/dvb/esection.h @@ -100,6 +100,10 @@ class eAUTable: public eAUGTable int first; ePtr m_demux; eMainloop *ml; + + /* needed to detect broken table version handling (seen on some m2ts files) */ + struct timespec m_prev_table_update; + int m_table_cnt; public: eAUTable() @@ -119,6 +123,7 @@ public: int begin(eMainloop *m, const eDVBTableSpec &spec, ePtr demux) { + m_table_cnt = 0; ml = m; m_demux = demux; first= 1; @@ -197,6 +202,24 @@ public: if (current && (!current->getSpec(spec))) { + /* detect broken table version handling (seen on some m2ts files) */ + if (m_table_cnt) + { + if (abs(timeout_usec(m_prev_table_update)) > 500000) + m_table_cnt = -1; + else if (m_table_cnt > 1) // two pmt update within one second + { + eDebug("Seen two consecutive table version changes within 500ms. " + "This seems broken, so auto update for pid %04x, table %02x is now disabled!!", + spec.pid, spec.tid); + m_table_cnt = 0; + return; + } + } + + ++m_table_cnt; + clock_gettime(CLOCK_MONOTONIC, &m_prev_table_update); + next = new Table(); CONNECT(next->tableReady, eAUTable::slotTableReady); spec.flags &= ~(eDVBTableSpec::tfAnyVersion|eDVBTableSpec::tfThisVersion|eDVBTableSpec::tfHaveTimeout); diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp index ea9e738..b5de46c 100644 --- a/lib/dvb/frontend.cpp +++ b/lib/dvb/frontend.cpp @@ -1860,11 +1860,11 @@ int eDVBFrontend::tuneLoopInt() // called by m_tuneTimer int slotid = sec_fe->m_slotid; // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000 if (slotid < 2) - sprintf(dev, "/dev/i2c/%d", slotid); + sprintf(dev, "/dev/i2c-%d", slotid); else if (slotid == 2) - sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2 + sprintf(dev, "/dev/i2c-2"); // first nim socket on DM8000 use /dev/i2c-2 else if (slotid == 3) - sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4 + sprintf(dev, "/dev/i2c-4"); // second nim socket on DM8000 use /dev/i2c-4 int fd = ::open(dev, O_RDWR); unsigned char data[2]; diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index f15cd04..86936f8 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -636,6 +636,7 @@ public: virtual RESULT getSTC(pts_t &pts, int num=0)=0; virtual RESULT getCADemuxID(uint8_t &id)=0; virtual RESULT flush()=0; + virtual int openDVR(int flags)=0; }; #if HAVE_DVB_API_VERSION < 3 && !defined(VIDEO_EVENT_SIZE_CHANGED) @@ -650,7 +651,7 @@ public: /** Set Displayed Video PID and type */ virtual RESULT setVideoPID(int vpid, int type)=0; - enum { af_MPEG, af_AC3, af_DTS, af_AAC }; + enum { af_MPEG, af_AC3, af_DTS, af_AAC, af_DTSHD }; /** Set Displayed Audio PID and type */ virtual RESULT setAudioPID(int apid, int type)=0; diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index ca56141..e5e6331 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -20,13 +20,14 @@ #include eDVBServicePMTHandler::eDVBServicePMTHandler() - :m_ca_servicePtr(0), m_dvb_scan(0), m_decode_demux_num(0xFF) + :m_ca_servicePtr(0), m_dvb_scan(0), m_decode_demux_num(0xFF), m_no_pat_entry_delay(eTimer::create()) { m_use_decode_demux = 0; m_pmt_pid = -1; eDVBResourceManager::getInstance(m_resourceManager); CONNECT(m_PMT.tableReady, eDVBServicePMTHandler::PMTready); CONNECT(m_PAT.tableReady, eDVBServicePMTHandler::PATready); + CONNECT(m_no_pat_entry_delay->timeout, eDVBServicePMTHandler::sendEventNoPatEntry); } eDVBServicePMTHandler::~eDVBServicePMTHandler() @@ -43,8 +44,15 @@ void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel) && (state == iDVBChannel::state_ok) && (!m_demux)) { if (m_channel) - if (m_channel->getDemux(m_demux, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode)) + { + if (m_pvr_demux_tmp) + { + m_demux = m_pvr_demux_tmp; + m_pvr_demux_tmp = NULL; + } + else if (m_channel->getDemux(m_demux, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode)) eDebug("Allocating %s-decoding a demux for now tuned-in channel failed.", m_use_decode_demux ? "" : "non-"); + } serviceEvent(eventTuned); @@ -126,25 +134,55 @@ void eDVBServicePMTHandler::PMTready(int error) } } +void eDVBServicePMTHandler::sendEventNoPatEntry() +{ + serviceEvent(eventNoPATEntry); +} + void eDVBServicePMTHandler::PATready(int) { + eDebug("PATready"); ePtr > ptr; if (!m_PAT.getCurrent(ptr)) { + int service_id_single = -1; + int pmtpid_single = -1; int pmtpid = -1; + int cnt=0; std::vector::const_iterator i; for (i = ptr->getSections().begin(); pmtpid == -1 && i != ptr->getSections().end(); ++i) { const ProgramAssociationSection &pat = **i; ProgramAssociationConstIterator program; for (program = pat.getPrograms()->begin(); pmtpid == -1 && program != pat.getPrograms()->end(); ++program) + { + ++cnt; if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID()) pmtpid = (*program)->getProgramMapPid(); + if (++cnt == 1 && pmtpid_single == -1 && pmtpid == -1) + { + pmtpid_single = (*program)->getProgramMapPid(); + service_id_single = (*program)->getProgramNumber(); + } + else + pmtpid_single = service_id_single = -1; + } } - if (pmtpid == -1) - serviceEvent(eventNoPATEntry); - else + if (pmtpid_single != -1) // only one PAT entry .. and not valid pmtpid found + { + eDebug("use single pat entry!"); + m_reference.setServiceID(eServiceID(service_id_single)); + pmtpid = pmtpid_single; + } + if (pmtpid == -1) { + eDebug("no PAT entry found.. start delay"); + m_no_pat_entry_delay->start(1000, true); + } + else { + eDebug("use pmtpid %04x for service_id %04x", pmtpid, m_reference.getServiceID().get()); + m_no_pat_entry_delay->stop(); m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux); + } } else serviceEvent(eventNoPAT); } @@ -230,8 +268,29 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i) { const ProgramMapSection &pmt = **i; + int is_hdmv = 0; + program.pcrPid = pmt.getPcrPid(); + for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); + desc != pmt.getDescriptors()->end(); ++desc) + { + if ((*desc)->getTag() == CA_DESCRIPTOR) + { + CaDescriptor *descr = (CaDescriptor*)(*desc); + program::capid_pair pair; + pair.caid = descr->getCaSystemId(); + pair.capid = descr->getCaPid(); + program.caids.push_back(pair); + } + else if ((*desc)->getTag() == REGISTRATION_DESCRIPTOR) + { + RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); + if (d->getFormatIdentifier() == 0x48444d56) // HDMV + is_hdmv = 1; + } + } + ElementaryStreamInfoConstIterator es; for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) { @@ -287,25 +346,34 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) audio.type = audioStream::atAACHE; forced_audio = 1; } - case 0x80: // user private ... but blueray LPCM - if (!isvideo && !isaudio) + case 0x80: // user private ... but bluray LPCM + case 0xA0: // bluray secondary LPCM + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atLPCM; } - case 0x81: // user private ... but blueray AC3 - if (!isvideo && !isaudio) + case 0x81: // user private ... but bluray AC3 + case 0xA1: // bluray secondary AC3 + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atAC3; } - case 0x82: // Blueray DTS (dvb user private...) - case 0xA2: // Blueray secondary DTS - if (!isvideo && !isaudio) + case 0x82: // bluray DTS (dvb user private...) + case 0xA2: // bluray secondary DTS + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atDTS; } + case 0x86: // bluray DTS-HD (dvb user private...) + case 0xA6: // bluray secondary DTS-HD + if (!isvideo && !isaudio && is_hdmv) + { + isaudio = 1; + audio.type = audioStream::atDTSHD; + } case 0x06: // PES Private case 0xEA: // TS_PSI_ST_SMPTE_VC1 { @@ -497,9 +565,9 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) default: break; } - if (isteletext && (isaudio || isvideo)) + if (isteletext && (isaudio || isvideo)) { - eDebug("ambiguous streamtype for PID %04x detected.. forced as teletext!", (*es)->getPid()); + eDebug("ambiguous streamtype for PID %04x detected.. forced as teletext!", (*es)->getPid()); continue; // continue with next PID } else if (issubtitle && (isaudio || isvideo)) @@ -537,18 +605,6 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) else continue; } - for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); - desc != pmt.getDescriptors()->end(); ++desc) - { - if ((*desc)->getTag() == CA_DESCRIPTOR) - { - CaDescriptor *descr = (CaDescriptor*)(*desc); - program::capid_pair pair; - pair.caid = descr->getCaSystemId(); - pair.capid = descr->getCaPid(); - program.caids.push_back(pair); - } - } } ret = 0; @@ -710,8 +766,8 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem { RESULT res=0; m_reference = ref; - m_use_decode_demux = use_decode_demux; + m_no_pat_entry_delay->stop(); /* use given service as backup. This is used for timeshift where we want to clone the live stream using the cache, but in fact have a PVR channel */ m_service = service; @@ -735,13 +791,12 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem { if (!ref.getServiceID().get() /* incorrect sid in meta file or recordings.epl*/ ) { - eWarning("no .meta file found, trying to find PMT pid"); eDVBTSTools tstools; + bool b = source || !tstools.openFile(ref.path.c_str(), 1); + eWarning("no .meta file found, trying to find PMT pid"); if (source) - tstools.setSource(source, streaminfo_file ? streaminfo_file : ref.path.c_str()); - else if (tstools.openFile(ref.path.c_str())) - eWarning("failed to open file"); - else + tstools.setSource(source, NULL); + if (b) { int service_id, pmt_pid; if (!tstools.findPMT(pmt_pid, service_id)) @@ -751,6 +806,8 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem m_pmt_pid = pmt_pid; } } + else + eWarning("no valid source to find PMT pid!"); } eDebug("alloc PVR"); /* allocate PVR */ @@ -792,7 +849,10 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem if (m_pvr_channel) { m_pvr_channel->setCueSheet(cue); - if (source) + + if (m_pvr_channel->getDemux(m_pvr_demux_tmp, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode)) + eDebug("Allocating %s-decoding a demux for PVR channel failed.", m_use_decode_demux ? "" : "non-"); + else if (source) m_pvr_channel->playSource(source, streaminfo_file); else m_pvr_channel->playFile(ref.path.c_str()); diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h index 86b634f..0c44f35 100644 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@ -86,8 +86,8 @@ class eDVBServicePMTHandler: public Object eUsePtr m_channel; eUsePtr m_pvr_channel; ePtr m_resourceManager; - ePtr m_demux; - + ePtr m_demux, m_pvr_demux_tmp; + void channelStateChanged(iDVBChannel *); ePtr m_channelStateChanged_connection; void channelEvent(iDVBChannel *, int event); @@ -102,6 +102,7 @@ class eDVBServicePMTHandler: public Object int m_use_decode_demux; uint8_t m_decode_demux_num; + ePtr m_no_pat_entry_delay; public: eDVBServicePMTHandler(); ~eDVBServicePMTHandler(); @@ -144,7 +145,7 @@ public: { int pid, rdsPid; // hack for some radio services which transmit radiotext on different pid (i.e. harmony fm, HIT RADIO FFH, ...) - enum { atMPEG, atAC3, atDTS, atAAC, atAACHE, atLPCM }; + enum { atMPEG, atAC3, atDTS, atAAC, atAACHE, atLPCM, atDTSHD }; int type; // mpeg2, ac3, dts, ... int component_tag; @@ -210,6 +211,7 @@ public: int getPMT(ePtr > &ptr) { return m_PMT.getCurrent(ptr); } int getChannel(eUsePtr &channel); void resetCachedProgram() { m_have_cached_program = false; } + void sendEventNoPatEntry(); /* deprecated interface */ int tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *sg=0, bool simulate=false, eDVBService *service = 0); diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 5cdecbd..e19dd1e 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -123,7 +123,7 @@ void eMPEGStreamInformation::fixupDiscontinuties() pts_t current = i->second - currentDelta; pts_t diff = current - lastpts_t; - if (llabs(diff) > (90000*5)) // 5sec diff + if (llabs(diff) > (90000*10)) // 10sec diff { // eDebug("%llx < %llx, have discont. new timestamp is %llx (diff is %llx)!", current, lastpts_t, i->second, diff); currentDelta = i->second - lastpts_t; /* FIXME: should be the extrapolated new timestamp, based on the current rate */ diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index 1403059..6cd855c 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -212,6 +212,8 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) break; case 0x71: // AC3 / DTS break; + case 0x72: // DTS - HD + break; default: eDebug("skip unknwn stream_id_extension %02x\n", payload[9+offs]); continue; @@ -700,9 +702,26 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram else if (direction == +1) direction = 0; } - /* let's find the next frame after the given offset */ off_t start = offset; +#if 0 + /* backtrack to find the previous sequence start, in case of MPEG2 */ + if ((data & 0xFF) == 0x00) { + do { + --start; + if (m_streaminfo.getStructureEntry(start, data, 0)) + { + eDebug("get previous failed"); + return -1; + } + } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00) && ((data & 0xFF) != 0xB3)); /* sequence start or previous frame */ + if ((data & 0xFF) != 0xB3) + start = offset; /* Failed to find corresponding sequence start, so never mind */ + } + +#endif + + /* let's find the next frame after the given offset */ do { if (m_streaminfo.getStructureEntry(offset, data, 1)) { @@ -717,9 +736,11 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram // eDebug("%08llx@%llx (next)", data, offset); } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00)); /* next frame */ +#if 0 /* align to TS pkt start */ -// start = start - (start % 188); -// offset = offset - (offset % 188); + start = start - (start % 188); + offset = offset - (offset % 188); +#endif len = offset - start; _offset = start; diff --git a/lib/gdi/accel.cpp b/lib/gdi/accel.cpp index fc739e9..bd1439f 100644 --- a/lib/gdi/accel.cpp +++ b/lib/gdi/accel.cpp @@ -138,12 +138,14 @@ int gAccel::fill(gSurface *dst, const eRect &area, unsigned long col) col); return 0; #endif -#if 0 // def BCM_ACCEL - bcm_accel_fill( - dst->data_phys, dst->x, dst->y, dst->stride, - area.left(), area.top(), area.width(), area.height(), - col); - return 0; +#ifdef BCM_ACCEL + if (!m_bcm_accel_state) { + bcm_accel_fill( + dst->data_phys, dst->x, dst->y, dst->stride, + area.left(), area.top(), area.width(), area.height(), + col); + return 0; + } #endif return -1; } diff --git a/lib/gdi/bcm.cpp b/lib/gdi/bcm.cpp index 12b5f22..b215b10 100644 --- a/lib/gdi/bcm.cpp +++ b/lib/gdi/bcm.cpp @@ -23,10 +23,10 @@ static int exec_list(void); int bcm_accel_init(void) { - fb_fd = open("/dev/fb/0", O_RDWR); + fb_fd = open("/dev/fb0", O_RDWR); if (fb_fd < 0) { - perror("/dev/fb/0"); + perror("/dev/fb0"); return 1; } if (exec_list()) @@ -123,6 +123,51 @@ void bcm_accel_fill( int x, int y, int width, int height, unsigned long color) { -// printf("unimplemented bcm_accel_fill\n"); + C(0x43); // reset source + C(0x53); // reset dest + C(0x5b); // reset pattern + C(0x67); // reset blend + C(0x75); // reset output + + // clear dest surface + P(0x0, 0); + P(0x1, 0); + P(0x2, 0); + P(0x3, 0); + P(0x4, 0); + C(0x45); + + // clear src surface + P(0x0, 0); + P(0x1, 0); + P(0x2, 0); + P(0x3, 0); + P(0x4, 0); + C(0x5); + + P(0x2d, color); + + P(0x2e, x); // prepare output rect + P(0x2f, y); + P(0x30, width); + P(0x31, height); + C(0x6e); // set this rect as output rect + + P(0x0, dst_addr); // prepare output surface + P(0x1, dst_stride); + P(0x2, dst_width); + P(0x3, dst_height); + P(0x4, 0x7e48888); + C(0x69); // set output surface + + P(0x6f, 0); + P(0x70, 0); + P(0x71, 2); + P(0x72, 2); + C(0x73); // select color keying + + C(0x77); // do it + + exec_list(); } diff --git a/lib/gdi/fb.cpp b/lib/gdi/fb.cpp index cde3e35..7ee555c 100644 --- a/lib/gdi/fb.cpp +++ b/lib/gdi/fb.cpp @@ -83,12 +83,12 @@ nolfb: int fbClass::showConsole(int state) { - int fd=open("/dev/vc/0", O_RDWR); + int fd=open("/dev/tty0", O_RDWR); if(fd>=0) { if(ioctl(fd, KDSETMODE, state?KD_TEXT:KD_GRAPHICS)<0) { - eDebug("setting /dev/vc/0 status failed."); + eDebug("setting /dev/tty0 status failed."); } close(fd); } diff --git a/lib/gdi/fb.h b/lib/gdi/fb.h index 5447380..fcb5ff2 100644 --- a/lib/gdi/fb.h +++ b/lib/gdi/fb.h @@ -19,7 +19,7 @@ class fbClass int m_number_of_pages; int m_phys_mem; #ifdef SWIG - fbClass(const char *fb="/dev/fb/0"); + fbClass(const char *fb="/dev/fb0"); ~fbClass(); public: #else @@ -41,7 +41,7 @@ public: unsigned int Stride() { return stride; } fb_cmap *CMAP() { return &cmap; } - fbClass(const char *fb="/dev/fb/0"); + fbClass(const char *fb="/dev/fb0"); ~fbClass(); // low level gfx stuff diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp index a19e11a..ba0794e 100644 --- a/lib/gui/elistboxcontent.cpp +++ b/lib/gui/elistboxcontent.cpp @@ -641,7 +641,8 @@ static ePyObject lookupColor(ePyObject color, ePyObject data) if ((icolor & 0xFF000000) == 0xFF000000) { int index = icolor & 0xFFFFFF; - eDebug("[eListboxPythonMultiContent] template color index: %d", index); + if (PyTuple_GetItem(data, index) == Py_None) + return ePyObject(); return PyTuple_GetItem(data, index); } diff --git a/lib/gui/epositiongauge.cpp b/lib/gui/epositiongauge.cpp index ff98c08..e45d4a6 100644 --- a/lib/gui/epositiongauge.cpp +++ b/lib/gui/epositiongauge.cpp @@ -112,6 +112,7 @@ int ePositionGauge::event(int event, void *data, void *data2) // painter.fill(eRect(0, 10, s.width(), s.height()-20)); pts_t in = 0, out = 0; + int xm, xm_last = -1; std::multiset::iterator i(m_cue_entries.begin()); @@ -126,17 +127,22 @@ int ePositionGauge::event(int event, void *data, void *data2) continue; } else if (i->what == 1) /* out */ out = i++->where; - else if (i->what == 2) /* mark */ + else /* mark or last */ { - int xm = scale(i->where); - painter.setForegroundColor(gRGB(0xFF8080)); - painter.fill(eRect(xm - 2, 0, 4, s.height())); + xm = scale(i->where); + if (i->what == 2) { + painter.setForegroundColor(gRGB(0xFF8080)); + if (xm - 2 < xm_last) /* Make sure last is not overdrawn */ + painter.fill(eRect(xm_last, 0, 2 + xm - xm_last, s.height())); + else + painter.fill(eRect(xm - 2, 0, 4, s.height())); + } else if (i->what == 3) { + painter.setForegroundColor(gRGB(0x80FF80)); + painter.fill(eRect(xm - 1, 0, 3, s.height())); + xm_last = xm + 2; + } i++; continue; - } else /* other marker, like last position */ - { - ++i; - continue; } } diff --git a/lib/gui/esubtitle.h b/lib/gui/esubtitle.h index 45345db..cdad728 100644 --- a/lib/gui/esubtitle.h +++ b/lib/gui/esubtitle.h @@ -23,15 +23,21 @@ struct ePangoSubtitlePageElement struct ePangoSubtitlePage { - pts_t show_pts; + pts_t m_show_pts; int m_timeout; /* in milliseconds */ std::vector m_elements; void clear() { m_elements.clear(); } }; +struct eVobSubtitlePage +{ + pts_t m_show_pts; + int m_timeout; /* in milliseconds */ + ePtr m_pixmap; +}; + class eDVBTeletextSubtitlePage; -class eDVBPangoSubtitlePage; -class ePangoSubtitlePage; +class eDVBSubtitlePage; class eSubtitleWidget: public eWidget, public Object { diff --git a/lib/python/Components/FileList.py b/lib/python/Components/FileList.py index 1d71514..1b7e81f 100755 --- a/lib/python/Components/FileList.py +++ b/lib/python/Components/FileList.py @@ -28,7 +28,8 @@ EXTENSIONS = { "mpeg": "movie", "mkv": "movie", "mp4": "movie", - "mov": "movie" + "mov": "movie", + "m2ts": "movie", } def FileEntryComponent(name, absolute = None, isDir = False): diff --git a/lib/python/Components/Sources/ServiceEvent.py b/lib/python/Components/Sources/ServiceEvent.py index 93c733b..8a0a66a 100644 --- a/lib/python/Components/Sources/ServiceEvent.py +++ b/lib/python/Components/Sources/ServiceEvent.py @@ -25,7 +25,7 @@ class ServiceEvent(Source, object): def newService(self, ref): if not self.service or not ref or self.service != ref: self.service = ref - if not ref or (ref.flags & Ref.flagDirectory) == Ref.flagDirectory or ref.flags & Ref.isMarker: + if not ref: self.changed((self.CHANGED_CLEAR,)) else: self.changed((self.CHANGED_ALL,)) diff --git a/lib/python/Components/TimerSanityCheck.py b/lib/python/Components/TimerSanityCheck.py index b472a19..b9dda6a 100644 --- a/lib/python/Components/TimerSanityCheck.py +++ b/lib/python/Components/TimerSanityCheck.py @@ -2,6 +2,7 @@ import NavigationInstance from time import localtime, mktime, gmtime from ServiceReference import ServiceReference from enigma import iServiceInformation, eServiceCenter, eServiceReference +from timer import TimerEntry class TimerSanityCheck: def __init__(self, timerlist, newtimer=None): @@ -107,7 +108,7 @@ class TimerSanityCheck: self.rep_eventlist.append((begin, idx)) begin += 86400 rflags >>= 1 - else: + elif timer.state < TimerEntry.StateEnded: self.nrep_eventlist.extend([(timer.begin,self.bflag,idx),(timer.end,self.eflag,idx)]) idx += 1 diff --git a/lib/python/Components/UsageConfig.py b/lib/python/Components/UsageConfig.py index 8ea9aa6..a265a16 100644 --- a/lib/python/Components/UsageConfig.py +++ b/lib/python/Components/UsageConfig.py @@ -102,13 +102,11 @@ def InitUsageConfig(): config.seek.selfdefined_79 = ConfigNumber(default=300) config.seek.speeds_forward = ConfigSet(default=[2, 4, 8, 16, 32, 64, 128], choices=[2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128]) - config.seek.speeds_backward = ConfigSet(default=[8, 16, 32, 64, 128], choices=[1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128]) + config.seek.speeds_backward = ConfigSet(default=[2, 4, 8, 16, 32, 64, 128], choices=[1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128]) config.seek.speeds_slowmotion = ConfigSet(default=[2, 4, 8], choices=[2, 4, 6, 8, 12, 16, 25]) config.seek.enter_forward = ConfigSelection(default = "2", choices = ["2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) config.seek.enter_backward = ConfigSelection(default = "1", choices = ["1", "2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) - config.seek.stepwise_minspeed = ConfigSelection(default = "16", choices = ["Never", "2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) - config.seek.stepwise_repeat = ConfigSelection(default = "3", choices = ["2", "3", "4", "5", "6"]) config.seek.on_pause = ConfigSelection(default = "play", choices = [ ("play", _("Play")), diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index e00dedd..2e7435b 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -174,7 +174,8 @@ class DemuxTask(Task): print "[DemuxTask::cleanup]" self.mplex_streamfiles = [ self.mplex_videofile ] for pid in self.relevantAudioPIDs: - self.mplex_streamfiles.append(self.mplex_audiofiles[pid]) + if pid in self.mplex_audiofiles: + self.mplex_streamfiles.append(self.mplex_audiofiles[pid]) print self.mplex_streamfiles if failed: diff --git a/lib/python/Plugins/Extensions/DVDPlayer/keymap.xml b/lib/python/Plugins/Extensions/DVDPlayer/keymap.xml index 7b7f205..bf57e75 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/keymap.xml +++ b/lib/python/Plugins/Extensions/DVDPlayer/keymap.xml @@ -8,7 +8,8 @@ - + + diff --git a/lib/python/Plugins/Extensions/DVDPlayer/plugin.py b/lib/python/Plugins/Extensions/DVDPlayer/plugin.py index eaf8db6..1cee0aa 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/DVDPlayer/plugin.py @@ -4,7 +4,7 @@ from Screens.Screen import Screen from Screens.MessageBox import MessageBox from Screens.ChoiceBox import ChoiceBox from Screens.HelpMenu import HelpableScreen -from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications +from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications, InfoBarAudioSelection, InfoBarSubtitleSupport from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap from Components.Label import Label from Components.Sources.StaticText import StaticText @@ -195,7 +195,7 @@ class ChapterZap(Screen): self.Timer.callback.append(self.keyOK) self.Timer.start(3000, True) -class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport): +class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport, InfoBarAudioSelection, InfoBarSubtitleSupport): ALLOW_SUSPEND = Screen.SUSPEND_PAUSES ENABLE_RESUME_SUPPORT = True @@ -244,8 +244,6 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP self.saved_config_speeds_backward = config.seek.speeds_backward.value self.saved_config_enter_forward = config.seek.enter_forward.value self.saved_config_enter_backward = config.seek.enter_backward.value - self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value - self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value self.saved_config_seek_on_pause = config.seek.on_pause.value self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value @@ -255,8 +253,6 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP config.seek.speeds_slowmotion.value = [ ] config.seek.enter_forward.value = "2" config.seek.enter_backward.value = "2" - config.seek.stepwise_minspeed.value = "Never" - config.seek.stepwise_repeat.value = "3" config.seek.on_pause.value = "play" def restore_infobar_seek_config(self): @@ -265,8 +261,6 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion config.seek.enter_forward.value = self.saved_config_enter_forward config.seek.enter_backward.value = self.saved_config_enter_backward - config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed - config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat config.seek.on_pause.value = self.saved_config_seek_on_pause def __init__(self, session, dvd_device = None, dvd_filelist = [ ], args = None): @@ -275,10 +269,12 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP InfoBarNotifications.__init__(self) InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions") InfoBarShowHide.__init__(self) + InfoBarAudioSelection.__init__(self) + InfoBarSubtitleSupport.__init__(self) HelpableScreen.__init__(self) self.save_infobar_seek_config() self.change_infobar_seek_config() - InfoBarSeek.__init__(self, useSeekBackHack=False) + InfoBarSeek.__init__(self) InfoBarPVRState.__init__(self) self.dvdScreen = self.session.instantiateDialog(DVDOverlay) @@ -354,6 +350,7 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP "prevTitle": (self.prevTitle, _("jump back to the previous title")), "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")), "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")), + "AudioSelection": (self.enterAudioSelection, _("Select audio track")), "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")), "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")), "nextAngle": (self.nextAngle, _("switch to the next angle")), @@ -546,6 +543,9 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP keys.keyPressed(key) return keys + def enterAudioSelection(self): + self.audioSelection() + def nextAudioTrack(self): self.sendKey(iServiceKeys.keyUser) diff --git a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp index 5fbfb0a..6d1397d 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp +++ b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp @@ -397,6 +397,61 @@ RESULT eServiceDVD::subtitle(ePtr &ptr) return 0; } +RESULT eServiceDVD::audioTracks(ePtr &ptr) +{ + ptr = this; + return 0; +} + +int eServiceDVD::getNumberOfTracks() +{ + int i = 0; + ddvd_get_audio_count(m_ddvdconfig, &i); + return i; +} + +int eServiceDVD::getCurrentTrack() +{ + int audio_id,audio_type; + uint16_t audio_lang; + ddvd_get_last_audio(m_ddvdconfig, &audio_id, &audio_lang, &audio_type); + return audio_id; +} + +RESULT eServiceDVD::selectTrack(unsigned int i) +{ + ddvd_set_audio(m_ddvdconfig, i); + return 0; +} + +RESULT eServiceDVD::getTrackInfo(struct iAudioTrackInfo &info, unsigned int audio_id) +{ + int audio_type; + uint16_t audio_lang; + ddvd_get_audio_byid(m_ddvdconfig, audio_id, &audio_lang, &audio_type); + char audio_string[3]={audio_lang >> 8, audio_lang, 0}; + info.m_pid = audio_id+1; + info.m_language = audio_string; + switch(audio_type) + { + case DDVD_MPEG: + info.m_description = "MPEG"; + break; + case DDVD_AC3: + info.m_description = "AC3"; + break; + case DDVD_DTS: + info.m_description = "DTS"; + break; + case DDVD_LPCM: + info.m_description = "LPCM"; + break; + default: + info.m_description = "und"; + } + return 0; +} + RESULT eServiceDVD::keys(ePtr &ptr) { ptr=this; @@ -623,14 +678,33 @@ PyObject *eServiceDVD::getInfoObject(int w) Py_RETURN_NONE; } -RESULT eServiceDVD::enableSubtitles(eWidget *parent, SWIG_PYOBJECT(ePyObject) /*entry*/) +RESULT eServiceDVD::enableSubtitles(eWidget *parent, ePyObject tuple) { delete m_subtitle_widget; + eSize size = eSize(720, 576); m_subtitle_widget = new eSubtitleWidget(parent); m_subtitle_widget->resize(parent->size()); - eSize size = eSize(720, 576); + int pid = -1; + + if ( tuple != Py_None ) + { + ePyObject entry; + int tuplesize = PyTuple_Size(tuple); + if (!PyTuple_Check(tuple)) + goto error_out; + if (tuplesize < 1) + goto error_out; + entry = PyTuple_GET_ITEM(tuple, 1); + if (!PyInt_Check(entry)) + goto error_out; + pid = PyInt_AsLong(entry)-1; + + ddvd_set_spu(m_ddvdconfig, pid); + m_event(this, evUser+7); + } + eDebug("eServiceDVD::enableSubtitles %i", pid); if (!m_pixmap) { @@ -648,6 +722,9 @@ RESULT eServiceDVD::enableSubtitles(eWidget *parent, SWIG_PYOBJECT(ePyObject) /* m_subtitle_widget->show(); return 0; + +error_out: + return -1; } RESULT eServiceDVD::disableSubtitles(eWidget */*parent*/) @@ -659,8 +736,26 @@ RESULT eServiceDVD::disableSubtitles(eWidget */*parent*/) PyObject *eServiceDVD::getSubtitleList() { - eDebug("eServiceDVD::getSubtitleList nyi"); - Py_RETURN_NONE; + ePyObject l = PyList_New(0); + unsigned int spu_count = 0; + ddvd_get_spu_count(m_ddvdconfig, &spu_count); + + for ( unsigned int spu_id = 0; spu_id < spu_count; spu_id++ ) + { + uint16_t spu_lang; + ddvd_get_spu_byid(m_ddvdconfig, spu_id, &spu_lang); + char spu_string[3]={spu_lang >> 8, spu_lang, 0}; + + ePyObject tuple = PyTuple_New(5); + PyTuple_SetItem(tuple, 0, PyInt_FromLong(2)); + PyTuple_SetItem(tuple, 1, PyInt_FromLong(spu_id+1)); + PyTuple_SetItem(tuple, 2, PyInt_FromLong(5)); + PyTuple_SetItem(tuple, 3, PyInt_FromLong(0)); + PyTuple_SetItem(tuple, 4, PyString_FromString(spu_string)); + PyList_Append(l, tuple); + Py_DECREF(tuple); + } + return l; } PyObject *eServiceDVD::getCachedSubtitle() diff --git a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h index c751a39..80cfcf0 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h +++ b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h @@ -26,7 +26,7 @@ public: RESULT offlineOperations(const eServiceReference &, ePtr &ptr); }; -class eServiceDVD: public iPlayableService, public iPauseableService, public iSeekableService, +class eServiceDVD: public iPlayableService, public iPauseableService, public iSeekableService, public iAudioTrackSelection, public iServiceInformation, public iSubtitleOutput, public iServiceKeys, public iCueSheet, public eThread, public Object { friend class eServiceFactoryDVD; @@ -35,7 +35,7 @@ public: virtual ~eServiceDVD(); // not implemented (yet) RESULT audioChannel(ePtr &ptr) { ptr = 0; return -1; } - RESULT audioTracks(ePtr &ptr) { ptr = 0; return -1; } + RESULT audioTracks(ePtr &ptr); RESULT frontendInfo(ePtr &ptr) { ptr = 0; return -1; } RESULT subServices(ePtr &ptr) { ptr = 0; return -1; } RESULT timeshift(ePtr &ptr) { ptr = 0; return -1; } @@ -89,8 +89,15 @@ public: void setCutList(SWIG_PYOBJECT(ePyObject)); void setCutListEnable(int enable); - // iServiceKeys + // iAudioTrackSelection + int getNumberOfTracks(); + RESULT selectTrack(unsigned int i); + RESULT getTrackInfo(struct iAudioTrackInfo &, unsigned int n); + int getCurrentTrack(); + + // iServiceKeys RESULT keyPressed(int key); + private: eServiceDVD(eServiceReference ref); diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py index b44a247..6ff1c5a 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@ -110,7 +110,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB # 'None' is magic to start at the list of mountpoints defaultDir = config.mediaplayer.defaultDir.getValue() - self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|m4v|mkv|mp4|m4a|dat|flac|mov)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") + self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|m4v|mkv|mp4|m4a|dat|flac|mov|m2ts)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") self["filelist"] = self.filelist self.playlist = MyPlayList() diff --git a/lib/python/Screens/AudioSelection.py b/lib/python/Screens/AudioSelection.py index a0bfcab..4c68962 100644 --- a/lib/python/Screens/AudioSelection.py +++ b/lib/python/Screens/AudioSelection.py @@ -46,7 +46,7 @@ class AudioSelection(Screen, ConfigListScreen): "cancel": self.cancel, "up": self.keyUp, "down": self.keyDown, - }, -3) + }, -2) self.settings = ConfigSubsection() choicelist = [(PAGE_AUDIO,_("audio tracks")), (PAGE_SUBTITLES,_("Subtitles"))] @@ -62,13 +62,12 @@ class AudioSelection(Screen, ConfigListScreen): streams = [] conflist = [] selectedidx = 0 - - service = self.session.nav.getCurrentService() - self.audioTracks = audio = service and service.audioTracks() - n = audio and audio.getNumberOfTracks() or 0 - + if self.settings.menupage.getValue() == PAGE_AUDIO: self.setTitle(_("Select audio track")) + service = self.session.nav.getCurrentService() + self.audioTracks = audio = service and service.audioTracks() + n = audio and audio.getNumberOfTracks() or 0 if SystemInfo["CanDownmixAC3"]: self.settings.downmix = ConfigOnOff(default=config.av.downmix_ac3.value) self.settings.downmix.addNotifier(self.changeAC3Downmix, initial_call = False) @@ -77,11 +76,15 @@ class AudioSelection(Screen, ConfigListScreen): if n > 0: self.audioChannel = service.audioChannel() - choicelist = [("0",_("left")), ("1",_("stereo")), ("2", _("right"))] - self.settings.channelmode = ConfigSelection(choices = choicelist, default = str(self.audioChannel.getCurrentChannel())) - self.settings.channelmode.addNotifier(self.changeMode, initial_call = False) - conflist.append(getConfigListEntry(_("Channel"), self.settings.channelmode)) - self["key_green"].setBoolean(True) + if self.audioChannel: + choicelist = [("0",_("left")), ("1",_("stereo")), ("2", _("right"))] + self.settings.channelmode = ConfigSelection(choices = choicelist, default = str(self.audioChannel.getCurrentChannel())) + self.settings.channelmode.addNotifier(self.changeMode, initial_call = False) + conflist.append(getConfigListEntry(_("Channel"), self.settings.channelmode)) + self["key_green"].setBoolean(True) + else: + conflist.append(('',)) + self["key_green"].setBoolean(False) selectedAudio = self.audioTracks.getCurrentTrack() for x in range(n): number = str(x) @@ -137,7 +140,7 @@ class AudioSelection(Screen, ConfigListScreen): language = _("") selected = "" - if sel and x[:4] == sel[:4]: + if sel and x == sel: selected = _("Running") selectedidx = idx @@ -156,7 +159,7 @@ class AudioSelection(Screen, ConfigListScreen): number = "%x%02x" % (x[3],x[2]) elif x[0] == 2: - types = ("UTF-8 text","SSA / AAS",".SRT file") + types = (_(""), "UTF-8 text", "SSA", "AAS", ".SRT file", "VOB", "PGS (unsupported)") description = types[x[2]] streams.append((x, "", number, description, language, selected)) @@ -185,7 +188,7 @@ class AudioSelection(Screen, ConfigListScreen): conflist.append(getConfigListEntry(Plugins[0][0], ConfigNothing())) self.plugincallfunc = Plugins[0][1] if len(Plugins) > 1: - print "these plugins are installed but not displayed in the dialog box:", Plugins[1:] + print "plugin(s) installed but not displayed in the dialog box:", Plugins[1:] self["config"].list = conflist self["config"].l.setList(conflist) @@ -219,7 +222,7 @@ class AudioSelection(Screen, ConfigListScreen): config.av.downmix_ac3.save() def changeMode(self, mode): - if mode is not None: + if mode is not None and self.audioChannel: self.audioChannel.selectChannel(int(mode.getValue())) def changeAudio(self, audio): diff --git a/lib/python/Screens/InfoBar.py b/lib/python/Screens/InfoBar.py index 5b06124..5506287 100644 --- a/lib/python/Screens/InfoBar.py +++ b/lib/python/Screens/InfoBar.py @@ -221,6 +221,7 @@ class MoviePlayer(InfoBarBase, InfoBarShowHide, \ self.session.nav.stopService() elif answer == "restart": self.doSeek(0) + self.setSeekState(self.SEEK_STATE_PLAY) def doEofInternal(self, playing): if not self.execing: diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 6fa8911..4f6eafc 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -717,7 +717,7 @@ class InfoBarSeek: SEEK_STATE_PAUSE = (1, 0, 0, "||") SEEK_STATE_EOF = (1, 0, 0, "END") - def __init__(self, actionmap = "InfobarSeekActions", useSeekBackHack=True): + def __init__(self, actionmap = "InfobarSeekActions"): self.__event_tracker = ServiceEventTracker(screen=self, eventmap= { iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged, @@ -774,20 +774,10 @@ class InfoBarSeek: self.__seekableStatusChanged() def makeStateForward(self, n): -# minspeed = config.seek.stepwise_minspeed.value -# repeat = int(config.seek.stepwise_repeat.value) -# if minspeed != "Never" and n >= int(minspeed) and repeat > 1: -# return (0, n * repeat, repeat, ">> %dx" % n) -# else: - return (0, n, 0, ">> %dx" % n) + return (0, n, 0, ">> %dx" % n) def makeStateBackward(self, n): -# minspeed = config.seek.stepwise_minspeed.value -# repeat = int(config.seek.stepwise_repeat.value) -# if minspeed != "Never" and n >= int(minspeed) and repeat > 1: -# return (0, -n * repeat, repeat, "<< %dx" % n) -# else: - return (0, -n, 0, "<< %dx" % n) + return (0, -n, 0, "<< %dx" % n) def makeStateSlowMotion(self, n): return (0, 0, n, "/%d" % n) @@ -1970,20 +1960,21 @@ class InfoBarCueSheetSupport: return True def jumpPreviousMark(self): - # we add 2 seconds, so if the play position is <2s after + # we add 5 seconds, so if the play position is <5s after # the mark, the mark before will be used self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True) def jumpNextMark(self): - if not self.jumpPreviousNextMark(lambda x: x): + if not self.jumpPreviousNextMark(lambda x: x-90000): self.doSeek(-1) def getNearestCutPoint(self, pts, cmp=abs, start=False): # can be optimized - beforecut = False + beforecut = True nearest = None + bestdiff = -1 + instate = True if start: - beforecut = True bestdiff = cmp(0 - pts) if bestdiff >= 0: nearest = [0, False] @@ -1992,14 +1983,19 @@ class InfoBarCueSheetSupport: beforecut = False if cp[1] == self.CUT_TYPE_IN: # Start is here, disregard previous marks diff = cmp(cp[0] - pts) - if diff >= 0: + if start and diff >= 0: nearest = cp bestdiff = diff else: nearest = None - if cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST): + bestdiff = -1 + if cp[1] == self.CUT_TYPE_IN: + instate = True + elif cp[1] == self.CUT_TYPE_OUT: + instate = False + elif cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST): diff = cmp(cp[0] - pts) - if diff >= 0 and (nearest is None or bestdiff > diff): + if instate and diff >= 0 and (nearest is None or bestdiff > diff): nearest = cp bestdiff = diff return nearest diff --git a/lib/python/Screens/Standby.py b/lib/python/Screens/Standby.py index 1a7ebbd..94a56ee 100644 --- a/lib/python/Screens/Standby.py +++ b/lib/python/Screens/Standby.py @@ -160,14 +160,9 @@ class TryQuitMainloop(MessageBox): self.conntected=False self.session.nav.record_event.remove(self.getRecordEvent) if value: - # hack .. we dont like to show any other screens when this screen has closed - self.onClose = [self.__closed] - self.session.dialog_stack = [] - self.session.summary_stack = [None] - MessageBox.close(self, True) - - def __closed(self): - quitMainloop(self.retval) + quitMainloop(self.retval) + else: + MessageBox.close(self, True) def __onShow(self): global inTryQuitMainloop diff --git a/lib/python/Tools/Directories.py b/lib/python/Tools/Directories.py index 518db49..8e4d004 100755 --- a/lib/python/Tools/Directories.py +++ b/lib/python/Tools/Directories.py @@ -57,7 +57,7 @@ defaultPaths = { SCOPE_USERETC: ("", PATH_DONTCREATE), # user home directory SCOPE_DEFAULTDIR: (eEnv.resolve("${datadir}/enigma2/defaults/"), PATH_CREATE), - SCOPE_DEFAULTPARTITION: ("/dev/mtdblock/6", PATH_DONTCREATE), + SCOPE_DEFAULTPARTITION: ("/dev/mtdblock6", PATH_DONTCREATE), SCOPE_DEFAULTPARTITIONMOUNTDIR: (eEnv.resolve("${datadir}/enigma2/dealer"), PATH_CREATE), SCOPE_METADIR: (eEnv.resolve("${datadir}/meta"), PATH_CREATE), } diff --git a/lib/service/Makefile.am b/lib/service/Makefile.am index edafd1a..9f956b6 100644 --- a/lib/service/Makefile.am +++ b/lib/service/Makefile.am @@ -16,7 +16,8 @@ libenigma_service_a_SOURCES = \ servicedvb.cpp \ servicedvbrecord.cpp \ servicefs.cpp \ - servicemp3.cpp + servicemp3.cpp \ + servicem2ts.cpp serviceincludedir = $(pkgincludedir)/lib/service serviceinclude_HEADERS = \ @@ -27,7 +28,8 @@ serviceinclude_HEADERS = \ servicedvb.h \ servicedvbrecord.h \ servicefs.h \ - servicemp3.h + servicemp3.h \ + servicem2ts.h if HAVE_LIBXINE libenigma_service_a_SOURCES += \ diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 914d6bf..8650989 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1801,6 +1801,8 @@ RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int info.m_description = "AAC-HE"; else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS) info.m_description = "DTS"; + else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD) + info.m_description = "DTS-HD"; else info.m_description = "???"; diff --git a/lib/service/servicem2ts.cpp b/lib/service/servicem2ts.cpp new file mode 100644 index 0000000..e79907d --- /dev/null +++ b/lib/service/servicem2ts.cpp @@ -0,0 +1,380 @@ +#include +#include +#include +#include + +DEFINE_REF(eServiceFactoryM2TS) + +class eM2TSFile: public iTsSource +{ + DECLARE_REF(eM2TSFile); + eSingleLock m_lock; +public: + eM2TSFile(const char *filename, bool cached=false); + ~eM2TSFile(); + + // iTsSource + off_t lseek(off_t offset, int whence); + ssize_t read(off_t offset, void *buf, size_t count); + off_t length(); + int valid(); +private: + int m_sync_offset; + int m_fd; /* for uncached */ + FILE *m_file; /* for cached */ + off_t m_current_offset, m_length; + bool m_cached; + off_t lseek_internal(off_t offset, int whence); +}; + +class eStaticServiceM2TSInformation: public iStaticServiceInformation +{ + DECLARE_REF(eStaticServiceM2TSInformation); + eServiceReference m_ref; + eDVBMetaParser m_parser; +public: + eStaticServiceM2TSInformation(const eServiceReference &ref); + RESULT getName(const eServiceReference &ref, std::string &name); + int getLength(const eServiceReference &ref); + RESULT getEvent(const eServiceReference &ref, ePtr &SWIG_OUTPUT, time_t start_time); + int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; } + int getInfo(const eServiceReference &ref, int w); + std::string getInfoString(const eServiceReference &ref,int w); + PyObject *getInfoObject(const eServiceReference &r, int what); +}; + +DEFINE_REF(eStaticServiceM2TSInformation); + +eStaticServiceM2TSInformation::eStaticServiceM2TSInformation(const eServiceReference &ref) +{ + m_ref = ref; + m_parser.parseFile(ref.path); +} + +RESULT eStaticServiceM2TSInformation::getName(const eServiceReference &ref, std::string &name) +{ + ASSERT(ref == m_ref); + if (m_parser.m_name.size()) + name = m_parser.m_name; + else + { + name = ref.path; + size_t n = name.rfind('/'); + if (n != std::string::npos) + name = name.substr(n + 1); + } + return 0; +} + +int eStaticServiceM2TSInformation::getLength(const eServiceReference &ref) +{ + ASSERT(ref == m_ref); + + eDVBTSTools tstools; + + struct stat s; + stat(ref.path.c_str(), &s); + + eM2TSFile *file = new eM2TSFile(ref.path.c_str()); + ePtr source = file; + + if (!source->valid()) + return 0; + + tstools.setSource(source); + + /* check if cached data is still valid */ + if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length)) + return m_parser.m_length / 90000; + + /* open again, this time with stream info */ + tstools.setSource(source, ref.path.c_str()); + + /* otherwise, re-calc length and update meta file */ + pts_t len; + if (tstools.calcLen(len)) + return 0; + + m_parser.m_length = len; + m_parser.m_filesize = s.st_size; + m_parser.updateMeta(ref.path); + return m_parser.m_length / 90000; +} + +int eStaticServiceM2TSInformation::getInfo(const eServiceReference &ref, int w) +{ + switch (w) + { + case iServiceInformation::sDescription: + return iServiceInformation::resIsString; + case iServiceInformation::sServiceref: + return iServiceInformation::resIsString; + case iServiceInformation::sFileSize: + return m_parser.m_filesize; + case iServiceInformation::sTimeCreate: + if (m_parser.m_time_create) + return m_parser.m_time_create; + else + return iServiceInformation::resNA; + default: + return iServiceInformation::resNA; + } +} + +std::string eStaticServiceM2TSInformation::getInfoString(const eServiceReference &ref,int w) +{ + switch (w) + { + case iServiceInformation::sDescription: + return m_parser.m_description; + case iServiceInformation::sServiceref: + return m_parser.m_ref.toString(); + case iServiceInformation::sTags: + return m_parser.m_tags; + default: + return ""; + } +} + +PyObject *eStaticServiceM2TSInformation::getInfoObject(const eServiceReference &r, int what) +{ + switch (what) + { + case iServiceInformation::sFileSize: + return PyLong_FromLongLong(m_parser.m_filesize); + default: + Py_RETURN_NONE; + } +} + +RESULT eStaticServiceM2TSInformation::getEvent(const eServiceReference &ref, ePtr &evt, time_t start_time) +{ + if (!ref.path.empty()) + { + ePtr event = new eServiceEvent; + std::string filename = ref.path; + filename.erase(filename.length()-4, 2); + filename+="eit"; + if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get())) + { + evt = event; + return 0; + } + } + evt = 0; + return -1; +} + +DEFINE_REF(eM2TSFile); + +eM2TSFile::eM2TSFile(const char *filename, bool cached) + :m_lock(false), m_sync_offset(0), m_fd(-1), m_file(NULL), m_current_offset(0), m_length(0), m_cached(cached) +{ + if (!m_cached) + m_fd = ::open(filename, O_RDONLY | O_LARGEFILE); + else + m_file = ::fopen64(filename, "rb"); + if (valid()) + m_current_offset = m_length = lseek_internal(0, SEEK_END); +} + +eM2TSFile::~eM2TSFile() +{ + if (m_cached) + { + if (m_file) + { + ::fclose(m_file); + m_file = 0; + } + } + else + { + if (m_fd >= 0) + ::close(m_fd); + m_fd = -1; + } +} + +off_t eM2TSFile::lseek(off_t offset, int whence) +{ + eSingleLocker l(m_lock); + + offset = (offset % 188) + (offset * 192) / 188; + + if (offset != m_current_offset) + m_current_offset = lseek_internal(offset, whence); + + return m_current_offset; +} + +off_t eM2TSFile::lseek_internal(off_t offset, int whence) +{ + off_t ret; + + if (!m_cached) + ret = ::lseek(m_fd, offset, whence); + else + { + if (::fseeko(m_file, offset, whence) < 0) + perror("fseeko"); + ret = ::ftello(m_file); + } + return ret <= 0 ? ret : (ret % 192) + (ret*188) / 192; +} + +ssize_t eM2TSFile::read(off_t offset, void *b, size_t count) +{ + eSingleLocker l(m_lock); + unsigned char tmp[192*3]; + unsigned char *buf = (unsigned char*)b; + + size_t rd=0; + offset = (offset % 188) + (offset * 192) / 188; + +sync: + if ((offset+m_sync_offset) != m_current_offset) + { +// eDebug("seekTo %lld", offset+m_sync_offset); + m_current_offset = lseek_internal(offset+m_sync_offset, SEEK_SET); + if (m_current_offset < 0) + return m_current_offset; + } + + while (rd < count) { + size_t ret; + if (!m_cached) + ret = ::read(m_fd, tmp, 192); + else + ret = ::fread(tmp, 1, 192, m_file); + if (ret < 0 || ret < 192) + return rd ? rd : ret; + + if (tmp[4] != 0x47) + { + if (rd > 0) { + eDebug("short read at pos %lld async!!", m_current_offset); + return rd; + } + else { + int x=0; + if (!m_cached) + ret = ::read(m_fd, tmp+192, 384); + else + ret = ::fread(tmp+192, 1, 384, m_file); + +#if 0 + eDebugNoNewLine("m2ts out of sync at pos %lld, real %lld:", offset + m_sync_offset, m_current_offset); + for (; x < 192; ++x) + eDebugNoNewLine(" %02x", tmp[x]); + eDebug(""); + x=0; +#else + eDebug("m2ts out of sync at pos %lld, real %lld", offset + m_sync_offset, m_current_offset); +#endif + for (; x < 192; ++x) + { + if (tmp[x] == 0x47 && tmp[x+192] == 0x47) + { + int add_offs = (x - 4); + eDebug("sync found at pos %d, sync_offset is now %d, old was %d", x, add_offs + m_sync_offset, m_sync_offset); + m_sync_offset += add_offs; + goto sync; + } + } + } + } + + memcpy(buf+rd, tmp+4, 188); + + rd += 188; + m_current_offset += 188; + } + + m_sync_offset %= 188; + + return rd; +} + +int eM2TSFile::valid() +{ + if (!m_cached) + return m_fd != -1; + else + return !!m_file; +} + +off_t eM2TSFile::length() +{ + return m_length; +} + +eServiceFactoryM2TS::eServiceFactoryM2TS() +{ + ePtr sc; + eServiceCenter::getPrivInstance(sc); + if (sc) + { + std::list extensions; + extensions.push_back("m2ts"); + extensions.push_back("mts"); + sc->addServiceFactory(eServiceFactoryM2TS::id, this, extensions); + } +} + +eServiceFactoryM2TS::~eServiceFactoryM2TS() +{ + ePtr sc; + + eServiceCenter::getPrivInstance(sc); + if (sc) + sc->removeServiceFactory(eServiceFactoryM2TS::id); +} + +RESULT eServiceFactoryM2TS::play(const eServiceReference &ref, ePtr &ptr) +{ + ptr = new eServiceM2TS(ref); + return 0; +} + +RESULT eServiceFactoryM2TS::record(const eServiceReference &ref, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryM2TS::list(const eServiceReference &ref, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryM2TS::info(const eServiceReference &ref, ePtr &ptr) +{ + ptr=new eStaticServiceM2TSInformation(ref); + return 0; +} + +RESULT eServiceFactoryM2TS::offlineOperations(const eServiceReference &ref, ePtr &ptr) +{ + ptr = 0; + return -1; +} + +eServiceM2TS::eServiceM2TS(const eServiceReference &ref) + :eDVBServicePlay(ref, NULL) +{ +} + +ePtr eServiceM2TS::createTsSource(eServiceReferenceDVB &ref) +{ + ePtr source = new eM2TSFile(ref.path.c_str()); + return source; +} + +RESULT eServiceM2TS::isCurrentlySeekable() +{ + return 1; // for fast winding we need index files... so only skip forward/backward yet +} + +eAutoInitPtr init_eServiceFactoryM2TS(eAutoInitNumbers::service+1, "eServiceFactoryM2TS"); diff --git a/lib/service/servicem2ts.h b/lib/service/servicem2ts.h new file mode 100644 index 0000000..bfa4f7d --- /dev/null +++ b/lib/service/servicem2ts.h @@ -0,0 +1,33 @@ +#ifndef __servicem2ts_h +#define __servicem2ts_h + +#include + +class eServiceFactoryM2TS: public iServiceHandler +{ + DECLARE_REF(eServiceFactoryM2TS); +public: + eServiceFactoryM2TS(); + virtual ~eServiceFactoryM2TS(); + enum { id = 0x3 }; + + // iServiceHandler + RESULT play(const eServiceReference &, ePtr &ptr); + RESULT record(const eServiceReference &, ePtr &ptr); + RESULT list(const eServiceReference &, ePtr &ptr); + RESULT info(const eServiceReference &, ePtr &ptr); + RESULT offlineOperations(const eServiceReference &, ePtr &ptr); +}; + +class eServiceM2TS: public eDVBServicePlay +{ + friend class eServiceFactoryM2TS; +protected: + eServiceM2TS(const eServiceReference &ref); + ePtr createTsSource(eServiceReferenceDVB &ref); + + // iSeekableService + RESULT isCurrentlySeekable(); +}; + +#endif diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index e453a2b..f96b8c4 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -19,6 +20,9 @@ #include #define HTTP_TIMEOUT 10 +static GstStaticPadTemplate subsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("text/plain; text/x-pango-markup; video/x-dvd-subpicture; subpicture/x-pgs")); +// int ret = gst_pad_set_caps (ghostpad, caps2); +// gst_caps_unref(caps2);)); // eServiceFactoryMP3 @@ -218,6 +222,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_seekTimeout = eTimer::create(eApp); m_subtitle_sync_timer = eTimer::create(eApp); m_streamingsrc_timeout = 0; + m_subtitle_hide_timer = eTimer::create(eApp); m_stream_tags = 0; m_currentAudioStream = -1; m_currentSubtitleStream = 0; @@ -225,8 +230,12 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_currentTrickRatio = 0; m_subs_to_pull = 0; m_buffer_size = 1*1024*1024; + m_prev_decoder_time = -1; + m_decoder_time_valid_state = 0; + CONNECT(m_seekTimeout->timeout, eServiceMP3::seekTimeoutCB); CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles); + CONNECT(m_subtitle_hide_timer->timeout, eServiceMP3::hideSubtitles); CONNECT(m_pump.recv_msg, eServiceMP3::gstPoll); m_aspect = m_width = m_height = m_framerate = m_progressive = -1; @@ -327,23 +336,62 @@ eServiceMP3::eServiceMP3(eServiceReference ref) g_object_set (G_OBJECT (m_gst_playbin), "uri", uri, NULL); - int flags = 0x47; // ( == GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_TEXT ) + int flags = 0x47; // ( GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_TEXT ); g_object_set (G_OBJECT (m_gst_playbin), "flags", flags, NULL); g_free(uri); - GstElement *subsink = gst_element_factory_make("appsink", "subtitle_sink"); - if (!subsink) - eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); - else - { - m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); - g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup"), NULL); - g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); - } - + m_gst_subtitlebin = gst_bin_new("subtitle_bin"); + if ( m_gst_playbin ) { + GstElement *appsink = gst_element_factory_make("appsink", "subtitle_sink"); + + if (!appsink) + eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); + + GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); + if ( dvdsubdec ) + { + gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, NULL); + g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); + } + else + { + eDebug("eServiceMP3::missing gst-plugin-dvdsub, no vob subtitle support!"); + gst_bin_add(GST_BIN(m_gst_subtitlebin), appsink); + } + + GstPadTemplate *templ; + templ = gst_static_pad_template_get (&subsinktemplate); + + GstPad *ghostpad = gst_ghost_pad_new_no_target_from_template("sink", templ); + gst_element_add_pad (m_gst_subtitlebin, ghostpad); + + GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb; subpicture/x-pgs"); + g_object_set (G_OBJECT (appsink), "caps", caps, NULL); + gst_caps_unref(caps); + + g_object_set (G_OBJECT (appsink), "async", FALSE, NULL); + g_object_set (G_OBJECT (appsink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); + g_object_set (G_OBJECT (appsink), "ts-offset", 0 * GST_SECOND, NULL); + + g_object_set_data (G_OBJECT (ghostpad), "application-instance", this); + g_signal_connect (G_OBJECT (ghostpad), "notify::caps", G_CALLBACK (gstGhostpadHasCAPS), this); + gst_pad_set_getcaps_function (ghostpad, gstGhostpadGetCAPS); + gst_pad_set_acceptcaps_function (ghostpad, gstGhostpadAcceptCAPS); + m_ghost_pad_buffer_alloc = GST_PAD_BUFFERALLOCFUNC(ghostpad); + m_ghost_pad_chain_function = GST_PAD_CHAINFUNC(ghostpad); + m_ghost_pad_subtitle_sink_event = GST_PAD_EVENTFUNC(ghostpad); + gst_pad_set_bufferalloc_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadBufferAlloc)); + gst_pad_set_event_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadSinkEvent)); + gst_pad_set_chain_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadChainFunction)); + m_gst_prev_subtitle_caps = gst_caps_new_empty(); + + g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); + m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); + gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), gstBusSyncHandler, this); char srt_filename[strlen(filename)+1]; strncpy(srt_filename,filename,strlen(filename)-3); @@ -380,15 +428,17 @@ eServiceMP3::eServiceMP3(eServiceReference ref) eServiceMP3::~eServiceMP3() { // disconnect subtitle callback - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + + if (appsink) { - g_signal_handler_disconnect (sink, m_subs_to_pull_handler_id); - gst_object_unref(sink); + g_signal_handler_disconnect (appsink, m_subs_to_pull_handler_id); + gst_object_unref(appsink); } delete m_subtitle_widget; + gst_caps_unref(this->m_gst_prev_subtitle_caps); // disconnect sync handler callback gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), NULL, NULL); @@ -442,6 +492,8 @@ RESULT eServiceMP3::stop() if (m_state == stStopped) return -1; + + //GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_playbin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-playbin"); eDebug("eServiceMP3::stop %s", m_ref.path.c_str()); gst_element_set_state(m_gst_playbin, GST_STATE_NULL); @@ -568,6 +620,8 @@ RESULT eServiceMP3::seekTo(pts_t to) if (!(ret = seekToImpl(to))) { m_subtitle_pages.clear(); + m_prev_decoder_time = -1; + m_decoder_time_valid_state = 0; m_subs_to_pull = 0; } } @@ -669,6 +723,7 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts) /* pos is in nanoseconds. we have 90 000 pts per second. */ pts = pos / 11111; +// eDebug("gst_element_query_position %lld pts (%lld ms)", pts, pos/1000000); return 0; } @@ -1111,6 +1166,48 @@ RESULT eServiceMP3::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i) return 0; } +subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL) +{ + subtype_t type = stUnknown; + GstCaps* caps = gst_pad_get_negotiated_caps(pad); + + if ( caps ) + { + GstStructure* str = gst_caps_get_structure(caps, 0); + const gchar *g_type = gst_structure_get_name(str); + eDebug("getSubtitleType::subtitle probe caps type=%s", g_type); + + if ( !strcmp(g_type, "video/x-dvd-subpicture") ) + type = stVOB; + else if ( !strcmp(g_type, "text/x-pango-markup") ) + type = stSSA; + else if ( !strcmp(g_type, "text/plain") ) + type = stPlainText; + else if ( !strcmp(g_type, "subpicture/x-pgs") ) + type = stPGS; + else + eDebug("getSubtitleType::unsupported subtitle caps %s (%s)", g_type, g_codec); + } + else if ( g_codec ) + { + eDebug("getSubtitleType::subtitle probe codec tag=%s", g_codec); + if ( !strcmp(g_codec, "VOB") ) + type = stVOB; + else if ( !strcmp(g_codec, "SubStation Alpha") || !strcmp(g_codec, "SSA") ) + type = stSSA; + else if ( !strcmp(g_codec, "ASS") ) + type = stASS; + else if ( !strcmp(g_codec, "UTF-8 plain text") ) + type = stPlainText; + else + eDebug("getSubtitleType::unsupported subtitle codec %s", g_codec); + } + else + eDebug("getSubtitleType::unidentifiable subtitle stream!"); + + return type; +} + void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) { if (!msg) @@ -1157,16 +1254,16 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) - { - g_object_set (G_OBJECT (sink), "max-buffers", 2, NULL); - g_object_set (G_OBJECT (sink), "sync", FALSE, NULL); - g_object_set (G_OBJECT (sink), "async", FALSE, NULL); - g_object_set (G_OBJECT (sink), "emit-signals", TRUE, NULL); - gst_object_unref(sink); - } + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + if (appsink) + { + g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); + g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL); + g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); + eDebug("eServiceMP3::appsink properties set!"); + gst_object_unref(appsink); + } setAC3Delay(ac3_delay); setPCMDelay(pcm_delay); } break; @@ -1283,7 +1380,6 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) continue; GstStructure* str = gst_caps_get_structure(caps, 0); const gchar *g_type = gst_structure_get_name(str); - eDebug("AUDIO STRUCT=%s", g_type); audio.type = gstCheckAudioPad(str); g_codec = g_strdup(g_type); g_lang = g_strdup_printf ("und"); @@ -1304,25 +1400,30 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } for (i = 0; i < n_text; i++) - { - gchar *g_lang; -// gchar *g_type; -// GstPad* pad = 0; -// g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); -// GstCaps* caps = gst_pad_get_negotiated_caps(pad); -// GstStructure* str = gst_caps_get_structure(caps, 0); -// g_type = gst_structure_get_name(str); -// g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); + { + gchar *g_codec = NULL, *g_lang = NULL; + g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); subtitleStream subs; - subs.type = stPlainText; +// int ret; + g_lang = g_strdup_printf ("und"); if ( tags && gst_is_tag_list(tags) ) + { gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); + gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec); + gst_tag_list_free(tags); + } + subs.language_code = std::string(g_lang); - eDebug("eServiceMP3::subtitle stream=%i language=%s"/* type=%s*/, i, g_lang/*, g_type*/); + eDebug("eServiceMP3::subtitle stream=%i language=%s codec=%s", i, g_lang, g_codec); + + GstPad* pad = 0; + g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); + if ( subs.type != stSRT ) + subs.type = getSubtitleType(pad, g_codec); + m_subtitleStreams.push_back(subs); g_free (g_lang); -// g_free (g_type); } m_event((iPlayableService*)this, evUpdatedEventInfo); break; @@ -1415,7 +1516,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) GstBusSyncReply eServiceMP3::gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data) { eServiceMP3 *_this = (eServiceMP3*)user_data; - _this->m_pump.send(1); + _this->m_pump.send(Message(1)); /* wake */ return GST_BUS_PASS; } @@ -1469,44 +1570,377 @@ audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure) return atUnknown; } -void eServiceMP3::gstPoll(const int &msg) +void eServiceMP3::gstPoll(const Message &msg) { - /* ok, we have a serious problem here. gstBusSyncHandler sends - us the wakup signal, but likely before it was posted. - the usleep, an EVIL HACK (DON'T DO THAT!!!) works around this. - - I need to understand the API a bit more to make this work - proplerly. */ - if (msg == 1) + if (msg.type == 1) { GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)); GstMessage *message; - usleep(1); - while ((message = gst_bus_pop (bus))) + while (message = gst_bus_pop(bus)) { gstBusCall(bus, message); gst_message_unref (message); } } - else + else if (msg.type == 2) pullSubtitle(); + else if (msg.type == 3) + gstGhostpadHasCAPS_synced(msg.d.pad); + else + eDebug("gstPoll unhandled Message %d\n", msg.type); } eAutoInitPtr init_eServiceFactoryMP3(eAutoInitNumbers::service+1, "eServiceFactoryMP3"); void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data) { - eServiceMP3 *_this = (eServiceMP3*)user_data; + eServiceMP3 *_this = (eServiceMP3*)user_data; eSingleLocker l(_this->m_subs_to_pull_lock); ++_this->m_subs_to_pull; - _this->m_pump.send(2); + _this->m_pump.send(Message(2)); +} + +gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event) +{ +// eDebug("eServiceMP3::gstGhostpadSinkEvent %s", gst_structure_get_name (event->structure)); + +// eServiceMP3 *_this = (eServiceMP3*) (gst_pad_get_parent (pad)); + eServiceMP3 *_this = (eServiceMP3*) g_object_get_data (G_OBJECT (pad), "application-instance"); + gboolean ret; + GstFormat format; + + if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB && event->structure && strcmp (gst_structure_get_name (event->structure), "subtitleoverlay-flush-subtitle") == 0) + { + eDebug ("Custom subtitle flush event"); +// GST_SUBTITLE_OVERLAY_LOCK (self); +// self->subtitle_flush = TRUE; +// self->subtitle_error = FALSE; +// if (self->subtitle_block_pad) +// gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, +// _pad_blocked_cb, gst_object_ref (self), +// (GDestroyNotify) gst_object_unref); +// if (self->video_block_pad) +// gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, +// _pad_blocked_cb, gst_object_ref (self), +// (GDestroyNotify) gst_object_unref); +// GST_SUBTITLE_OVERLAY_UNLOCK (self); +// + gst_event_unref (event); + event = NULL; + ret = TRUE; + goto out; + } else if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) + { + gst_event_parse_new_segment_full (event, NULL, NULL, NULL, &format, NULL, NULL, NULL); + if (_this->m_gst_subtitle_segment.format != GST_FORMAT_UNDEFINED && _this->m_gst_subtitle_segment.format != format) + { + eDebug("Subtitle segment format changed: %s -> %s", gst_format_get_name(_this->m_gst_subtitle_segment.format), gst_format_get_name(format)); + gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED); + } + } + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + eDebug("Resetting subtitle segment because of flush-stop"); + gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED); + /* fall through */ + case GST_EVENT_FLUSH_START: + case GST_EVENT_NEWSEGMENT: + case GST_EVENT_EOS: +// eDebug("GST_EVENT_FLUSH_START GST_EVENT_NEWSEGMENT GST_EVENT_EOS"); + /* Add our event marker to make sure no events from here go ever outside + * the element, they're only interesting for our internal elements */ +// event = +// GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST +// (event))); +// if (!event->structure) { +// event->structure = +// gst_structure_id_empty_new (_subtitle_overlay_event_marker_id); +// gst_structure_set_parent_refcount (event->structure, +// &event->mini_object.refcount); +// } +// gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id, +// G_TYPE_BOOLEAN, TRUE, NULL); + break; + default: + eDebug("GST_EVENT_TYPE other: %i", GST_EVENT_TYPE (event)); + break; + } + + ret = _this->m_ghost_pad_subtitle_sink_event (pad, gst_event_ref (event)); +// eDebug("original EVENTFUNC returned %i", ret); + + if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { + gboolean update; + gdouble rate, applied_rate; + gint64 start, stop, position; + + GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT, + event->structure); + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &position); + + GST_DEBUG_OBJECT (pad, "Old subtitle segment: %" GST_SEGMENT_FORMAT, + &_this->m_gst_subtitle_segment); + if (_this->m_gst_subtitle_segment.format != format) { + GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s", + gst_format_get_name (_this->m_gst_subtitle_segment.format), + gst_format_get_name (format)); + gst_segment_init (&_this->m_gst_subtitle_segment, format); + } + + gst_segment_set_newsegment_full (&_this->m_gst_subtitle_segment, update, rate, + applied_rate, format, start, stop, position); + GST_DEBUG_OBJECT (pad, "New subtitle segment: %" GST_SEGMENT_FORMAT, + &_this->m_gst_subtitle_segment); + } + gst_event_unref (event); +// +out: +// gst_object_unref (_this); + return ret; +} + +GstCaps* eServiceMP3::gstGhostpadGetCAPS(GstPad * pad) +{ +// eDebug("eServiceMP3::gstGhostpadGetCAPS"); + return gst_static_pad_template_get_caps(&subsinktemplate); +} + +gboolean eServiceMP3::gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps) +{ + GstCaps *templ_caps = gst_static_pad_template_get_caps (&subsinktemplate); + gboolean ret = gst_caps_can_intersect (templ_caps, caps); + +// eDebug("gstGhostpadAcceptCAPS templ=%s, given=%s ret=%i", gst_caps_to_string(templ_caps), gst_caps_to_string(caps), ret); + gst_caps_unref (templ_caps); + + return ret; +} + +void eServiceMP3::gstGhostpadLink(gpointer user_data, GstCaps * caps) +{ + GstStructure *s; + GstPad *sinkpad; + eServiceMP3 *_this = (eServiceMP3*)user_data; + + // FIXME: Need to cache events from the ghostpad and pass them forward + // now... and keep track of the segment and pass newsegment events + // downstream. + s = gst_caps_get_structure (caps, 0); + + GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); + GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); + + gst_ghost_pad_set_target(GST_GHOST_PAD(ghostpad), NULL); + gst_element_unlink(dvdsubdec, appsink); + int ret = -1; + + if ( gst_structure_has_name (s, "video/x-dvd-subpicture") && dvdsubdec ) + { + sinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); + ret = gst_element_link_pads (dvdsubdec, "src", appsink, "sink"); +// eDebug("gstGhostpadLink:: dvdsubdec+appsink = %i", ret); + } + else + { + sinkpad = gst_element_get_static_pad (appsink, "sink"); +// eDebug("gstGhostpadLink:: appsink"); + } + + gst_ghost_pad_set_target (GST_GHOST_PAD(ghostpad), sinkpad); +} + +GstFlowReturn eServiceMP3::gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf) +{ + eServiceMP3 *_this = (eServiceMP3*) g_object_get_data (G_OBJECT (pad), "application-instance"); + +// eDebug("eServiceMP3::gstGhostpadBufferAlloc prevcaps=%s newcaps=%s", gst_caps_to_string(_this->m_gst_prev_subtitle_caps), gst_caps_to_string(caps)); + if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps)) + gstGhostpadLink (_this, caps); + + return _this->m_ghost_pad_buffer_alloc (pad, offset, size, caps, buf); +} + +void eServiceMP3::gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data) +{ + eServiceMP3 *_this = (eServiceMP3*)user_data; + + gst_object_ref (pad); + + _this->m_pump.send(Message(3, pad)); } +// after messagepump +void eServiceMP3::gstGhostpadHasCAPS_synced(GstPad *pad) +{ + GstCaps *caps; + + g_object_get (G_OBJECT (pad), "caps", &caps, NULL); + +// eDebug("gstGhostpadHasCAPS:: signal::caps = %s", gst_caps_to_string(caps)); + + if (caps) + { + subtitleStream subs; + +// eDebug("gstGhostpadHasCAPS_synced %p %d", pad, m_subtitleStreams.size()); + + if (!m_subtitleStreams.empty()) + subs = m_subtitleStreams[m_currentSubtitleStream]; + else { + subs.type = stUnknown; + subs.pad = pad; + } + + if ( subs.type == stUnknown ) + { + GstTagList *tags; +// eDebug("gstGhostpadHasCAPS::m_subtitleStreams[%i].type == stUnknown...", m_currentSubtitleStream); + + gchar *g_lang; + g_signal_emit_by_name (m_gst_playbin, "get-text-tags", m_currentSubtitleStream, &tags); + + g_lang = g_strdup_printf ("und"); + if ( tags && gst_is_tag_list(tags) ) + gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); + + subs.language_code = std::string(g_lang); + GstPad *ghostpad = gst_element_get_static_pad(m_gst_subtitlebin, "sink"); + subs.type = getSubtitleType(ghostpad); + + if (!m_subtitleStreams.empty()) + m_subtitleStreams[m_currentSubtitleStream] = subs; + else + m_subtitleStreams.push_back(subs); + + g_free (g_lang); + } + +// eDebug("gstGhostpadHasCAPS:: m_gst_prev_subtitle_caps=%s equal=%i",gst_caps_to_string(m_gst_prev_subtitle_caps),gst_caps_is_equal(m_gst_prev_subtitle_caps, caps)); + + if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (m_gst_prev_subtitle_caps, caps)) + gstGhostpadLink(this, caps); + + m_gst_prev_subtitle_caps = gst_caps_copy(caps); + + gst_caps_unref (caps); + } + + gst_object_unref (pad); +} + +GstFlowReturn eServiceMP3::gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + + eServiceMP3 *_this = (eServiceMP3*)g_object_get_data (G_OBJECT (pad), "application-instance"); + +// gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); +// gint64 duration_ns = GST_BUFFER_DURATION(buffer); + size_t len = GST_BUFFER_SIZE(buffer); + + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; +// eDebug("gstGhostpadChainFunction buffer: '%s' caps: %s ", line, gst_caps_to_string(GST_BUFFER_CAPS(buffer))); + + ret = _this->m_ghost_pad_chain_function(pad, buffer); +// eDebug("original chain func returns %i", ret); + return ret; +} + + +// void eServiceMP3::gstCBsubtitleLink(GObject *obj, GParamSpec *pspec, gpointer user_data) +// { +// +// eServiceMP3 *_this = (eServiceMP3*)user_data; +// eDebug("gstCBsubtitleCAPS:: m_currentSubtitleStream=%i, m_subtitleStreams.size()=%i", _this->m_currentSubtitleStream, _this->m_subtitleStreams.size()); +// +// if ( _this->m_currentSubtitleStream >= (int)_this->m_subtitleStreams.size() ) +// { +// eDebug("return invalid stream count"); +// return; +// } +// +// subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream]; +// +// if ( subs.type == stUnknown ) +// { +// GstTagList *tags; +// eDebug("gstCBsubtitleCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); +// +// gchar *g_lang; +// g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->m_currentSubtitleStream, &tags); +// +// g_lang = g_strdup_printf ("und"); +// if ( tags && gst_is_tag_list(tags) ) +// gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); +// subs.language_code = std::string(g_lang); +// +// subs.type = getSubtitleType(GST_PAD(obj)); +// +// _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs; +// +// g_free (g_lang); +// } +// +// gstCBsubtitleLink(subs.type, _this); +// } + +// void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) +// { +// eServiceMP3 *_this = (eServiceMP3*)user_data; +// +// if ( type == stVOB ) +// { +// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); +// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); +// GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); +// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); +// ret += gst_element_link(dvdsubdec, appsink); +// eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, set target & link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); +// } +// else if ( type < stVOB && type > stUnknown ) +// { +// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); +// GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink"); +// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); +// gst_element_unlink(dvdsubdec, appsink); +// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); +// eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, set target=%i", appsink, appsinkpad, ghostpad, ret); +// } +// else +// { +// eDebug("gstCBsubtitleLink:: unsupported subtitles"); +// } +// } +/* +gboolean eServiceMP3::gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data) +{ + eDebug("gstCBsubtitleDrop"); + + gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); + gint64 duration_ns = GST_BUFFER_DURATION(buffer); + size_t len = GST_BUFFER_SIZE(buffer); + + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; + eDebug("dropping buffer '%s' ", line); + return false; +}*/ + + void eServiceMP3::pullSubtitle() { - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + + if (appsink) { while (m_subs_to_pull && m_subtitle_pages.size() < 2) { @@ -1514,28 +1948,55 @@ void eServiceMP3::pullSubtitle() { eSingleLocker l(m_subs_to_pull_lock); --m_subs_to_pull; - g_signal_emit_by_name (sink, "pull-buffer", &buffer); + g_signal_emit_by_name (appsink, "pull-buffer", &buffer); } if (buffer) { gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); gint64 duration_ns = GST_BUFFER_DURATION(buffer); size_t len = GST_BUFFER_SIZE(buffer); - unsigned char line[len+1]; - memcpy(line, GST_BUFFER_DATA(buffer), len); - line[len] = 0; - eDebug("got new subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); - ePangoSubtitlePage page; - gRGB rgbcol(0xD0,0xD0,0xD0); - page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); - page.show_pts = buf_pos / 11111L; - page.m_timeout = duration_ns / 1000000; - m_subtitle_pages.push_back(page); - pushSubtitles(); + eDebug("pullSubtitle m_subtitleStreams[m_currentSubtitleStream].type=%i",m_subtitleStreams[m_currentSubtitleStream].type); + + if ( m_subtitleStreams[m_currentSubtitleStream].type ) + { + if ( m_subtitleStreams[m_currentSubtitleStream].type < stVOB ) + { + unsigned char line[len+1]; + SubtitlePage page; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; + eDebug("got new text subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); + gRGB rgbcol(0xD0,0xD0,0xD0); + page.type = SubtitlePage::Pango; + page.pango_page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); + page.pango_page.m_show_pts = buf_pos / 11111L; + page.pango_page.m_timeout = duration_ns / 1000000; + m_subtitle_pages.push_back(page); + if (m_subtitle_pages.size()==1) + pushSubtitles(); + } + else if ( m_subtitleStreams[m_currentSubtitleStream].type == stVOB ) + { + SubtitlePage page; + eDebug("got new subpicture @ buf_pos = %lld ns (in pts=%lld), duration=%lld ns, len=%i bytes. ", buf_pos, buf_pos/11111, duration_ns, len); + page.type = SubtitlePage::Vob; + page.vob_page.m_pixmap = new gPixmap(eSize(720, 576), 32, 1); + memcpy(page.vob_page.m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); + page.vob_page.m_show_pts = buf_pos / 11111L; + page.vob_page.m_timeout = duration_ns / 1000; + m_subtitle_pages.push_back(page); + if (m_subtitle_pages.size()==1) + pushSubtitles(); + } + else + { + eDebug("unsupported subpicture... ignoring"); + } + } gst_buffer_unref(buffer); } } - gst_object_unref(sink); + gst_object_unref(appsink); } else eDebug("no subtitle sink!"); @@ -1543,45 +2004,64 @@ void eServiceMP3::pullSubtitle() void eServiceMP3::pushSubtitles() { - ePangoSubtitlePage page; - pts_t running_pts; while ( !m_subtitle_pages.empty() ) { + SubtitlePage &frontpage = m_subtitle_pages.front(); + pts_t running_pts; + gint64 diff_ms = 0; + gint64 show_pts; + getPlayPosition(running_pts); - page = m_subtitle_pages.front(); - gint64 diff_ms = ( page.show_pts - running_pts ) / 90; - eDebug("eServiceMP3::pushSubtitles show_pts = %lld running_pts = %lld diff = %lld", page.show_pts, running_pts, diff_ms); - if (diff_ms < -100) - { - GstFormat fmt = GST_FORMAT_TIME; - gint64 now; - if (gst_element_query_position(m_gst_playbin, &fmt, &now) != -1) - { - now /= 11111; - diff_ms = abs((now - running_pts) / 90); - eDebug("diff < -100ms check decoder/pipeline diff: decoder: %lld, pipeline: %lld, diff: %lld", running_pts, now, diff_ms); - if (diff_ms > 100000) - { - eDebug("high decoder/pipeline difference.. assume decoder has now started yet.. check again in 1sec"); - m_subtitle_sync_timer->start(1000, true); - break; - } + + if (m_decoder_time_valid_state < 4) { + ++m_decoder_time_valid_state; + if (m_prev_decoder_time == running_pts) + m_decoder_time_valid_state = 0; + if (m_decoder_time_valid_state < 4) { +// if (m_decoder_time_valid_state) +// eDebug("%d: decoder time not valid! prev %lld, now %lld\n", m_decoder_time_valid_state, m_prev_decoder_time/90, running_pts/90); +// else +// eDebug("%d: decoder time not valid! now %lld\n", m_decoder_time_valid_state, running_pts/90); + m_subtitle_sync_timer->start(25, true); + m_prev_decoder_time = running_pts; + break; } - else - eDebug("query position for decoder/pipeline check failed!"); - eDebug("subtitle to late... drop"); + } + + if (frontpage.type == SubtitlePage::Pango) + show_pts = frontpage.pango_page.m_show_pts; + else + show_pts = frontpage.vob_page.m_show_pts; + + diff_ms = ( show_pts - running_pts ) / 90; + eDebug("check subtitle: decoder: %lld, show_pts: %lld, diff: %lld ms", running_pts/90, show_pts/90, diff_ms); + + if ( diff_ms < -100 ) + { + eDebug("subtitle too late... drop"); m_subtitle_pages.pop_front(); } else if ( diff_ms > 20 ) { -// eDebug("start recheck timer"); - m_subtitle_sync_timer->start(diff_ms > 1000 ? 1000 : diff_ms, true); + eDebug("start timer"); + m_subtitle_sync_timer->start(diff_ms, true); break; } else // immediate show { - if (m_subtitle_widget) - m_subtitle_widget->setPage(page); + if ( m_subtitle_widget ) + { + eDebug("show!\n"); + if ( frontpage.type == SubtitlePage::Pango) + m_subtitle_widget->setPage(frontpage.pango_page); + else + { + m_subtitle_widget->setPixmap(frontpage.vob_page.m_pixmap, eRect(0, 0, 720, 576)); + eDebug("blit vobsub pixmap... hide in %i ms", frontpage.vob_page.m_timeout); + m_subtitle_hide_timer->start(frontpage.vob_page.m_timeout, true); + } + m_subtitle_widget->show(); + } m_subtitle_pages.pop_front(); } } @@ -1589,12 +2069,26 @@ void eServiceMP3::pushSubtitles() pullSubtitle(); } +void eServiceMP3::hideSubtitles() +{ +// eDebug("eServiceMP3::hideSubtitles()"); + if ( m_subtitle_widget ) + m_subtitle_widget->hide(); +} + RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) { +// eDebug ("eServiceMP3::enableSubtitles m_currentSubtitleStream=%i this=%p",m_currentSubtitleStream, this); ePyObject entry; int tuplesize = PyTuple_Size(tuple); int pid, type; gint text_pid = 0; + eSingleLocker l(m_subs_to_pull_lock); + +// GstPad *pad = 0; +// g_signal_emit_by_name (m_gst_playbin, "get-text-pad", m_currentSubtitleStream, &pad); +// gst_element_get_static_pad(m_gst_subtitlebin, "sink"); +// gulong subprobe_handler_id = gst_pad_add_buffer_probe (pad, G_CALLBACK (gstCBsubtitleDrop), NULL); if (!PyTuple_Check(tuple)) goto error_out; @@ -1609,12 +2103,14 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) goto error_out; type = PyInt_AsLong(entry); +// eDebug ("eServiceMP3::enableSubtitles new pid=%i",pid); if (m_currentSubtitleStream != pid) { - eSingleLocker l(m_subs_to_pull_lock); g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL); +// eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid); m_currentSubtitleStream = pid; m_subs_to_pull = 0; + m_prev_decoder_time = -1; m_subtitle_pages.clear(); } @@ -1625,6 +2121,9 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) g_object_get (G_OBJECT (m_gst_playbin), "current-text", &text_pid, NULL); eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid); +// gst_pad_remove_buffer_probe (pad, subprobe_handler_id); + + m_event((iPlayableService*)this, evUpdatedInfo); return 0; @@ -1651,26 +2150,25 @@ PyObject *eServiceMP3::getCachedSubtitle() PyObject *eServiceMP3::getSubtitleList() { - eDebug("eServiceMP3::getSubtitleList"); - +// eDebug("eServiceMP3::getSubtitleList"); ePyObject l = PyList_New(0); - int stream_count[sizeof(subtype_t)]; - for ( unsigned int i = 0; i < sizeof(subtype_t); i++ ) - stream_count[i] = 0; - + int stream_idx = 0; + for (std::vector::iterator IterSubtitleStream(m_subtitleStreams.begin()); IterSubtitleStream != m_subtitleStreams.end(); ++IterSubtitleStream) { subtype_t type = IterSubtitleStream->type; ePyObject tuple = PyTuple_New(5); +// eDebug("eServiceMP3::getSubtitleList idx=%i type=%i, code=%s", stream_idx, int(type), (IterSubtitleStream->language_code).c_str()); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2)); - PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(stream_count[type])); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(stream_idx)); PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(int(type))); PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(0)); PyTuple_SET_ITEM(tuple, 4, PyString_FromString((IterSubtitleStream->language_code).c_str())); PyList_Append(l, tuple); Py_DECREF(tuple); - stream_count[type]++; + stream_idx++; } + eDebug("eServiceMP3::getSubtitleList finished"); return l; } diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index d54997a..c620151 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -46,7 +46,7 @@ public: typedef struct _GstElement GstElement; typedef enum { atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC } audiotype_t; -typedef enum { stPlainText, stSSA, stSRT } subtype_t; +typedef enum { stUnknown, stPlainText, stSSA, stASS, stSRT, stVOB, stPGS } subtype_t; typedef enum { ctNone, ctMPEGTS, ctMPEGPS, ctMKV, ctAVI, ctMP4, ctVCD, ctCDA } containertype_t; class eServiceMP3: public iPlayableService, public iPauseableService, @@ -197,24 +197,74 @@ private: }; int m_state; GstElement *m_gst_playbin; + GstElement *m_gst_subtitlebin; GstTagList *m_stream_tags; - eFixedMessagePump m_pump; + + struct Message + { + Message() + :type(-1) + {} + Message(int type) + :type(type) + {} + Message(int type, GstPad *pad) + :type(type) + { + d.pad=pad; + } + + int type; + union { + GstPad *pad; // for msg type 3 + } d; + }; + + eFixedMessagePump m_pump; std::string m_error_message; audiotype_t gstCheckAudioPad(GstStructure* structure); void gstBusCall(GstBus *bus, GstMessage *msg); static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data); - static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); - GstPad* gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type); - void gstPoll(const int&); static void gstHTTPSourceSetAgent(GObject *source, GParamSpec *unused, gpointer user_data); + static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); + static GstCaps* gstGhostpadGetCAPS (GstPad * pad); + static gboolean gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps); + static void gstGhostpadLink(gpointer user_data, GstCaps * caps); + static GstFlowReturn gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf); + static void gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data); + static gboolean gstGhostpadSinkEvent(GstPad * pad, GstEvent * event); + static GstFlowReturn gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer); +/* static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); + static void gstCBsubtitleLink(subtype_t type, gpointer user_data); + static gboolean gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data);*/ + void gstPoll(const Message&); + void gstGhostpadHasCAPS_synced(GstPad *pad); + + GstPadBufferAllocFunction m_ghost_pad_buffer_alloc; + GstPadChainFunction m_ghost_pad_chain_function; + GstPadEventFunction m_ghost_pad_subtitle_sink_event; + GstCaps *m_gst_prev_subtitle_caps; + GstSegment m_gst_subtitle_segment; + GstPadEventFunction m_gst_sink_event; - std::list m_subtitle_pages; + struct SubtitlePage + { + enum { Unknown, Pango, Vob } type; + ePangoSubtitlePage pango_page; + eVobSubtitlePage vob_page; + }; + + std::list m_subtitle_pages; ePtr m_subtitle_sync_timer; - + ePtr m_subtitle_hide_timer; ePtr m_streamingsrc_timeout; + pts_t m_prev_decoder_time; + int m_decoder_time_valid_state; + void pushSubtitles(); void pullSubtitle(); + void hideSubtitles(); void sourceTimeout(); int m_subs_to_pull; sourceStream m_sourceinfo; diff --git a/main/enigma.cpp b/main/enigma.cpp index 1cdd867..91645d8 100644 --- a/main/enigma.cpp +++ b/main/enigma.cpp @@ -251,8 +251,9 @@ int main(int argc, char **argv) { gPainter p(my_lcd_dc); - p.resetClip(eRect(0, 0, 132, 64)); + p.resetClip(eRect(ePoint(0, 0), my_lcd_dc->size())); p.clear(); + p.flush(); } return exit_code; diff --git a/po/ar.po b/po/ar.po index a560b90..2f6ebf5 100755 --- a/po/ar.po +++ b/po/ar.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-08-20 00:08+0200\n" "Last-Translator: Hazem \n" "Language-Team: Arabic \n" @@ -4336,6 +4336,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/ca.po b/po/ca.po index b214073..ed5e7b1 100755 --- a/po/ca.po +++ b/po/ca.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ca\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2007-08-14 10:23+0200\n" "Last-Translator: Oriol Pellicer \n" "Language-Team: \n" @@ -4741,6 +4741,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/cs.po b/po/cs.po index 5b6da82..9c492d6 100755 --- a/po/cs.po +++ b/po/cs.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2008-09-28 18:09+0100\n" "Last-Translator: ws79 \n" "Language-Team: \n" @@ -4740,6 +4740,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/da.po b/po/da.po index 5a8c2f2..266b005 100755 --- a/po/da.po +++ b/po/da.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Enigma2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-04-13 21:10+0200\n" "Last-Translator: Ingmar \n" "Language-Team: jazzydane \n" @@ -4804,6 +4804,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/de.po b/po/de.po index ea948b5..49fe3d8 100755 --- a/po/de.po +++ b/po/de.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-11-01 14:20+0100\n" "Last-Translator: Mladen Horvat \n" "Language-Team: none\n" @@ -4935,6 +4935,9 @@ msgstr "Leute & Blogs" msgid "PermanentClock shows the clock permanently on the screen." msgstr "PermanentClock zeigt die Uhrzeit permanent auf Ihrem Fernseher an." +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "Tiere" diff --git a/po/el.po b/po/el.po index f18ce12..92b1125 100755 --- a/po/el.po +++ b/po/el.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2008-07-17 12:13+0100\n" "Last-Translator: \n" "Language-Team: \n" @@ -4747,6 +4747,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/en.po b/po/en.po index fb3e76c..e4dc8ed 100755 --- a/po/en.po +++ b/po/en.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2005-11-17 20:53+0100\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -4855,6 +4855,9 @@ msgstr "People & Blogs" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "Pets & Animals" diff --git a/po/es.po b/po/es.po index 165d285..c80f022 100755 --- a/po/es.po +++ b/po/es.po @@ -7,14 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" -"PO-Revision-Date: 2009-08-21 18:08+0100\n" -"Last-Translator: José Juan Zapater \n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" +"PO-Revision-Date: 2011-02-01 00:10+0200\n" +"Last-Translator: Jose Juan \n" "Language-Team: none\n" +"Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Pootle 2.0.3\n" "X-Poedit-Language: Spanish\n" "X-Poedit-SourceCharset: iso-8859-1\n" "X-Poedit-Country: SPAIN\n" @@ -137,16 +139,15 @@ msgstr "" msgid " " msgstr " " -# msgid " Results" -msgstr "" +msgstr "Resultados" # msgid " extensions." msgstr "extensiones." msgid " ms" -msgstr "" +msgstr "ms" # msgid " packages selected." @@ -223,10 +224,9 @@ msgstr "¡%d canales encontrados!" msgid "%d.%B %Y" msgstr "%d/%B/%Y" -# #, python-format msgid "%i ms" -msgstr "" +msgstr "%i ms" # #, python-format @@ -399,16 +399,16 @@ msgid "A" msgstr "A" msgid "A BackToTheRoots-Skin .. or good old times." -msgstr "" +msgstr "Una Piel BackToTheRoots .. or buenos momentos antiguos" msgid "A BackToTheRoots-Skin ... or good old times." -msgstr "" +msgstr "Una Piel BackToTheRoots ... o buenos momentos anteriores" msgid "A basic ftp client" -msgstr "" +msgstr "Un cliente ftp básico" msgid "A client for www.dyndns.org" -msgstr "" +msgstr "Un cliente para www.dyndns.org" # #, python-format @@ -420,7 +420,7 @@ msgstr "" "¿Quiere conservar su versión?" msgid "A demo plugin for TPM usage." -msgstr "" +msgstr "Un plugin de demo para el uso de TPM" # msgid "" @@ -443,25 +443,26 @@ msgid "A graphical EPG for all services of an specific bouquet" msgstr "Un EPG gráfico para todos los canales de una lista específica" msgid "A graphical EPG interface" -msgstr "" +msgstr "Un interfaz EPG gráfico" msgid "A graphical EPG interface." -msgstr "" +msgstr "Un interfaz EPG gráfico." -# msgid "" "A mount entry with this name already exists!\n" "Update existing entry and continue?\n" msgstr "" +"¡Ya existe un punto de montaje con ese nombre!\n" +"¿Actualizar el existente y continuar?\n" msgid "A nice looking HD skin from Kerni" -msgstr "" +msgstr "Una bonita piel HD de Kerni" msgid "A nice looking HD skin in Brushed Alu Design from Kerni." -msgstr "" +msgstr "Una bonita piel HD en diseño aluminio depillado." msgid "A nice looking skin from Kerni" -msgstr "" +msgstr "Una bonita piel de Kerni" # #, python-format @@ -516,7 +517,7 @@ msgstr "" "¿Quiere desabilitar el segundo interface de red?" msgid "A simple downloading application for other plugins" -msgstr "" +msgstr "Una aplicación simple de descargas para otros plugins" # msgid "" @@ -583,10 +584,10 @@ msgid "About..." msgstr "Acerca de..." msgid "Access to the ARD-Mediathek" -msgstr "" +msgstr "Acceso al ARD-Mediathek" msgid "Access to the ARD-Mediathek online video database." -msgstr "" +msgstr "Acceso a la base de datos de video online de ARD-Mediathek." # msgid "Accesspoint:" @@ -596,9 +597,8 @@ msgstr "Punto de Acceso:" msgid "Action on long powerbutton press" msgstr "Acción dejando pulsado el encendido" -# msgid "Action on short powerbutton press" -msgstr "" +msgstr "Acción al pulsar poco rato el botón de power" # msgid "Action:" @@ -612,15 +612,15 @@ msgstr "Activar PiP" msgid "Activate network settings" msgstr "Activar configuración de red" -# msgid "Active" -msgstr "" +msgstr "Activo" -# msgid "" "Active/\n" "Inactive" msgstr "" +"Activo/\n" +"Inactivo" # msgid "Adapter settings" @@ -642,9 +642,8 @@ msgstr "¿Añadir configuración WLAN?" msgid "Add a mark" msgstr "Añadir marca" -# msgid "Add a new NFS or CIFS mount point to your Dreambox." -msgstr "" +msgstr "Añadir a tu Dreambox un punto de montaje NFS o CIFS" # msgid "Add a new title" @@ -658,9 +657,8 @@ msgstr "¿Añadir configuración de red?" msgid "Add new AutoTimer" msgstr "Añadir nueva AutoProgramación" -# msgid "Add new network mount point" -msgstr "" +msgstr "Añadir un nuevo punto de montaje de red" # msgid "Add timer" @@ -682,13 +680,11 @@ msgstr "Añadir a la lista" msgid "Add to favourites" msgstr "Añadir a favoritos" -# msgid "Add zap timer instead of record timer?" -msgstr "" +msgstr "¿Añadir programación de zapeo en lugar de grabación?" -# msgid "Added: " -msgstr "" +msgstr "Añadido:" # msgid "" @@ -719,10 +715,10 @@ msgstr "" "use una tecla numérica para seleccionar otras pantallas de test." msgid "Adult streaming plugin" -msgstr "" +msgstr "Plugin de streaming adulto" msgid "Adult streaming plugin." -msgstr "" +msgstr "Plugin de streaming adulto." # msgid "Advanced Options" @@ -752,6 +748,8 @@ msgid "" "After a reboot or power outage, StartupToStandby will bring your Dreambox to " "standby-mode." msgstr "" +"Después de un reinicio o un fallo de corriente, IniciarAReposo te llevará el " +"Dreambox al modo reposo." # msgid "After event" @@ -766,7 +764,7 @@ msgstr "" "individualmente. Mire el manual de su dreambox para saber cómo." msgid "Ai.HD skin-style control plugin" -msgstr "" +msgstr "Plugin para controlar el estilo de la piel Ai.HD" # msgid "Album" @@ -780,9 +778,8 @@ msgstr "Todo" msgid "All Satellites" msgstr "Todos satélites" -# msgid "All Time" -msgstr "" +msgstr "Todo el Tiempo" # msgid "All non-repeating timers" @@ -793,10 +790,10 @@ msgid "Allow zapping via Webinterface" msgstr "Permitir zapear via interface web" msgid "Allows the execution of TuxboxPlugins." -msgstr "" +msgstr "Permite la ejecución del TuxboxPlugins." msgid "Allows user to download files from rapidshare in the background." -msgstr "" +msgstr "Permite al usuario descargar ficheros de rapidshare en segundo plano." # msgid "Alpha" @@ -811,7 +808,7 @@ msgid "Alternative services tuner priority" msgstr "Prioridad de sintonizadores alternativa" msgid "Always ask" -msgstr "" +msgstr "Preguntar siempre" # msgid "Always ask before sending" @@ -825,9 +822,8 @@ msgstr "Cantidad de grabaciones que quedan" msgid "An empty filename is illegal." msgstr "Un nombre de fichero vacío es ilegal." -# msgid "An error occured." -msgstr "" +msgstr "Ha ocurrido un error." # msgid "An unknown error occured!" @@ -885,19 +881,19 @@ msgstr "" "¿Está seguro que quiere restaurar su backup Enigma2?Enigma2 reiniciará " "después de restaurar" -# msgid "" "Are you sure you want to save this network mount?\n" "\n" msgstr "" +"¿Está seguro que quiere guardar este montaje de red?\n" +"\n" # msgid "Artist" msgstr "Artista" -# msgid "Ascending" -msgstr "" +msgstr "Ascendente" # msgid "Ask before shutdown:" @@ -912,10 +908,10 @@ msgid "Aspect Ratio" msgstr "Relación de aspecto" msgid "Assigning providers/services/caids to a CI module" -msgstr "" +msgstr "Asignando proveedores/servicios/caids al módulo CI" msgid "Atheros" -msgstr "" +msgstr "Atheros" # msgid "Audio" @@ -925,22 +921,21 @@ msgstr "Sonido" msgid "Audio Options..." msgstr "Opciones de sonido..." -# msgid "Audio Sync" -msgstr "" +msgstr "Sincronización de audio" -# msgid "Audio Sync Setup" -msgstr "" +msgstr "Configuración de sincronización de audio" msgid "" "AudoSync allows delaying the sound output (Bitstream/PCM) so that it is " "synchronous to the picture." msgstr "" +"Sincronización de audio permite retrasar la salida de audio (Bitstream/PCM), " +"para que así se sincronize con la imagen." -# msgid "Australia" -msgstr "" +msgstr "Australia" # msgid "Author: " @@ -990,6 +985,8 @@ msgid "" "AutoTimer scans the EPG and creates Timers depending on user-defined search " "criteria." msgstr "" +"AutoProgramación escanea el EPG y crea Programaciones dependiendo del " +"criterio de búsqueda definido por el usuario." # msgid "Automatic" @@ -1000,34 +997,35 @@ msgid "Automatic Scan" msgstr "Búsqueda automática" msgid "Automatic volume adjustment" -msgstr "" +msgstr "Ajuste de volumen automático" msgid "Automatic volume adjustment for ac3/dts services." -msgstr "" +msgstr "Ajuste de volumen automático para canales ac3/dts." msgid "Automatically change video resolution" -msgstr "" +msgstr "Cambiar la resolución de video automáticamente" msgid "" "Automatically changes the output resolution depending on the video " "resolution you are watching." msgstr "" +"Cambiar la resolución de salida automáticamente dependiendo de la resolución " +"que está viendo." msgid "Automatically create timer events based on keywords" -msgstr "" +msgstr "Crear programaciones automáticamente basadas en palabras" msgid "Automatically informs you on low internal memory" -msgstr "" +msgstr "Informar automáticamente de memoria baja" msgid "Automatically refresh EPG" -msgstr "" +msgstr "Refrescar automáticamente el EPG" msgid "Automatically send crashlogs to Dream Multimedia" -msgstr "" +msgstr "Enviar automáticamente a Dream Multimedia los logs de fallos" -# msgid "Autos & Vehicles" -msgstr "" +msgstr "Coches" # msgid "Autowrite timer" @@ -1046,10 +1044,10 @@ msgid "BA" msgstr "BA" msgid "BASIC-HD Skin by Ismail Demir" -msgstr "" +msgstr "Piel BASIC-HD por Ismail Demir" msgid "BASIC-HD Skin for Dreambox Images created from Ismail Demir" -msgstr "" +msgstr "Piel BASIC-HD para images Dreambox creada por Ismail Demir" # msgid "BB" @@ -1140,10 +1138,10 @@ msgid "Blue boost" msgstr "Impulso azul" msgid "Bonjour/Avahi control plugin" -msgstr "" +msgstr "plugin de control Bonjour/Avahi" msgid "Bonjour/Avahi control plugin." -msgstr "" +msgstr "plugin de control Bonjour/Avahi." # msgid "Bookmarks" @@ -1153,23 +1151,21 @@ msgstr "Marcadores" msgid "Bouquets" msgstr "Listas" -# msgid "Brazil" -msgstr "" +msgstr "Brasil" # msgid "Brightness" msgstr "Brillo" msgid "Browse for and connect to network shares" -msgstr "" +msgstr "Examinar y conectar a carpetas de red" msgid "Browse for nfs/cifs shares and connect to them." -msgstr "" +msgstr "Examinar y conectar a carpetas nfs/cifs compartidas." -# msgid "Browse network neighbourhood" -msgstr "" +msgstr "Examinar la red próxima" # msgid "Burn DVD" @@ -1179,13 +1175,11 @@ msgstr "Grabar DVD" msgid "Burn existing image to DVD" msgstr "Graba una imagen existente a DVD" -# -#, fuzzy msgid "Burn to DVD" msgstr "Grabar a DVD..." msgid "Burn your recordings to DVD" -msgstr "" +msgstr "Grabar sus grabaciones a DVD" # msgid "Bus: " @@ -1206,22 +1200,22 @@ msgstr "C" msgid "C-Band" msgstr "Banda-C" -#, fuzzy msgid "CDInfo" -msgstr "Info" +msgstr "CDInfo" msgid "" "CDInfo enables gathering album and track details from CDDB and CD-Text when " "playing Audio CDs in Mediaplayer." msgstr "" +"CDInfo habilita la información de los detalles del álbum y pista desde CDDB " +"y CD-Text cuando se reproducen los CDs de audio en el reproductor de medios." # msgid "CI assignment" msgstr "Asignación CI" -# msgid "CIFS share" -msgstr "" +msgstr "compartir CIFS" # msgid "CVBS" @@ -1236,18 +1230,16 @@ msgid "Cache Thumbnails" msgstr "Cache de Miniaturas" msgid "Callmonitor for NCID-based call notification" -msgstr "" +msgstr "Notificación de llamada NCID" msgid "Callmonitor for the Fritz!Box routers" -msgstr "" +msgstr "Monitor de llamada para los routers Fritz!Box" -#, fuzzy msgid "Can't connect to server. Please check your network!" msgstr "Por favor, ¡chequee su configuración de red!" -# msgid "Canada" -msgstr "" +msgstr "Canadá" # msgid "Cancel" @@ -1265,53 +1257,47 @@ msgstr "Tarjeta" msgid "Catalan" msgstr "Catalán" -# msgid "Center screen at the lower border" -msgstr "" +msgstr "Centrar la pantalla al borde inferior" -# msgid "Center screen at the upper border" -msgstr "" +msgstr "Centrar la pantalla al borde superior" -# msgid "Change active delay" -msgstr "" +msgstr "Cambiar el retardo activo" # msgid "Change bouquets in quickzap" msgstr "Cambiar de lista en zapin rápido" -# msgid "Change default recording offset?" -msgstr "" +msgstr "¿Quiere cambiar el retardo de grabación por defecto?" -# msgid "Change hostname" -msgstr "" +msgstr "Cambiar el nombre de la máquina" # msgid "Change pin code" msgstr "Cambiar código pin" msgid "Change service PIN" -msgstr "" +msgstr "Cambiar el PIN de servicio" msgid "Change service PINs" -msgstr "" +msgstr "Cambiar los PINs de servicio" msgid "Change setup PIN" -msgstr "" +msgstr "Cambiar el PIN de configuración" # msgid "Change step size" msgstr "Cambiar tamaño" -# msgid "Change the hostname of your Dreambox." -msgstr "" +msgstr "Cambiar el nombre de la máquina de su Dreambox." msgid "Changelog" -msgstr "" +msgstr "Novedades" # msgid "Channel" @@ -1321,9 +1307,8 @@ msgstr "Canal" msgid "Channel Selection" msgstr "Selección de Canal" -# msgid "Channel audio:" -msgstr "" +msgstr "Canal de audio:" # msgid "Channel not in services list" @@ -1382,7 +1367,7 @@ msgid "Choose bouquet" msgstr "Elegir lista" msgid "Choose image to download" -msgstr "" +msgstr "Elegir imagen para descargar" # msgid "Choose target folder" @@ -1421,10 +1406,10 @@ msgid "Cleanup Wizard settings" msgstr "Configuración de Asistente de limpieza" msgid "Cleanup timerlist automatically" -msgstr "" +msgstr "Limpiar la lista de programaciones automáticamente" msgid "Cleanup timerlist automatically." -msgstr "" +msgstr "Limpiar la lista de programaciones automáticamente." # msgid "CleanupWizard" @@ -1434,9 +1419,8 @@ msgstr "LimpiarAsistente" msgid "Clear before scan" msgstr "Limpiar antes de buscar" -# msgid "Clear history on Exit:" -msgstr "" +msgstr "Limpiar la historia al Salir:" # msgid "Clear log" @@ -1486,9 +1470,8 @@ msgstr "Configuración de la colección" msgid "Color Format" msgstr "Formato de Color" -# msgid "Comedy" -msgstr "" +msgstr "Comedia" # msgid "Command execution..." @@ -1531,7 +1514,7 @@ msgid "Complex (allows mixing audio tracks and aspects)" msgstr "Complejo (permite mexclar pistas de audio y aspectos)" msgid "Composition of the recording filenames" -msgstr "" +msgstr "Composición de los nombre de ficheros de grabación" # msgid "Configuration Mode" @@ -1554,7 +1537,7 @@ msgid "Configure nameservers" msgstr "Configurar DNSs" msgid "Configure your WLAN network interface" -msgstr "" +msgstr "Configurar el interfaz de la red WLAN" # msgid "Configure your internal LAN" @@ -1617,28 +1600,28 @@ msgid "Contrast" msgstr "Contraste" msgid "Control your Dreambox with your Web browser." -msgstr "" +msgstr "Controlar su Dreambox con su navegador Web." msgid "Control your Dreambox with your browser" -msgstr "" +msgstr "Controlar su Dreambox con su navegador" msgid "Control your dreambox with only the MUTE button" -msgstr "" +msgstr "Controla su dreambox con sólo su botón MUTE" msgid "Control your dreambox with only the MUTE button." -msgstr "" +msgstr "Controlar su dreambox con sólo su botón MUTE." msgid "Control your internal system fan." -msgstr "" +msgstr "Controlar el ventilador interno del sistema." msgid "Control your kids's tv usage" -msgstr "" +msgstr "Controlar el uso de la tv por los niños" msgid "Control your system fan" -msgstr "" +msgstr "Controlar el ventilador del sistema" msgid "Copy, rename, delete, move local files on your Dreambox." -msgstr "" +msgstr "Copiar, renombrar, borrar, mover ficheros locales en su Dreambox." # msgid "Could not connect to Dreambox .NFI Image Feed Server:" @@ -1686,10 +1669,10 @@ msgid "Create DVD-ISO" msgstr "Crear DVD-ISO" msgid "Create a backup of your Video DVD on your DreamBox hard drive." -msgstr "" +msgstr "Crear una copia de su DVD en su disco duro de su Dreambox." msgid "Create a backup of your Video-DVD" -msgstr "" +msgstr "Crear una copia de su DVD-Video" # msgid "Create a new AutoTimer." @@ -1708,13 +1691,13 @@ msgid "Create movie folder failed" msgstr "Falló la creación de la carpeta de películas" msgid "Create preview pictures of your Movies" -msgstr "" +msgstr "Crear imágenes de previsualización de sus Películas" msgid "Create remote timers" -msgstr "" +msgstr "Crear programaciones remotas" msgid "Create timers on remote Dreamboxes." -msgstr "" +msgstr "Crear programaciones en sus Dreamboxes remotos." # #, python-format @@ -1734,7 +1717,7 @@ msgid "Current Transponder" msgstr "Transponder actual" msgid "Current device: " -msgstr "" +msgstr "Dispositivo actual:" # msgid "Current settings:" @@ -1749,7 +1732,7 @@ msgid "Current version:" msgstr "Versión actual:" msgid "Currently installed image" -msgstr "" +msgstr "Imagen actualmente instalada" # #, python-format @@ -1781,23 +1764,23 @@ msgid "Customize" msgstr "Configurar" msgid "Customize Vali-XD skins" -msgstr "" +msgstr "Pieles por Vali-XD" msgid "Customize Vali-XD skins by yourself." -msgstr "" +msgstr "Personalizar pieles Vali-XD por si mismo." # msgid "Cut" msgstr "Cortar" msgid "Cut your movies" -msgstr "" +msgstr "Recortar sus películas" msgid "Cut your movies." -msgstr "" +msgstr "Recortar sus películas." msgid "CutListEditor allows you to edit your movies" -msgstr "" +msgstr "CutListEditor permite editar sus películas" msgid "" "CutListEditor allows you to edit your movies.\n" @@ -1805,6 +1788,10 @@ msgid "" "cut'.\n" "Then seek to the end, press OK, select 'end cut'. That's it." msgstr "" +"CutListEditor permite editar sus películas.\n" +"Ir al inicio a partir del que quiere recortar. Pulse OK, seleccione 'corte " +"inicial'.\n" +"Después vaya al final y pulse OK, selecciones 'corte final'. Eso es todo." # msgid "Cutlist editor..." @@ -1814,9 +1801,8 @@ msgstr "Editor de listas de corte..." msgid "Czech" msgstr "Checo" -# msgid "Czech Republic" -msgstr "" +msgstr "República Checa" # msgid "D" @@ -1826,9 +1812,8 @@ msgstr "D" msgid "DHCP" msgstr "DHCP" -# msgid "DUAL LAYER DVD" -msgstr "" +msgstr "DVD DOBLE CAPA" # msgid "DVB-S" @@ -1855,13 +1840,16 @@ msgid "DVD media toolbox" msgstr "Barra de disco DVD" msgid "DVDPlayer plays your DVDs on your Dreambox" -msgstr "" +msgstr "DVDPlayer reproduce sus DVDs en su Dreambox" msgid "" "DVDPlayer plays your DVDs on your Dreambox.\n" "With the DVDPlayer you can play your DVDs on your Dreambox from a DVD or " "even from an iso file or video_ts folder on your harddisc or network." msgstr "" +"DVDPlayer reproduce sus DVDs en su Dreambox.\n" +"Con el DVDPlayer puede reproducir sus DVDs en su Dreambox desde el DVD o " +"incluso desde un fichero iso o una carpeta video_ts de su disco duro o red." # msgid "Danish" @@ -1883,14 +1871,12 @@ msgstr "Decidir qué hacer cuando un crashlog sea encontrado." msgid "Decide what should happen to the crashlogs after submission." msgstr "Decidir qué hacer después de enviar el crashlog." -# msgid "Decrease delay" -msgstr "" +msgstr "Reducir retardo" -# #, python-format msgid "Decrease delay by %i ms (can be set)" -msgstr "" +msgstr "Reducir retardo en %i ms (puede ser puesto)" # msgid "Deep Standby" @@ -1912,16 +1898,14 @@ msgstr "Ubicación por defecto de películas" msgid "Default services lists" msgstr "Lista de canales por defecto" -# -#, fuzzy msgid "Defaults" msgstr "Por defecto" msgid "Define a startup service" -msgstr "" +msgstr "Definir un canal de inicio" msgid "Define a startup service for your Dreambox." -msgstr "" +msgstr "Definir un canal de inicio para su Dreambox." # msgid "Delay" @@ -1943,9 +1927,8 @@ msgstr "Borrar entrada" msgid "Delete failed!" msgstr "¡Falló el borrado!" -# msgid "Delete mount" -msgstr "" +msgstr "Borrar montaje" # #, python-format @@ -1956,9 +1939,8 @@ msgstr "" "No borrar más satélite configurado\n" "%s?" -# msgid "Descending" -msgstr "" +msgstr "Descendiendo" # msgid "Description" @@ -1969,7 +1951,7 @@ msgid "Deselect" msgstr "Deseleccionar" msgid "Details for plugin: " -msgstr "" +msgstr "Detalles del plugin:" # msgid "Detected HDD:" @@ -2011,12 +1993,11 @@ msgstr "Marcando:" msgid "Digital contour removal" msgstr "Borrar contorno digital" -# msgid "Dir:" -msgstr "" +msgstr "Dir:" msgid "Direct playback of Youtube videos" -msgstr "" +msgstr "Reproduce directamente los videos de Youtube" # msgid "Direct playback of linked titles without menu" @@ -2051,13 +2032,11 @@ msgstr "Desactivar programación" msgid "Disabled" msgstr "Desactivado" -# msgid "Discard changes and close plugin" -msgstr "" +msgstr "Descartar cambios y cerrar plugin" -# msgid "Discard changes and close screen" -msgstr "" +msgstr "Descartar cambios y cerrar pantalla" # msgid "Disconnect" @@ -2087,15 +2066,14 @@ msgstr "Configurar Pantalla" msgid "Display and Userinterface" msgstr "Pantalla e Interfaz de usuario" -# msgid "Display search results by:" -msgstr "" +msgstr "Visualizar los resultados de búsqueda por:" msgid "Display your photos on the TV" -msgstr "" +msgstr "Visualizar sus fotos en su TV" msgid "Displays movie information from the InternetMovieDatabase" -msgstr "" +msgstr "Visualizar información de la película desde la InternetMovieDatabase" # #, python-format @@ -2164,15 +2142,15 @@ msgstr "¿Quiere hacer otra búsqueda manual?" #, python-format msgid "Do you want to download the image to %s ?" -msgstr "" +msgstr "¿Quiere descargar la imagen a %s?" # msgid "Do you want to enable the parental control feature on your dreambox?" msgstr "¿Quiere activar el control de adultos en su dreambox?" -# msgid "Do you want to enter a username and password for this host?\n" msgstr "" +"¿Quiere introducir un nombre de usuario y contraseña para esta máquina?\n" # msgid "Do you want to install default sat lists?" @@ -2206,9 +2184,8 @@ msgstr "¿Quiere restaurar su configuración?" msgid "Do you want to resume this playback?" msgstr "¿Quiere continuar esta reproducción?" -# msgid "Do you want to see more entries?" -msgstr "" +msgstr "¿Quiere ver más entradas?" # msgid "" @@ -2262,7 +2239,7 @@ msgstr "Descargar" #, python-format msgid "Download %s from Server" -msgstr "" +msgstr "Descargar %s desde el Servidor" # msgid "Download .NFI-Files for USB-Flasher" @@ -2272,16 +2249,14 @@ msgstr "Descargar ficheros .NFI para el USB-Flasher" msgid "Download Plugins" msgstr "Descargar Plugins" -# msgid "Download Video" -msgstr "" +msgstr "Descargar Video" msgid "Download files from Rapidshare" -msgstr "" +msgstr "Descargar ficheros desde Rapidshare" -# msgid "Download location" -msgstr "" +msgstr "Localización de la descarga" # msgid "Downloadable new plugins" @@ -2299,9 +2274,8 @@ msgstr "Descargando" msgid "Downloading plugin information. Please wait..." msgstr "Descargando información del plugin. Espere..." -# msgid "Downloading screenshots. Please wait..." -msgstr "" +msgstr "Descargando pantallazos. Por favor, espere..." # msgid "Dreambox format data DVD (HDTV compatible)" @@ -2311,9 +2285,8 @@ msgstr "Formato dreambox DVD (HDTV compatible)" msgid "Dreambox software because updates are available." msgstr "Actualizaciones del software Dreambox están disponibles." -# msgid "Duration: " -msgstr "" +msgstr "Duración:" # msgid "Dutch" @@ -2341,6 +2314,10 @@ msgid "" "(in standby mode without any running recordings) to perform updates of the " "epg information on these channels." msgstr "" +"EPGRefresh automáticamente cambia a los canales definidos por el usuario " +"cuando está desocupado\n" +"(en modo reposo si hay alguna grabación ejecutándose) para realizar " +"actualizaciones en la información del epg de esos canales." # #, python-format @@ -2379,9 +2356,8 @@ msgstr "Editar Programaciones y buscar nuevos Eventos" msgid "Edit Title" msgstr "Editar Título" -# msgid "Edit bouquets list" -msgstr "" +msgstr "Editar lista de canales" # msgid "Edit chapters of current title" @@ -2404,10 +2380,10 @@ msgid "Edit settings" msgstr "Editar configuración" msgid "Edit tags of recorded movies" -msgstr "" +msgstr "Editar etiquetas de películas grabadas" msgid "Edit tags of recorded movies." -msgstr "" +msgstr "Editar etiquetas de películas grabadas." # msgid "Edit the Nameserver configuration of your Dreambox.\n" @@ -2433,24 +2409,22 @@ msgstr "Editando" msgid "Editor for new AutoTimers" msgstr "Editor para nuevas AutoProgramaciones" -# msgid "Education" -msgstr "" +msgstr "Educación" # msgid "Electronic Program Guide" msgstr "Guía de Programación Electrónica" msgid "Emailclient is an IMAP4 e-mail viewer for the Dreambox." -msgstr "" +msgstr "Emailclient es un visor de e-mail IMAP4 para su Dreambox." # msgid "Enable" msgstr "Activar" -# msgid "Enable /media" -msgstr "" +msgstr "Habilitar /media" # msgid "Enable 5V for active antenna" @@ -2464,29 +2438,24 @@ msgstr "¿Activar el Asistente de Limpieza?" msgid "Enable Filtering" msgstr "Activar Filtro" -# msgid "Enable HTTP Access" -msgstr "" +msgstr "Habilitar Acceso HTTP" -# msgid "Enable HTTP Authentication" -msgstr "" +msgstr "Habilitar Autenticación HTTP" -# msgid "Enable HTTPS Access" -msgstr "" +msgstr "Habilitar Acceso HTTPS" -# msgid "Enable HTTPS Authentication" -msgstr "" +msgstr "Habilitar Autenticación HTTPS" # msgid "Enable Service Restriction" msgstr "Activar Restricción de Canales" -# msgid "Enable Streaming Authentication" -msgstr "" +msgstr "Habilitar Autenticación en Streaming" # msgid "Enable multiple bouquets" @@ -2496,11 +2465,11 @@ msgstr "Habilitar multiples listas" msgid "Enable parental control" msgstr "Activar el control de adultos" -# msgid "" "Enable this to be able to access the AutoTimer Overview from within the " "extension menu." msgstr "" +"Activar esto para activar el acceso al AutoTimer desde el menú de extensión." # msgid "Enable timer" @@ -2510,11 +2479,12 @@ msgstr "Activar programación" msgid "Enabled" msgstr "Activado" -# msgid "" "Encoding the channel uses for it's EPG data. You only need to change this if " "you're searching for special characters like the german umlauts." msgstr "" +"Codificar el canal a usar desde su dato del EPG. Sólo necesita cambiar esto " +"si está buscando por caracteres especiales como los umlauts alemanes." # msgid "Encrypted: " @@ -2564,6 +2534,8 @@ msgid "" "Enigma2 Plugin to play AVI/DIVX/WMV/etc. videos from PC on your Dreambox. " "Needs a running VLC from www.videolan.org on your pc." msgstr "" +"El plugin de Enigma2 para reproducir videos AVI/DIVX/WMV/etc. desde el pc en " +"su Dreambox. Necesita una ejecución de VLC en su pc (www.videolan.org)." # msgid "" @@ -2585,9 +2557,8 @@ msgstr "" msgid "Enter Fast Forward at speed" msgstr "Introduzca velocidad de avance hacia delante" -# msgid "Enter IP to scan..." -msgstr "" +msgstr "Introduzca la IP a escanear..." # msgid "Enter Rewind at speed" @@ -2597,53 +2568,43 @@ msgstr "Introduzca velocidad de avance hacia atrás" msgid "Enter main menu..." msgstr "Entre al menú principal..." -# msgid "Enter new hostname for your Dreambox" -msgstr "" +msgstr "Introduzca el nombre de su Dreambox" -# msgid "Enter options:" -msgstr "" +msgstr "Introduzca opciones:" -# msgid "Enter password:" -msgstr "" +msgstr "Introduzca contraseña:" -# msgid "Enter pin code" -msgstr "" +msgstr "Introduzca código pin" -# msgid "Enter share directory:" -msgstr "" +msgstr "Introduzca el directorio compartido:" -# msgid "Enter share name:" -msgstr "" +msgstr "Introduza el nombre compartido:" # msgid "Enter the service pin" msgstr "Ponga el pin del canal" -# msgid "Enter user and password for host: " -msgstr "" +msgstr "Introduzca el usuario y la contraseña para la máquina:" -# msgid "Enter username:" -msgstr "" +msgstr "Introduzca nombre de usuario:" # msgid "Enter your email address so that we can contact you if needed." msgstr "Introduzca su email para que contactemos con usted si es necesario." -# msgid "Enter your search term(s)" -msgstr "" +msgstr "Introduzca los términos a buscar:" -# msgid "Entertainment" -msgstr "" +msgstr "Entretenimiento" # msgid "Error" @@ -2678,10 +2639,8 @@ msgstr "Todo está bien" msgid "Exact match" msgstr "Coincidencia exacta" -# -#, fuzzy msgid "Exceeds dual layer medium!" -msgstr "¡excede el disco de doble capa!" +msgstr "¡Excede el disco de doble capa!" # msgid "Exclude" @@ -2692,7 +2651,7 @@ msgid "Execute \"after event\" during timespan" msgstr "Ejectuar el después del Evento durante el Tiempo" msgid "Execute TuxboxPlugins" -msgstr "" +msgstr "Ejecuta TuxboxPlugins" # msgid "Execution Progress:" @@ -2715,7 +2674,7 @@ msgid "Exit editor" msgstr "Salir del editor" msgid "Exit input device selection." -msgstr "" +msgstr "Sale de la selección de dispositivo de entrada." # msgid "Exit network wizard" @@ -2769,6 +2728,8 @@ msgid "" "FTPBrowser allows uploading and downloading files between your Dreambox and " "a server using the file transfer protocol." msgstr "" +"FTPBrowser permite subir y bajar ficheros entre su Dreambox y un servidor " +"usando el protocolo de transferencia de ficheros." # msgid "Factory reset" @@ -2813,25 +2774,21 @@ msgstr "Época rápida" msgid "Favourites" msgstr "Favoritos" -# msgid "Fetching feed entries" -msgstr "" +msgstr "Descargando las entradas" -# msgid "Fetching search entries" -msgstr "" +msgstr "Descargando las entradas de búsqueda" -# msgid "Filesystem Check" -msgstr "" +msgstr "Chequear sistema de ficheros" # msgid "Filesystem contains uncorrectable errors" msgstr "El sistema de archivos contiene errores graves" -# msgid "Film & Animation" -msgstr "" +msgstr "Cine y animación" # msgid "Filter" @@ -2871,7 +2828,7 @@ msgid "Finnish" msgstr "Finlandés" msgid "First generate your skin-style with the Ai.HD-Control plugin." -msgstr "" +msgstr "Primero genera su piel de estilo Ai.HD-Control" # msgid "Flash" @@ -2906,9 +2863,8 @@ msgstr "Contador de tramas sin problemas de sombras" msgid "Frame size in full view" msgstr "Tamaño de trama en vista completa" -# msgid "France" -msgstr "" +msgstr "Francia" # msgid "French" @@ -2944,9 +2900,10 @@ msgstr "Frisón" msgid "FritzCall shows incoming calls to your Fritz!Box on your Dreambox." msgstr "" +"FritzCall muestra sus llamadas de entrada a su Fritz!Box en su Dreambox." msgid "Frontend for /tmp/mmi.socket" -msgstr "" +msgstr "Frontend para /tmp/mmi.socket" # #, python-format @@ -2966,18 +2923,19 @@ msgstr "" "¿Quiere Reiniciar el GUI ahora?" msgid "GUI that allows user to change the ftp- / telnet password." -msgstr "" +msgstr "GUI que permite al usuario cambiar la contraseña para ftp/telnet." msgid "" "GUI that allows user to change the ftp-/telnet-password of the Dreambox." msgstr "" +"GUI que permite al usuario cambiar la contraseña del ftp/telnet en su " +"Dreambox." msgid "GUI to change the ftp and telnet-password" -msgstr "" +msgstr "GUI para cambiar la contraseña al ftp y telnet" -# msgid "Gaming" -msgstr "" +msgstr "Juegos" # msgid "Gateway" @@ -3003,46 +2961,43 @@ msgstr "Retardo general PCM (ms)" msgid "Genre" msgstr "Género" -# msgid "Genuine Dreambox" -msgstr "" +msgstr "Dreambox Genuino" msgid "Genuine Dreambox validation failed!" -msgstr "" +msgstr "Falló la validación del Dreambox Genuino" msgid "Genuine Dreambox verification" -msgstr "" +msgstr "Verificación de Dreambox Genuino" # msgid "German" msgstr "Alemán" msgid "German storm information" -msgstr "" +msgstr "Información alemana de tormentas" msgid "German traffic information" -msgstr "" +msgstr "Información alemana del tráfico" -# msgid "Germany" -msgstr "" +msgstr "Alemania" msgid "Get AudioCD info from CDDB and CD-Text" -msgstr "" +msgstr "Conseguir información AudioCD desde CDDB y CD-Text" msgid "Get latest experimental image" -msgstr "" +msgstr "Conseguir la última imagen experimental" msgid "Get latest release image" -msgstr "" +msgstr "Conseguir la última version de la imagen " # msgid "Getting plugin information. Please wait..." msgstr "Leyendo información del complemento. Espere..." -# msgid "Global delay" -msgstr "" +msgstr "Retardo global" # msgid "Goto 0" @@ -3053,20 +3008,21 @@ msgid "Goto position" msgstr "Ir a la posición" msgid "GraphMultiEPG shows a graphical timeline EPG" -msgstr "" +msgstr "GraphMultiEPG muestra un gráfico de la línea de tiempo del EPG" msgid "" "GraphMultiEPG shows a graphical timeline EPG.\n" "Shows a nice overview of all running und upcoming tv shows." msgstr "" +"GraphMultiEPG muestra un gráfico de tiempos del EPG.\n" +"Muestra una vista general de todos programas actuales y siguientes." # msgid "Graphical Multi EPG" msgstr "Multi EPG Gráfico" -# msgid "Great Britain" -msgstr "" +msgstr "Gran Bretaña" # msgid "Greek" @@ -3081,6 +3037,10 @@ msgid "" "protocol\n" "like Recording started notifications to a PC running a growl client" msgstr "" +"Growlee permite que su Dreambox envíe mensajes cortos usando el protocolo " +"growl\n" +"como la notificación de inicio de una grabación a un PC ejecutando un " +"cliente growl" # msgid "Guard Interval" @@ -3094,17 +3054,14 @@ msgstr "Modo intervalo seguro" msgid "Guess existing timer based on begin/end" msgstr "Las programaciones existentes están basadas en Inicio/Fin" -# msgid "HD videos" -msgstr "" +msgstr "Videos HD" -# msgid "HTTP Port" -msgstr "" +msgstr "Puerto HTTP" -# msgid "HTTPS Port" -msgstr "" +msgstr "Puerto HTTPS" # msgid "Harddisk" @@ -3118,9 +3075,8 @@ msgstr "Configuración del disco duro" msgid "Harddisk standby after" msgstr "Disco duro en reposo después" -# msgid "Help" -msgstr "" +msgstr "Ayuda" # msgid "Hidden network SSID" @@ -3142,24 +3098,21 @@ msgstr "Modo jerárquico" msgid "High bitrate support" msgstr "Soporte de bitrate alto" -# msgid "History" -msgstr "" +msgstr "Historia" -# msgid "Holland" -msgstr "" +msgstr "Holanda" -# msgid "Hong Kong" -msgstr "" +msgstr "Hong Kong" # msgid "Horizontal" msgstr "Horizontal" msgid "Hotplugging for removeable devices" -msgstr "" +msgstr "Conexión en caliente de dispositivos removibles" # msgid "How many minutes do you want to record?" @@ -3169,9 +3122,8 @@ msgstr "¿Cuántos minutos quiere grabar?" msgid "How to handle found crashlogs?" msgstr "¿Cómo quiere manejar los crashlogs?" -# msgid "Howto & Style" -msgstr "" +msgstr "Cómo hacer y Estilo" # msgid "Hue" @@ -3182,18 +3134,17 @@ msgid "Hungarian" msgstr "Húngaro" msgid "IMAP4 e-mail viewer for the Dreambox" -msgstr "" +msgstr "Visor de e-mail IMAP4 para su Dreambox" # msgid "IP Address" msgstr "Dirección IP" -# msgid "IP:" -msgstr "" +msgstr "IP:" msgid "IRC Client for Enigma2" -msgstr "" +msgstr "Cliente IRC para Enigma2" # msgid "ISO file is too large for this filesystem!" @@ -3207,12 +3158,13 @@ msgstr "ruta ISO" msgid "Icelandic" msgstr "Islandés" -# #, python-format msgid "" "If this is enabled an existing timer will also be considered recording an " "event if it records at least 80% of the it." msgstr "" +"Si activa esto, una grabación existente también será considerada grabación " +"si el evento graba al menos el 80% de ella." # msgid "" @@ -3272,14 +3224,12 @@ msgstr "Incluir" msgid "Include your email and name (optional) in the mail?" msgstr "¿Incluir su email y nombre (opcional) en el email?" -# msgid "Increase delay" -msgstr "" +msgstr "Incrementar retardo" -# #, python-format msgid "Increase delay by %i ms (can be set)" -msgstr "" +msgstr "Incrementar retardo por %i ms (puede ser puesto)" # msgid "Increased voltage" @@ -3289,9 +3239,8 @@ msgstr "Voltaje incrementado" msgid "Index" msgstr "Índice" -# msgid "India" -msgstr "" +msgstr "India" # msgid "Info" @@ -3317,9 +3266,8 @@ msgstr "Iniciar" msgid "Initial location in new timers" msgstr "Ruta inicial en nuevas programaciones" -# msgid "Initialization" -msgstr "" +msgstr "Inicialización" # msgid "Initialize" @@ -3334,10 +3282,10 @@ msgid "Input" msgstr "Entrada" msgid "Input device setup" -msgstr "" +msgstr "Configuración del dispositivo de entrada" msgid "Input devices" -msgstr "" +msgstr "Dispositivos de entrada" # msgid "Install" @@ -3412,10 +3360,10 @@ msgid "Internal Flash" msgstr "Flash Interna" msgid "Internal LAN adapter." -msgstr "" +msgstr "Adaptador de RED interna" msgid "Internal firmware updater" -msgstr "" +msgstr "Actualización de firmware interno" # msgid "Invalid Location" @@ -3426,25 +3374,22 @@ msgstr "Localización inválida" msgid "Invalid directory selected: %s" msgstr "Directorio seleccionado inválido: %s" -# # File: tmp/enigma2_plugins/genuinedreambox/src/plugin.py, line: 304 msgid "Invalid response from Security service pls restart again" msgstr "" +"Respuesta no válida del canal de Seguridad, por favor reinicie de nuevo" -# # File: tmp/enigma2_plugins/genuinedreambox/src/plugin.py, line: 132 msgid "Invalid response from server." -msgstr "" +msgstr "Respuesta no válida del servidor." -# # File: tmp/enigma2_plugins/genuinedreambox/src/plugin.py, line: 177 #, python-format msgid "Invalid response from server. Please report: %s" -msgstr "" +msgstr "Respuesta no válida del servidor. Por favor reporte: %s" -# msgid "Invalid selection" -msgstr "" +msgstr "Selección no válida" # msgid "Inversion" @@ -3454,17 +3399,15 @@ msgstr "Inversión" msgid "Ipkg" msgstr "Ipkg" -# msgid "Ireland" -msgstr "" +msgstr "Irlanda" # msgid "Is this videomode ok?" msgstr "¿Es este modo de video ok?" -# msgid "Israel" -msgstr "" +msgstr "Israel" # msgid "" @@ -3486,18 +3429,16 @@ msgid "Italian" msgstr "Italiano" msgid "Italian Weather forecast on Dreambox" -msgstr "" +msgstr "Previsión italiana del tiempo en su Dreambox" msgid "Italian Weather forecast on Dreambox from www.google.it." -msgstr "" +msgstr "Previsión italiana del tiempo en su Dreambox desde www.google.it." -# msgid "Italy" -msgstr "" +msgstr "Italia" -# msgid "Japan" -msgstr "" +msgstr "Japón" # msgid "Job View" @@ -3509,59 +3450,57 @@ msgid "Just Scale" msgstr "Sólo escala" msgid "Kerni's BrushedAlu-HD skin" -msgstr "" +msgstr "Pien Kerni's BrushedAlu-HD" msgid "Kerni's DreamMM-HD skin" -msgstr "" +msgstr "Piel Kerni's DreamMM-HD" msgid "Kerni's Elgato-HD skin" -msgstr "" +msgstr "Piel Kerni's Elgato-HD" msgid "Kerni's SWAIN skin" -msgstr "" +msgstr "Piel Kerni's SWAIN" msgid "Kerni's SWAIN-HD skin" -msgstr "" +msgstr "Piel Kerni's SWAIN-HD" msgid "Kerni's UltraViolet skin" -msgstr "" +msgstr "Piel Kerni's UltraViolet" msgid "Kerni's YADS-HD skin" -msgstr "" +msgstr "Piel Kerni's YADS-HD" msgid "Kerni's dTV-HD skin" -msgstr "" +msgstr "Piel Kerni's dTV-HD" msgid "Kerni's dTV-HD-Reloaded skin" -msgstr "" +msgstr "Piel Kerni's dTV-HD-Reloaded" msgid "Kerni's dmm-HD skin" -msgstr "" +msgstr "Piel Kerni's dmm-HD" msgid "Kerni's dreamTV-HD skin" -msgstr "" +msgstr "Piel Kerni's dreamTV-HD skin" msgid "Kerni's simple skin" -msgstr "" +msgstr "Piel Kerni's simple" msgid "Kerni-HD1 skin" -msgstr "" +msgstr "Piel Kerni-HD1" msgid "Kerni-HD1R2 skin" -msgstr "" +msgstr "Piel Kerni-HD1R2" msgid "Kernis HD1 skin" -msgstr "" +msgstr "Piel Kernis HD1" -# #, python-format msgid "Key %(Key)s successfully set to %(delay)i ms" -msgstr "" +msgstr "Tecla %(Key)s puesto correctamente a %(delay)i ms" -# #, python-format msgid "Key %(key)s (current value: %(value)i ms)" -msgstr "" +msgstr "Tecla %(key)s (valor actual: %(value)i ms)" # msgid "Keyboard" @@ -3580,14 +3519,14 @@ msgid "Keymap" msgstr "Mapa de teclado" msgid "KiddyTimer allows to control your kids's daily tv usage." -msgstr "" +msgstr "KiddyTimer permite controlar el uso diario de la tv de sus hijos." # msgid "LAN Adapter" msgstr "Adaptador de red" msgid "LAN connection" -msgstr "" +msgstr "Conexión de red local" # msgid "LNB" @@ -3679,10 +3618,10 @@ msgid "List of Storage Devices" msgstr "Listar dispositivos de almacenamiento" msgid "Listen and record internet radio" -msgstr "" +msgstr "Escuche y grabe radio internet" msgid "Listen and record shoutcast internet radio on your Dreambox." -msgstr "" +msgstr "Escuche y grabe shoutcast de radios de internet en su Dreambox." # msgid "Lithuanian" @@ -3696,9 +3635,8 @@ msgstr "Cargar" msgid "Load Length of Movies in Movielist" msgstr "Calcular longitud de Películas en la lista" -# msgid "Load feed on startup:" -msgstr "" +msgstr "Cargar fuente al arrancar:" # msgid "Load movie-length" @@ -3708,9 +3646,8 @@ msgstr "Cargar la longitud de las películas" msgid "Local Network" msgstr "Red Local" -# msgid "Local share name" -msgstr "" +msgstr "Nombre compartido local" # msgid "Location" @@ -3733,21 +3670,21 @@ msgid "Long Keypress" msgstr "Pulsar tecla largo" msgid "Long filenames" -msgstr "" +msgstr "Nombres de ficheros largos" # msgid "Longitude" msgstr "Longitud" -# msgid "Lower bound of timespan." -msgstr "" +msgstr "Límite inferior del intervalo de tiempo." -# msgid "" "Lower bound of timespan. Nothing before this time will be matched. Offsets " "are not taken into account!" msgstr "" +"Límite inferior de tiempo. Nada antes de este tiempo coincidirá. ¡El " +"intervalo de inicio no es tenido en cuenta!" # msgid "MMC Card" @@ -3782,25 +3719,25 @@ msgid "Manage extensions" msgstr "Manejar extensiones" msgid "Manage local files" -msgstr "" +msgstr "Manejar ficheros locales" msgid "Manage logos to display at boot time or while in radio mode." -msgstr "" +msgstr "Manejar logos a visualizar al arranque o mientras está en modo radio." msgid "Manage logos to display at boottime" -msgstr "" +msgstr "Manejar logos a visualizar al arranque" -# msgid "Manage network shares" -msgstr "" +msgstr "Manejar unidades de red" msgid "" "Manage your music files in a database, play it with Merlin Music Player." msgstr "" +"Manejar sus ficheros de música en una base de datos, reproduciéndolo con el " +"Reproductor de Música Merlin." -# msgid "Manage your network shares..." -msgstr "" +msgstr "Manejar sus unidades compartidas en red..." # msgid "Manage your receiver's software" @@ -3848,11 +3785,12 @@ msgstr "Max. Bitrate: " msgid "Maximum duration (in m)" msgstr "Máxima Duración (en m)" -# msgid "" "Maximum event duration to match. If an event is longer than this ammount of " "time (without offset) it won't be matched." msgstr "" +"Máxima duración del evento para coincidir. Si un evento es más largo que " +"esta cantidad de tiempo (sin adelanto) no coincidirá." # msgid "Media player" @@ -4842,6 +4780,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/et.po b/po/et.po index f6fe726..b607aa0 100755 --- a/po/et.po +++ b/po/et.po @@ -6,14 +6,14 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-12-30 09:00+0200\n" "Last-Translator: Arvo \n" "Language-Team: none\n" -"Language: et\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: et\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Pootle 2.0.3\n" @@ -4563,6 +4563,9 @@ msgstr "Inimesed & blogid" msgid "PermanentClock shows the clock permanently on the screen." msgstr "PermanentClock näitab ekraanil pidevalt kellaaega." +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "Loomad & Lemmikloomad" diff --git a/po/fi.po b/po/fi.po index 2ed03a9..c0e53f6 100755 --- a/po/fi.po +++ b/po/fi.po @@ -3,14 +3,14 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-12-19 14:53+0200\n" "Last-Translator: Timo \n" "Language-Team: none\n" -"Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Pootle 2.0.3\n" "X-Poedit-Language: Finnish\n" @@ -4619,6 +4619,9 @@ msgstr "Ihmiset ja blogit" msgid "PermanentClock shows the clock permanently on the screen." msgstr "PermanentClock näyttää kellon pysyvästi kuvaruudulla." +msgid "Persian" +msgstr "" + msgid "Pets & Animals" msgstr "Lemmikit ja eläimet" diff --git a/po/fr.po b/po/fr.po index c20a6e6..ea368df 100755 --- a/po/fr.po +++ b/po/fr.po @@ -3,9 +3,9 @@ msgid "" msgstr "" "Project-Id-Version: enigma 2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" -"PO-Revision-Date: 2011-01-26 12:50+0200\n" -"Last-Translator: Mladen \n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" +"PO-Revision-Date: 2011-02-09 20:34+0200\n" +"Last-Translator: Remi \n" "Language-Team: french\n" "Language: fr\n" "MIME-Version: 1.0\n" @@ -4805,6 +4805,9 @@ msgstr "Peuple & Blogs" msgid "PermanentClock shows the clock permanently on the screen." msgstr "PermanentClock affiche l'horloge permanente sur l'écran." +msgid "Persian" +msgstr "Iranien" + # msgid "Pets & Animals" msgstr "Animaux & Sauvages" diff --git a/po/fy.po b/po/fy.po index a5c1a6c..5ed3e0e 100755 --- a/po/fy.po +++ b/po/fy.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: fy\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2008-12-29 16:22+0100\n" "Last-Translator: gerrit \n" "Language-Team: gerrit \n" @@ -4777,6 +4777,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/hr.po b/po/hr.po index 90700ea..0d0187c 100755 --- a/po/hr.po +++ b/po/hr.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2008-01-27 23:38+0100\n" "Last-Translator: Jurica \n" "Language-Team: \n" @@ -4728,6 +4728,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/hu.po b/po/hu.po index 07ba6f7..a1971ca 100755 --- a/po/hu.po +++ b/po/hu.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2008-11-26 15:36+0100\n" "Last-Translator: MediaVox-Extrasat \n" "Language-Team: none\n" @@ -4766,6 +4766,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/is.po b/po/is.po index 05e191e..4dbdde3 100755 --- a/po/is.po +++ b/po/is.po @@ -5,14 +5,14 @@ msgid "" msgstr "" "Project-Id-Version: Icelandic translation v.1.44\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-11-18 19:57+0200\n" "Last-Translator: Baldur \n" "Language-Team: Polar Team/LT Team \n" -"Language: is\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: is\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Pootle 2.0.3\n" "X-Poedit-Language: Icelandic\n" @@ -4355,6 +4355,9 @@ msgstr "Fólk & blogg" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + msgid "Pets & Animals" msgstr "Dýralíf" diff --git a/po/it.po b/po/it.po index d8e2881..ea377f1 100755 --- a/po/it.po +++ b/po/it.po @@ -4,14 +4,14 @@ msgid "" msgstr "" "Project-Id-Version: enigma2 v2.6 Italian Locale\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" -"PO-Revision-Date: 2010-10-30 14:41+0200\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" +"PO-Revision-Date: 2011-02-06 00:32+0200\n" "Last-Translator: spaeleus \n" "Language-Team: WWW.LINSAT.NET \n" +"Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Pootle 2.0.3\n" "X-Poedit-Language: Italian\n" @@ -1547,7 +1547,7 @@ msgid "Configure nameservers" msgstr "Configurare i nameserver" msgid "Configure your WLAN network interface" -msgstr "Plugin per la configurazione di una rete locale wireless" +msgstr "Plugin per la configurazione di una interfaccia di rete WLAN" # msgid "Configure your internal LAN" @@ -4843,6 +4843,9 @@ msgstr "Gente & Blog" msgid "PermanentClock shows the clock permanently on the screen." msgstr "Plugin per visualizzare un orologio in modo permanente sullo schermo." +msgid "Persian" +msgstr "Persiano" + msgid "Pets & Animals" msgstr "Cuccioli & Animali" diff --git a/po/lt.po b/po/lt.po index e723632..fe69c5c 100755 --- a/po/lt.po +++ b/po/lt.po @@ -3,8 +3,8 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" -"PO-Revision-Date: 2010-11-07 22:38+0200\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" +"PO-Revision-Date: 2011-01-28 21:11+0200\n" "Last-Translator: Audronis \n" "Language-Team: Adga / enigma2 (c) \n" "Language: lt\n" @@ -18,13 +18,12 @@ msgstr "" "X-Poedit-SourceCharset: utf-8\n" "X-Poedit-Country: LITHUANIA\n" -# msgid "" "\n" "Advanced options and settings." msgstr "" "\n" -"IÅ¡plėstiniai pasirinkimai ir nustatymai." +"IÅ¡plėstinės funkcijos ir nustatymai." # msgid "" @@ -187,10 +186,9 @@ msgstr "#ffffffff" msgid "%H:%M" msgstr "%H:%M" -# #, python-format msgid "%d jobs are running in the background!" -msgstr "%d darbas yra veikiantis fone!" +msgstr "%d darbai, veikiantys fone!" #, python-format msgid "%d min" @@ -275,7 +273,7 @@ msgid "16:10 Letterbox" msgstr "16:10 Letterbox" msgid "16:10 PanScan" -msgstr "16:10 PanScan" +msgstr "16:10 Panoraminis Skanavimas" # msgid "16:9" @@ -316,7 +314,7 @@ msgid "4:3 Letterbox" msgstr "4:3 Letterbox" msgid "4:3 PanScan" -msgstr "4:3 PanScan" +msgstr "4:3 Panoraminis skanavimas" # msgid "5" @@ -401,7 +399,6 @@ msgstr "" "Baigtas įraÅ¡ymas pagal laikmatį nori nustatyti JÅ«sų\n" "imtuvą iÅ¡jungimui. Padaryti tai dabar?" -# msgid "" "A finished record timer wants to shut down\n" "your Dreambox. Shutdown now?" @@ -619,23 +616,18 @@ msgstr "Pridėti žymeklį" msgid "Add a new NFS or CIFS mount point to your Dreambox." msgstr "Pridėti naują NFS arba CIFS pajungimo taÅ¡ką jÅ«sų Dreambox'ui." -# msgid "Add a new title" -msgstr "Pridėkite naują pavadinimą" +msgstr "Pridėti naują pavadinimą" -# msgid "Add network configuration?" msgstr "Pridėti tinklo konfigÅ«raciją?" -# msgid "Add new AutoTimer" msgstr "Pridėti naują Auto Laikmatį" -# msgid "Add new network mount point" msgstr "Pridėti naują tinklo pajungimo taÅ¡ką" -# msgid "Add timer" msgstr "Laikmatis" @@ -692,32 +684,26 @@ msgstr "" "bandomuosius ekranus." msgid "Adult streaming plugin" -msgstr "Suaugusiųjų transliacijos priedas" +msgstr "Transliacijos tik suaugusiems priedas" msgid "Adult streaming plugin." -msgstr "Suaugusiųjų transliacijos priedas." +msgstr "Transliacijos tik suaugusiems priedas." -# msgid "Advanced Options" -msgstr "IÅ¡plėstiniai nustatymai" +msgstr "IÅ¡plėstinės funkcijos" -# msgid "Advanced Software" msgstr "IÅ¡plėstinė programinė įranga" -# msgid "Advanced Software Plugin" msgstr "IÅ¡plėstinė programinės įrangos papildoma programa" -# msgid "Advanced Video Enhancement Setup" -msgstr "IÅ¡plėstas vaizdo stiprinimo valdymas" +msgstr "IÅ¡plėstinis vaizdo gerinimo valdymas" -# msgid "Advanced Video Setup" msgstr "IÅ¡plėstiniai vaizdo nustatymai" -# msgid "Advanced restore" msgstr "IÅ¡plėstinis atkÅ«rimas" @@ -725,12 +711,11 @@ msgid "" "After a reboot or power outage, StartupToStandby will bring your Dreambox to " "standby-mode." msgstr "" -"Po perkrovimo ar elektros energijos nutraukimo, StartupToStandby nukels jÅ«sų " -"Dreambox į budėjimo režimą." +"Po perkrovimo ar elektros energijos nutraukimo, StartupToStandby perkels " +"jÅ«sų Dreambox į budėjimo režimą." -# msgid "After event" -msgstr "Po įvykio" +msgstr "Po užduoties" # msgid "" @@ -1002,23 +987,18 @@ msgstr "AutomatiÅ¡kai atnaujinti EPG" msgid "Automatically send crashlogs to Dream Multimedia" msgstr "AutomatiÅ¡kai siųsti crashlogs į Dream Multimediją" -# msgid "Autos & Vehicles" -msgstr "Automobiliai ir Transporto priemonės" +msgstr "Automobiliai ir transporto priemonės" -# msgid "Autowrite timer" msgstr "Automatinis laikamačio perraÅ¡ymas" -# msgid "Available format variables" -msgstr "Galimi formatai" +msgstr "Galimi kintami formatai" -# msgid "B" msgstr "B" -# msgid "BA" msgstr "BA" @@ -1028,11 +1008,9 @@ msgstr "BASIC-HD Tema nuo Ismail Demir" msgid "BASIC-HD Skin for Dreambox Images created from Ismail Demir" msgstr "BASIC-HD tema dėl Dreambox atvaizdų sukurta Ismail Demir" -# msgid "BB" msgstr "BB" -# msgid "BER" msgstr "BER" @@ -4335,6 +4313,9 @@ msgstr "Liaudis ir Blogai" msgid "PermanentClock shows the clock permanently on the screen." msgstr "PermanentClock rodo laikrodį ilgam ant ekrano." +msgid "Persian" +msgstr "Persų" + msgid "Pets & Animals" msgstr "Numylėtiniai ir GyvÅ«nai" diff --git a/po/lv.po b/po/lv.po index 00c7da2..b733ef1 100755 --- a/po/lv.po +++ b/po/lv.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2009-02-25 20:35+0200\n" "Last-Translator: Ivo Grinbergs \n" "Language-Team: Ivo / enigma2 (c) \n" @@ -4816,6 +4816,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/nl.po b/po/nl.po index 37250cf..91f983a 100755 --- a/po/nl.po +++ b/po/nl.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" -"PO-Revision-Date: 2011-01-26 11:56+0200\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" +"PO-Revision-Date: 2011-01-28 09:34+0200\n" "Last-Translator: Benny \n" "Language-Team: \n" "Language: nl\n" @@ -522,7 +522,7 @@ msgstr "" "Wilt u de tweede netwerk interface uitschakelen?" msgid "A simple downloading application for other plugins" -msgstr "" +msgstr "Een eenvoudige downloadapplicatie voor andere plugins" # msgid "" @@ -753,6 +753,8 @@ msgid "" "After a reboot or power outage, StartupToStandby will bring your Dreambox to " "standby-mode." msgstr "" +"Na een reboot of stroomuitval, brengt StartupToStandby uw Dreambox in stand-" +"by." # msgid "After event" @@ -793,10 +795,12 @@ msgid "Allow zapping via Webinterface" msgstr "Zappen via Webinterface toestaan" msgid "Allows the execution of TuxboxPlugins." -msgstr "" +msgstr "Maakt het uitvoeren van TuxboxPlugins mogelijk." msgid "Allows user to download files from rapidshare in the background." msgstr "" +"Maakt het mogelijk om op de achtergrond bestanden van RapidShare te " +"downloaden." # msgid "Alpha" @@ -912,7 +916,7 @@ msgid "Aspect Ratio" msgstr "Beeldverhouding" msgid "Assigning providers/services/caids to a CI module" -msgstr "" +msgstr "Toewijzen van zenders/kanalen/caids aan een CI-module" msgid "Atheros" msgstr "Atheros" @@ -937,6 +941,8 @@ msgid "" "AudoSync allows delaying the sound output (Bitstream/PCM) so that it is " "synchronous to the picture." msgstr "" +"AudioSync kan geluid (Bitstream/PCM) vertragen zodat het synchroon loopt met " +"het beeld." # msgid "Australia" @@ -990,6 +996,8 @@ msgid "" "AutoTimer scans the EPG and creates Timers depending on user-defined search " "criteria." msgstr "" +"AutoTimer scant de EPG en creëert Timers afhankelijk van de door de " +"gebruiker gedefinieerde zoekcriteria." # msgid "Automatic" @@ -1012,9 +1020,11 @@ msgid "" "Automatically changes the output resolution depending on the video " "resolution you are watching." msgstr "" +"Verandert automatisch de output resolutie, afhankelijk van de videoresolutie " +"waar u naar kijkt." msgid "Automatically create timer events based on keywords" -msgstr "" +msgstr "Maakt automatisch timers aan op basis van trefwoorden" msgid "Automatically informs you on low internal memory" msgstr "Automatisch informeert u over weinig intern geheugen" @@ -1422,10 +1432,10 @@ msgid "Cleanup Wizard settings" msgstr "Cleanup Wizard instellingen" msgid "Cleanup timerlist automatically" -msgstr "" +msgstr "Ruimt de timerlijst automatisch op" msgid "Cleanup timerlist automatically." -msgstr "" +msgstr "Ruimt de timerlijst automatisch op." # msgid "CleanupWizard" @@ -1710,7 +1720,7 @@ msgid "Create movie folder failed" msgstr "Aanmaken van de opnamemap is mislukt" msgid "Create preview pictures of your Movies" -msgstr "" +msgstr "Maakt voorbeeld miniaturen aan van uw films" msgid "Create remote timers" msgstr "" @@ -1807,6 +1817,11 @@ msgid "" "cut'.\n" "Then seek to the end, press OK, select 'end cut'. That's it." msgstr "" +"Met CutListEditor kunt u uw opnames bewerken.\n" +"Ga naar het begin van het deel dat u wilt knippen. Druk op 'OK', kies 'start " +"cut'.\n" +"Ga vervolgens naar het einde van het deel dat u wilt knippen, druk op 'OK', " +"kies 'end cut'. Dat is alles. " # msgid "Cutlist editor..." @@ -1864,9 +1879,6 @@ msgid "" "With the DVDPlayer you can play your DVDs on your Dreambox from a DVD or " "even from an iso file or video_ts folder on your harddisc or network." msgstr "" -"DVD-speler speelt uw DVD's af op uw Dreambox.\n" -"Met de DVD-speler kunt u DVD's afspelen op uw Dreambox, maar ook een ISO-" -"bestand en een Video-ts map op uw harde schijf of van uw netwerk." # msgid "Danish" @@ -1922,10 +1934,10 @@ msgid "Defaults" msgstr "Standaard" msgid "Define a startup service" -msgstr "" +msgstr "Bepaal de status na opstarten" msgid "Define a startup service for your Dreambox." -msgstr "" +msgstr "Bepaal de status na het opstarten van uw Dreambox." # msgid "Delay" @@ -1973,7 +1985,7 @@ msgid "Deselect" msgstr "Deselecteer" msgid "Details for plugin: " -msgstr "Details voor plugin:" +msgstr "Details voor plugin: " # msgid "Detected HDD:" @@ -2339,6 +2351,10 @@ msgid "" "(in standby mode without any running recordings) to perform updates of the " "epg information on these channels." msgstr "" +"EPGRefresh zal automatisch op de door de u ingestelde kanalen afstemmen als " +"de ontvanger niet in gebruik is\n" +"(in standby zonder dat er een opname loopt) om de EPG-gegevens van die " +"kanalen in te lezen. " # #, python-format @@ -2686,7 +2702,7 @@ msgid "Execute \"after event\" during timespan" msgstr "Uitvoeren na gebeurtenis gedurende tijdspanne" msgid "Execute TuxboxPlugins" -msgstr "" +msgstr "Voer TuxboxPlugins uit" # msgid "Execution Progress:" @@ -2934,7 +2950,7 @@ msgid "Frisian" msgstr "Fries" msgid "FritzCall shows incoming calls to your Fritz!Box on your Dreambox." -msgstr "" +msgstr "FritzCall toont inkomende gesprekken op uw Dreambox." msgid "Frontend for /tmp/mmi.socket" msgstr "" @@ -2957,14 +2973,16 @@ msgstr "" "de nieuwe skin te activeren. Nu herstarten?" msgid "GUI that allows user to change the ftp- / telnet password." -msgstr "" +msgstr "Gebruikersinterface voor het aanpassen van het FTP-/telnet-wachtwoord." msgid "" "GUI that allows user to change the ftp-/telnet-password of the Dreambox." msgstr "" +"Gebruikersinterface voor het aanpassen van het FTP-/telnet-wachtwoord van uw " +"Dreambox." msgid "GUI to change the ftp and telnet-password" -msgstr "" +msgstr "Gebruikersinterface voor het aanpassen van het FTP-/telnet-wachtwoord." # msgid "Gaming" @@ -3018,7 +3036,7 @@ msgid "Germany" msgstr "Duitsland" msgid "Get AudioCD info from CDDB and CD-Text" -msgstr "" +msgstr "Toont AudioCD-informatie van de CDDB en van CD-tekst" msgid "Get latest experimental image" msgstr "Ontvang het laatste experimentele image" @@ -3043,12 +3061,14 @@ msgid "Goto position" msgstr "Naar positie draaien" msgid "GraphMultiEPG shows a graphical timeline EPG" -msgstr "" +msgstr "GraphMultiEPG toont de EPG op een grafische tijdschaal" msgid "" "GraphMultiEPG shows a graphical timeline EPG.\n" "Shows a nice overview of all running und upcoming tv shows." msgstr "" +"GraphMultiEPG toont de EPG op een grafische tijdschaal.\n" +"Geeft een mooi overzicht van alle lopende en komende programma's." # msgid "Graphical Multi EPG" @@ -3149,7 +3169,7 @@ msgid "Horizontal" msgstr "Horizontaal" msgid "Hotplugging for removeable devices" -msgstr "" +msgstr "Hotplugging voor verwijderbare opslagmedia" # msgid "How many minutes do you want to record?" @@ -3475,10 +3495,10 @@ msgid "Italian" msgstr "Italiaans" msgid "Italian Weather forecast on Dreambox" -msgstr "" +msgstr "Italiaanse weersverwachting op uw Dreambox" msgid "Italian Weather forecast on Dreambox from www.google.it." -msgstr "" +msgstr "Italiaanse weersverwachting van www.google.it op uw Dreambox" # msgid "Italy" @@ -3787,6 +3807,8 @@ msgstr "Beheer gedeelde netwerkmappen" msgid "" "Manage your music files in a database, play it with Merlin Music Player." msgstr "" +"Beheer muziekbestanden in een database, speel die af met de Merlin Music " +"Player." msgid "Manage your network shares..." msgstr "Beheer uw netwerkverbindingen." @@ -4074,11 +4096,14 @@ msgstr "Opname locatie" msgid "" "MovieTagger adds tags to recorded movies to sort a large list of movies." msgstr "" +"MovieTagger voegt tags toe aan opnames om die gemakkelijk te kunnen sorteren." msgid "" "Movielist Preview creates screenshots of recordings and shows them inside " "the movielist." msgstr "" +"Movielist Preview maakt schermafbeeldingen van opnames en toont die in de " +"opnamelijst." # msgid "Movielist menu" @@ -4820,6 +4845,9 @@ msgstr "Mensen & Blogs" msgid "PermanentClock shows the clock permanently on the screen." msgstr "PermanentClock toont de klok permanent op het scherm." +msgid "Persian" +msgstr "" + msgid "Pets & Animals" msgstr "Huisdieren & Dieren" @@ -8341,10 +8369,10 @@ msgid "Watch streams from ZDF Mediathek" msgstr "" msgid "WeatherPlugin shows weatherforecasts on your Dreambox." -msgstr "" +msgstr "WeatherPlugin toont de weersverwachting op uw Dreambox." msgid "Weatherforecast on your Dreambox" -msgstr "" +msgstr "De weersverwachting op uw Dreambox." # msgid "Webinterface" @@ -8418,10 +8446,17 @@ msgid "" "\n" "The Help button shows this help again." msgstr "" -"Welkom bij de MyTube Youtube speler.Gebruik de boeket+ toets om te navigeren " -"naar het zoekveld en de boeket- om te navigeren naar de video inzendingen." -"Voor het afspelen van een film druk op OK van uw afstandsbediening.Druk op " -"info om de film beschrijving te zien.Druk op de menu knop voor extra opties." +"Welkom bij de MyTube Youtube speler.\n" +"\n" +"Gebruik de boeket+ toets om te navigeren naar het zoekveld en de boeket- om " +"te navigeren naar de video inzendingen.\n" +"\n" +"Voor het afspelen van een film druk op OK van uw afstandsbediening.\n" +"\n" +"Druk op info om de film beschrijving te zien.\n" +"\n" +"Druk op de menu knop voor extra opties.\n" +"\n" "De knop Help geeft deze hulp weer." msgid "" @@ -8435,9 +8470,15 @@ msgid "" "\n" "Press exit to get back to the input field." msgstr "" -"Welkom bij de MyTube Youtube speler.Tijdens het invoeren van je zoekterm(en) " -"krijg je suggesties weergegeven die overeenkomen met uw zoekterm.Druk op " -"exit om terug te keren naar het zoek veld." +"Welkom bij de MyTube Youtube speler.\n" +"\n" +"Tijdens het invoeren van je zoekterm(en) krijg je suggesties weergegeven die " +"overeenkomen met uw zoekterm.\n" +"\n" +"Om een suggestie te selecteren druk op DOWN van uw afstandsbediening, " +"selecteer het gewenste resultaat en druk op OK om het zoeken te starten.\n" +"\n" +"Druk op exit om terug te keren naar het zoek veld." # msgid "" @@ -8517,6 +8558,8 @@ msgid "" "When this option is enabled the AutoTimer won't match events where another " "timer with the same description already exists in the timer list." msgstr "" +"Als deze optie is ingesteld zal AutoTimer geen gebeurtenissen koppelen als " +"een andere timer met dezelfde beschrijving al bestaat." # msgid "" @@ -8559,6 +8602,8 @@ msgid "" "With AntiScrollbar you can cover up annoying ticker lines (e.g. in news " "channels)." msgstr "" +"Met de AntiScrollbar kunt u hinderlijke 'ticker lines' (b.v. bij " +"nieuwskanalen) verbergen." msgid "" "With DVDBurn you can make compilations of records from your Dreambox hard " @@ -8567,17 +8612,27 @@ msgid "" "a standard-compliant DVD that can be played on conventinal DVD players.\n" "HDTV recordings can only be burned in proprietary dreambox format." msgstr "" +"Met DVDBurn kunt u compilaties maken van opnames op de schijf van uw " +"ontvanger.\n" +"Optioneel kunt u aanpasbare menu's toevoegen. De compilatie kan worden " +"opgeslagen op een standaard DVD die op een convetionele DVD-speler kan " +"worden afgespeeld.\n" +"HDTV opnames kunnen alleen maar worden opgeslagen in het standaard .ts-" +"formaat." msgid "With EPGSearch you can search through the EPG and create timers." -msgstr "" +msgstr "Met EPGSearch kunt u de EPG doorzoeken en timers aanmaken." msgid "With Genuine Dreambox you can verify the authenticity of your Dreambox." msgstr "" +"Met Genuine Dreambox kunt u de authenticiteit van uw Dreambox verifieren." msgid "" "With IMDb you can download and displays movie information (rating, poster, " "cast, synopsis etc.) about the selected event." msgstr "" +"Met IMDB kunt u informatie binnenhalen en vertonen (waardering, poster, " +"cast, beschrijving etc) over de geselecteerde opname." msgid "With MovieRetitle you can rename your movies." msgstr "Met MovieRetitle kunt u de naam van uw films wijzigen." @@ -8607,6 +8662,10 @@ msgid "" "each of them.\n" "This allows watching a scrambled service while recording another one." msgstr "" +"Met de CommonInterfaceAssignment plugin kunt u aan elke CI-module in uw " +"ontvanger specifieke providers/services/caids toewijzen.\n" +"Dit maakt het mogelijk naar een versleutelde uitzending te kijken en " +"tegelijkertijd een andere op te nemen." msgid "" "With the CrashlogAutoSubmit plugin it is possible to automaticallymail " @@ -8617,21 +8676,28 @@ msgid "" "With the DefaultServicesScanner plugin you can scan default lamedbs sorted " "by satellite with a connected dish positioner." msgstr "" +"Met de DefaultServicesScanner plugin kunt u met een gemotoriseerde schotel " +"de default lamedbs scannen op volgorde van satellieten." msgid "" "With the DiseqcTester plugin you can test your satellite equipment for " "DiSEqC compatibility and errors." msgstr "" +"Met de DiseqcTester plugin kunt u uw installatie controleren op DiSEqC-" +"compatibiliteit en -fouten." msgid "" "With the NFIFlash plugin it is possible to prepare a USB stick with an " "Dreambox image.\n" "It is then possible to flash your Dreambox with the image on that stick." msgstr "" +"Met de NFIFlash plugin kunt u een USB-stick met een Dreambox-image " +"gereedmaken.\n" +"U kunt dan uw Dreambox flashen met het image op de stick." msgid "" "With the NetworkWizard you can easily configure your network step by step." -msgstr "" +msgstr "Met de NetworkWizard kunt u stap-voor-stap uw netwerk configureren." msgid "" "With the PositionerSetup plugin it is easy to install and configure a " @@ -8875,6 +8941,9 @@ msgid "" "\n" "Do you want to set the pin now?" msgstr "" +"Voer nu een pincode in en verberg het voor uw kinderen.\n" +"\n" +"Wilt u nu een pincode instellen?" # msgid "" @@ -9784,9 +9853,8 @@ msgstr "niet ondersteund" msgid "not used" msgstr "niet gebruikt" -# msgid "nothing connected" -msgstr "niets aangesloten" +msgstr "Niets aangesloten" # msgid "of a DUAL layer medium used." diff --git a/po/no.po b/po/no.po index b7baaef..a089b9d 100755 --- a/po/no.po +++ b/po/no.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2008-06-12 14:34+0100\n" "Last-Translator: MMMMMM \n" "Language-Team: none\n" @@ -4743,6 +4743,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/pl.po b/po/pl.po index bc2a30c..703e02d 100755 --- a/po/pl.po +++ b/po/pl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-07-23 12:21+0200\n" "Last-Translator: Mladen \n" "Language-Team: none\n" @@ -4871,6 +4871,9 @@ msgstr "Ludzie & Blogi" msgid "PermanentClock shows the clock permanently on the screen." msgstr "PermanentClock pokazuje na stałe zegar na ekranie." +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "Zwierzęta" diff --git a/po/pt.po b/po/pt.po index c69892f..0051f5e 100755 --- a/po/pt.po +++ b/po/pt.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma Portuguese\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2008-03-30 18:45-0000\n" "Last-Translator: Muaitai \n" "Language-Team: Muaitai \n" @@ -4744,6 +4744,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/ru.po b/po/ru.po index f109664..d748c01 100755 --- a/po/ru.po +++ b/po/ru.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-05-18 18:10+0200\n" "Last-Translator: peter \n" "Language-Team: Russian / enigma(c) Ukraine, Kiev>\n" @@ -4759,6 +4759,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/sk.po b/po/sk.po index e11193b..12fb3ae 100755 --- a/po/sk.po +++ b/po/sk.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-05-12 13:09+0200\n" "Last-Translator: acid-burn <>\n" "Language-Team: none\n" @@ -3946,6 +3946,9 @@ msgstr "Ľudia a blogy" msgid "PermanentClock shows the clock permanently on the screen." msgstr "Stále hodiny zobrazujú čas na obrazovke trvalo." +msgid "Persian" +msgstr "" + msgid "Pets & Animals" msgstr "Deti a zvieratá" diff --git a/po/sl.po b/po/sl.po index 40b0d5b..f49fe2c 100755 --- a/po/sl.po +++ b/po/sl.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: ENIGMA 1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2009-01-25 13:59+0100\n" "Last-Translator: Gregor \n" "Language-Team: \n" @@ -4771,6 +4771,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/po/sr.po b/po/sr.po index 7c2864b..9b59a08 100755 --- a/po/sr.po +++ b/po/sr.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Enigma2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2009-10-10 11:18+0100\n" "Last-Translator: maja \n" "Language-Team: veselin & majevica CRNABERZA \n" @@ -4842,6 +4842,9 @@ msgstr "Ljudi & Blogovi" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "Kućni ljub.& životinje" diff --git a/po/sv.po b/po/sv.po index d735dca..ebbf80d 100755 --- a/po/sv.po +++ b/po/sv.po @@ -7,13 +7,13 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-12-08 08:01+0200\n" "Last-Translator: sig \n" -"Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Pootle 2.0.3\n" "X-Poedit-Language: Swedish\n" @@ -4782,6 +4782,9 @@ msgstr "Folk & Bloggar" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "Husdjur & Vilddjur" diff --git a/po/tr.po b/po/tr.po index 0b47715..c889108 100755 --- a/po/tr.po +++ b/po/tr.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: enigma2 Turkish Locale\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2010-04-30 20:58+0200\n" "Last-Translator: Zulfikar \n" "Language-Team: http://hobiagaci.com \n" @@ -4802,6 +4802,9 @@ msgstr "Ä°nsanlar" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "Hayvanlar" diff --git a/po/uk.po b/po/uk.po index b45c28a..af214d4 100755 --- a/po/uk.po +++ b/po/uk.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: tuxbox-enigma 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-01 13:01+0000\n" +"POT-Creation-Date: 2011-01-27 12:42+0000\n" "PO-Revision-Date: 2008-09-28 14:03+0200\n" "Last-Translator: stepan_kv \n" "Language-Team: http://sat-ukraine.info/\n" @@ -4814,6 +4814,9 @@ msgstr "" msgid "PermanentClock shows the clock permanently on the screen." msgstr "" +msgid "Persian" +msgstr "" + # msgid "Pets & Animals" msgstr "" diff --git a/tools/enigma2.sh.in b/tools/enigma2.sh.in index a19e673..5914c3f 100755 --- a/tools/enigma2.sh.in +++ b/tools/enigma2.sh.in @@ -7,11 +7,23 @@ if [ -x @bindir@/showiframe -a -f /boot/backdrop.mvi ]; then @bindir@/showiframe /boot/backdrop.mvi fi +# hook to execute scripts always before enigma2 start +if [ -x @bindir@/enigma2_pre_start.sh ]; then + @bindir@/enigma2_pre_start.sh +fi + if [ -d /home/root ]; then cd /home/root fi -LD_PRELOAD=@libdir@/libopen.so.0.0.0 @bindir@/enigma2 +LIBS=@libdir@/libopen.so.0.0.0 + +#check for dreambox specific passthrough helper lib +if [ -e @libdir@/libpassthrough.so ]; then + LIBS="$LIBS @libdir@/libpassthrough.so" +fi + +LD_PRELOAD=$LIBS @bindir@/enigma2 # enigma2 exit codes: #