diff -pruN mythtv-0.19/contrib/mythrename.pl mythtv/contrib/mythrename.pl --- mythtv-0.19/contrib/mythrename.pl 2006-02-07 13:05:03.000000000 +1000 +++ mythtv/contrib/mythrename.pl 2006-02-07 13:05:03.000000000 +1000 @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# $Date: 2006-02-06 22:05:03 -0500 (Mon, 06 Feb 2006) $ +# $Date: 2006-02-07 13:05:03 +1000 (Tue, 07 Feb 2006) $ # $Revision: 8888 $ # $Author: xris $ # diff -pruN mythtv-0.19/contrib/optimize_mythdb.pl mythtv/contrib/optimize_mythdb.pl --- mythtv-0.19/contrib/optimize_mythdb.pl 2005-08-21 06:21:40.000000000 +1000 +++ mythtv/contrib/optimize_mythdb.pl 2005-08-21 06:21:40.000000000 +1000 @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# $Date: 2005-08-20 16:21:40 -0400 (Sat, 20 Aug 2005) $ +# $Date: 2005-08-21 06:21:40 +1000 (Sun, 21 Aug 2005) $ # $Revision: 7095 $ # $Author: xris $ # diff -pruN mythtv-0.19/libs/libavcodec/libavcodec.pro mythtv/libs/libavcodec/libavcodec.pro --- mythtv-0.19/libs/libavcodec/libavcodec.pro 2006-01-16 17:14:43.000000000 +1000 +++ mythtv/libs/libavcodec/libavcodec.pro 2006-04-16 17:27:30.000000000 +1000 @@ -430,4 +430,5 @@ macx { LIBS += -lz QMAKE_LFLAGS_SHLIB += -single_module QMAKE_LFLAGS_SHLIB += -seg1addr 0xC3000000 + QMAKE_LFLAGS_SHLIB += -read_only_relocs warning } diff -pruN mythtv-0.19/libs/libavformat/aviobuf.c mythtv/libs/libavformat/aviobuf.c --- mythtv-0.19/libs/libavformat/aviobuf.c 2006-01-16 17:14:43.000000000 +1000 +++ mythtv/libs/libavformat/aviobuf.c 2006-02-23 17:54:05.000000000 +1000 @@ -164,7 +164,13 @@ offset_t url_fseek(ByteIOContext *s, off void url_fskip(ByteIOContext *s, offset_t offset) { - url_fseek(s, offset, SEEK_CUR); + if (offset < 16384) + { + static unsigned char fskipbuf[16384]; + get_buffer(s, fskipbuf, offset); + } + else + url_fseek(s, offset, SEEK_CUR); } offset_t url_ftell(ByteIOContext *s) diff -pruN mythtv-0.19/libs/libmyth/audiooutputca.cpp mythtv/libs/libmyth/audiooutputca.cpp --- mythtv-0.19/libs/libmyth/audiooutputca.cpp 2005-10-11 10:30:51.000000000 +1000 +++ mythtv/libs/libmyth/audiooutputca.cpp 2006-04-16 17:23:48.000000000 +1000 @@ -7,7 +7,7 @@ * This plays MythTV audio through the default output device on OS X. * * = REVISION - * $Id: audiooutputca.cpp 7441 2005-10-11 00:30:51Z ijr $ + * $Id: audiooutputca.cpp 9721 2006-04-16 07:23:48Z nigel $ * * = AUTHORS * Jeremiah Morris @@ -107,8 +107,10 @@ bool AudioOutputCA::OpenDevice() bzero(&conv_in_desc, sizeof(AudioStreamBasicDescription)); conv_in_desc.mSampleRate = audio_samplerate; conv_in_desc.mFormatID = kAudioFormatLinearPCM; - conv_in_desc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger - | kLinearPCMFormatFlagIsBigEndian; + conv_in_desc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; +#ifdef WORDS_BIGENDIAN + conv_in_desc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; +#endif conv_in_desc.mBytesPerPacket = audio_bytes_per_sample; conv_in_desc.mFramesPerPacket = 1; conv_in_desc.mBytesPerFrame = audio_bytes_per_sample; diff -pruN mythtv-0.19/libs/libmyth/lcddevice.cpp mythtv/libs/libmyth/lcddevice.cpp --- mythtv-0.19/libs/libmyth/lcddevice.cpp 2006-01-26 03:11:56.000000000 +1000 +++ mythtv/libs/libmyth/lcddevice.cpp 2006-04-10 06:00:15.000000000 +1000 @@ -150,7 +150,7 @@ bool LCD::connectToHost(const QString &l if (!connected) { - QTextStream os(socket); + QTextStream os(socket->socketDevice()); int count = 0; do @@ -213,7 +213,7 @@ void LCD::sendToServer(const QString &so return; } - QTextStream os(socket); + QTextStream os(socket->socketDevice()); last_command = someText; @@ -224,7 +224,7 @@ void LCD::sendToServer(const QString &so #endif // Just stream the text out the socket - os << someText << "\n" << flush; + os << someText << "\n"; } else { diff -pruN mythtv-0.19/libs/libmyth/mythcontext.cpp mythtv/libs/libmyth/mythcontext.cpp --- mythtv-0.19/libs/libmyth/mythcontext.cpp 2006-01-25 20:22:57.000000000 +1000 +++ mythtv/libs/libmyth/mythcontext.cpp 2006-03-17 17:06:55.000000000 +1000 @@ -2621,9 +2621,13 @@ void MythContext::LogEntry(const QString d->LoadLogSettings(); if (d->m_logenable == 1) { + QString fullMsg = message; + if (!details.isEmpty()) + fullMsg += ": " + details; + if (message.left(21) != "Last message repeated") { - if (message == d->lastLogStrings[module]) + if (fullMsg == d->lastLogStrings[module]) { d->lastLogCounts[module] += 1; return; @@ -2639,7 +2643,7 @@ void MythContext::LogEntry(const QString } d->lastLogCounts[module] = 0; - d->lastLogStrings[module] = message; + d->lastLogStrings[module] = fullMsg; } } @@ -2693,7 +2697,7 @@ void MythContext::LogEntry(const QString } if (priority <= d->m_logprintlevel) - VERBOSE(VB_IMPORTANT, module + ": " + message); + VERBOSE(VB_IMPORTANT, module + ": " + fullMsg); } } diff -pruN mythtv-0.19/libs/libmyth/mythdialogs.cpp mythtv/libs/libmyth/mythdialogs.cpp --- mythtv-0.19/libs/libmyth/mythdialogs.cpp 2006-01-16 16:45:15.000000000 +1000 +++ mythtv/libs/libmyth/mythdialogs.cpp 2006-02-22 13:44:43.000000000 +1000 @@ -2617,6 +2617,7 @@ MythPasswordDialog::MythPasswordDialog(Q password_editor->setEchoMode(QLineEdit::Password); password_editor->setGeometry(textWidth + 20,10,135,30); password_editor->setBackgroundOrigin(ParentOrigin); + password_editor->setAllowVirtualKeyboard(false); connect(password_editor, SIGNAL(textChanged(const QString &)), this, SLOT(checkPassword(const QString &))); diff -pruN mythtv-0.19/libs/libmyth/mythwidgets.cpp mythtv/libs/libmyth/mythwidgets.cpp --- mythtv-0.19/libs/libmyth/mythwidgets.cpp 2005-11-22 18:51:53.000000000 +1000 +++ mythtv/libs/libmyth/mythwidgets.cpp 2006-03-17 17:32:14.000000000 +1000 @@ -353,7 +353,8 @@ void MythLineEdit::keyPressEvent(QKeyEve (e->key() == Qt::Key_Enter) || (e->key() == Qt::Key_Return))) { - if (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1) + if ((allowVirtualKeyboard) && + (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1)) { popup = new VirtualKeyboard(gContext->GetMainWindow(), this); gContext->GetMainWindow()->detach(popup); @@ -726,10 +727,11 @@ void MythRemoteLineEdit::keyPressEvent(Q QWidget::focusNextPrevChild(true); emit tryingToLooseFocus(true); } - else if (action == "SELECT" && - (e->text().isNull() || - (e->key() == Qt::Key_Enter) || - (e->key() == Qt::Key_Return))) + else if ((action == "SELECT") && + (!active_cycle) && + ((e->text().isNull()) || + (e->key() == Qt::Key_Enter) || + (e->key() == Qt::Key_Return))) { if (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1) { @@ -749,7 +751,7 @@ void MythRemoteLineEdit::keyPressEvent(Q if (handled) return; - if (!handled && popup && popup->isShown()) + if (popup && popup->isShown()) { endCycle(); QTextEdit::keyPressEvent(e); diff -pruN mythtv-0.19/libs/libmyth/mythwidgets.h mythtv/libs/libmyth/mythwidgets.h --- mythtv-0.19/libs/libmyth/mythwidgets.h 2005-10-30 21:41:09.000000000 +1000 +++ mythtv/libs/libmyth/mythwidgets.h 2006-02-22 13:44:43.000000000 +1000 @@ -122,17 +122,21 @@ class MythLineEdit : public QLineEdit Q_OBJECT public: MythLineEdit(QWidget *parent=NULL, const char* widgetName=0) : - QLineEdit(parent, widgetName) { rw = true; Init(); }; + QLineEdit(parent, widgetName) + { rw = true; allowVirtualKeyboard = true; Init(); }; MythLineEdit(const QString& contents, QWidget *parent=NULL, const char* widgetName=0) : - QLineEdit(contents, parent, widgetName) { rw = true; Init(); }; + QLineEdit(contents, parent, widgetName) + { rw = true; allowVirtualKeyboard = true; Init(); }; virtual ~MythLineEdit(); void setHelpText(QString help) { helptext = help; }; void setRW(bool readwrite = true) { rw = readwrite; }; void setRO() { rw = false; }; + void setAllowVirtualKeyboard(bool allowKbd = true) + { allowVirtualKeyboard = allowKbd; } void setPopupPosition(PopupPosition pos) { popupPosition = pos; } PopupPosition getPopupPosition(void) { return popupPosition; } @@ -154,6 +158,7 @@ class MythLineEdit : public QLineEdit VirtualKeyboard *popup; QString helptext; bool rw; + bool allowVirtualKeyboard; PopupPosition popupPosition; }; diff -pruN mythtv-0.19/libs/libmyth/remotefile.cpp mythtv/libs/libmyth/remotefile.cpp --- mythtv-0.19/libs/libmyth/remotefile.cpp 2005-12-08 06:49:24.000000000 +1000 +++ mythtv/libs/libmyth/remotefile.cpp 2006-02-23 17:54:05.000000000 +1000 @@ -15,6 +15,7 @@ RemoteFile::RemoteFile(const QString &ur path = url; readposition = 0; filesize = -1; + timeoutisfast = false; query = "QUERY_FILETRANSFER %1"; @@ -295,4 +296,34 @@ bool RemoteFile::SaveAs(QByteArray &data Read(data.data(), filesize); return true; -} +} + +void RemoteFile::SetTimeout(bool fast) +{ + if (timeoutisfast == fast) + return; + + if (!sock) + { + VERBOSE(VB_NETWORK, "RemoteFile::Seek(): Called with no socket"); + return; + } + + if (!sock->isOpen() || sock->error()) + return; + + if (!controlSock->isOpen() || controlSock->error()) + return; + + QStringList strlist = QString(query).arg(recordernum); + strlist << "SET_TIMEOUT"; + strlist << QString::number((int)fast); + + lock.lock(); + WriteStringList(controlSock, strlist); + ReadStringList(controlSock, strlist); + lock.unlock(); + + timeoutisfast = fast; +} + diff -pruN mythtv-0.19/libs/libmyth/remotefile.h mythtv/libs/libmyth/remotefile.h --- mythtv-0.19/libs/libmyth/remotefile.h 2005-12-08 06:49:24.000000000 +1000 +++ mythtv/libs/libmyth/remotefile.h 2006-02-23 17:54:05.000000000 +1000 @@ -27,6 +27,8 @@ class RemoteFile long long GetFileSize(void); + void SetTimeout(bool fast); + private: QSocketDevice *openSocket(bool control); @@ -43,6 +45,7 @@ class RemoteFile QMutex lock; long long filesize; + bool timeoutisfast; }; #endif diff -pruN mythtv-0.19/libs/libmyth/util.cpp mythtv/libs/libmyth/util.cpp --- mythtv-0.19/libs/libmyth/util.cpp 2006-02-08 07:52:26.000000000 +1000 +++ mythtv/libs/libmyth/util.cpp 2006-03-19 05:32:52.000000000 +1000 @@ -1006,16 +1006,20 @@ long long getDiskSpace(const QString &fi long long freespace = -1; QCString cstr = file_on_disk.local8Bit(); - if (statfs(cstr, &statbuf) == 0) + total = used = -1; + + // there are cases where statfs will return 0 (good), but f_blocks and + // others are invalid and set to 0 (such as when an automounted directory + // is not mounted but still visible because --ghost was used), + // so check to make sure we can have a total size > 0 + if ((statfs(cstr, &statbuf) == 0) && + (statbuf.f_blocks > 0) && + (statbuf.f_bsize > 0)) { freespace = statbuf.f_bsize * (statbuf.f_bavail >> 10); total = statbuf.f_bsize * (statbuf.f_blocks >> 10); used = total - freespace; } - else - { - freespace = total = used = -1; - } return freespace; } diff -pruN mythtv-0.19/libs/libmythsoundtouch/AAFilter.cpp mythtv/libs/libmythsoundtouch/AAFilter.cpp --- mythtv-0.19/libs/libmythsoundtouch/AAFilter.cpp 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/AAFilter.cpp 2004-11-14 08:29:45.000000000 +1000 @@ -12,7 +12,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: AAFilter.cpp 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/AAFilter.h mythtv/libs/libmythsoundtouch/AAFilter.h --- mythtv-0.19/libs/libmythsoundtouch/AAFilter.h 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/AAFilter.h 2004-11-14 08:29:45.000000000 +1000 @@ -13,7 +13,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: AAFilter.h 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/BPMDetect.h mythtv/libs/libmythsoundtouch/BPMDetect.h --- mythtv-0.19/libs/libmythsoundtouch/BPMDetect.h 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/BPMDetect.h 2004-11-14 08:29:45.000000000 +1000 @@ -26,7 +26,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: BPMDetect.h 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/cpu_detect.h mythtv/libs/libmythsoundtouch/cpu_detect.h --- mythtv-0.19/libs/libmythsoundtouch/cpu_detect.h 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/cpu_detect.h 2004-11-14 08:29:45.000000000 +1000 @@ -12,7 +12,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: cpu_detect.h 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/cpu_detect_x86_gcc.cpp mythtv/libs/libmythsoundtouch/cpu_detect_x86_gcc.cpp --- mythtv-0.19/libs/libmythsoundtouch/cpu_detect_x86_gcc.cpp 2005-01-24 16:42:19.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/cpu_detect_x86_gcc.cpp 2005-01-24 16:42:19.000000000 +1000 @@ -12,7 +12,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2005-01-24 01:42:19 -0500 (Mon, 24 Jan 2005) $ +// Last changed : $Date: 2005-01-24 16:42:19 +1000 (Mon, 24 Jan 2005) $ // File revision : $Revision: 5151 $ // // $Id: cpu_detect_x86_gcc.cpp 5151 2005-01-24 06:42:19Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIFOSampleBuffer.cpp mythtv/libs/libmythsoundtouch/FIFOSampleBuffer.cpp --- mythtv-0.19/libs/libmythsoundtouch/FIFOSampleBuffer.cpp 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/FIFOSampleBuffer.cpp 2004-11-14 08:29:45.000000000 +1000 @@ -15,7 +15,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: FIFOSampleBuffer.cpp 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIFOSampleBuffer.h mythtv/libs/libmythsoundtouch/FIFOSampleBuffer.h --- mythtv-0.19/libs/libmythsoundtouch/FIFOSampleBuffer.h 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/FIFOSampleBuffer.h 2004-11-14 08:29:45.000000000 +1000 @@ -15,7 +15,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: FIFOSampleBuffer.h 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIFOSamplePipe.h mythtv/libs/libmythsoundtouch/FIFOSamplePipe.h --- mythtv-0.19/libs/libmythsoundtouch/FIFOSamplePipe.h 2005-05-24 06:39:12.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/FIFOSamplePipe.h 2005-05-24 06:39:12.000000000 +1000 @@ -17,7 +17,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2005-05-23 16:39:12 -0400 (Mon, 23 May 2005) $ +// Last changed : $Date: 2005-05-24 06:39:12 +1000 (Tue, 24 May 2005) $ // File revision : $Revision: 6468 $ // // $Id: FIFOSamplePipe.h 6468 2005-05-23 20:39:12Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIRFilter.cpp mythtv/libs/libmythsoundtouch/FIRFilter.cpp --- mythtv-0.19/libs/libmythsoundtouch/FIRFilter.cpp 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/FIRFilter.cpp 2004-11-14 08:29:45.000000000 +1000 @@ -11,7 +11,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: FIRFilter.cpp 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIRFilter.h mythtv/libs/libmythsoundtouch/FIRFilter.h --- mythtv-0.19/libs/libmythsoundtouch/FIRFilter.h 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/FIRFilter.h 2004-11-14 08:29:45.000000000 +1000 @@ -11,7 +11,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: FIRFilter.h 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/mmx_gcc.cpp mythtv/libs/libmythsoundtouch/mmx_gcc.cpp --- mythtv-0.19/libs/libmythsoundtouch/mmx_gcc.cpp 2005-06-30 07:41:57.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/mmx_gcc.cpp 2005-06-30 07:41:57.000000000 +1000 @@ -15,7 +15,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2005-06-29 17:41:57 -0400 (Wed, 29 Jun 2005) $ +// Last changed : $Date: 2005-06-30 07:41:57 +1000 (Thu, 30 Jun 2005) $ // File revision : $Revision: 6741 $ // // $Id: mmx_gcc.cpp 6741 2005-06-29 21:41:57Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/RateTransposer.cpp mythtv/libs/libmythsoundtouch/RateTransposer.cpp --- mythtv-0.19/libs/libmythsoundtouch/RateTransposer.cpp 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/RateTransposer.cpp 2004-11-14 08:29:45.000000000 +1000 @@ -10,7 +10,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: RateTransposer.cpp 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/RateTransposer.h mythtv/libs/libmythsoundtouch/RateTransposer.h --- mythtv-0.19/libs/libmythsoundtouch/RateTransposer.h 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/RateTransposer.h 2004-11-14 08:29:45.000000000 +1000 @@ -14,7 +14,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: RateTransposer.h 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/SoundTouch.cpp mythtv/libs/libmythsoundtouch/SoundTouch.cpp --- mythtv-0.19/libs/libmythsoundtouch/SoundTouch.cpp 2005-11-12 09:19:13.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/SoundTouch.cpp 2005-11-12 09:19:13.000000000 +1000 @@ -41,7 +41,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2005-11-11 18:19:13 -0500 (Fri, 11 Nov 2005) $ +// Last changed : $Date: 2005-11-12 09:19:13 +1000 (Sat, 12 Nov 2005) $ // File revision : $Revision: 7850 $ // // $Id: SoundTouch.cpp 7850 2005-11-11 23:19:13Z danielk $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/SoundTouch.h mythtv/libs/libmythsoundtouch/SoundTouch.h --- mythtv-0.19/libs/libmythsoundtouch/SoundTouch.h 2005-11-12 09:19:13.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/SoundTouch.h 2005-11-12 09:19:13.000000000 +1000 @@ -41,7 +41,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2005-11-11 18:19:13 -0500 (Fri, 11 Nov 2005) $ +// Last changed : $Date: 2005-11-12 09:19:13 +1000 (Sat, 12 Nov 2005) $ // File revision : $Revision: 7850 $ // // $Id: SoundTouch.h 7850 2005-11-11 23:19:13Z danielk $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/STTypes.h mythtv/libs/libmythsoundtouch/STTypes.h --- mythtv-0.19/libs/libmythsoundtouch/STTypes.h 2005-01-21 16:08:36.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/STTypes.h 2005-01-21 16:08:36.000000000 +1000 @@ -8,7 +8,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2005-01-21 01:08:36 -0500 (Fri, 21 Jan 2005) $ +// Last changed : $Date: 2005-01-21 16:08:36 +1000 (Fri, 21 Jan 2005) $ // File revision : $Revision: 5097 $ // // $Id: STTypes.h 5097 2005-01-21 06:08:36Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/TDStretch.cpp mythtv/libs/libmythsoundtouch/TDStretch.cpp --- mythtv-0.19/libs/libmythsoundtouch/TDStretch.cpp 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/TDStretch.cpp 2004-11-14 08:29:45.000000000 +1000 @@ -13,7 +13,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: TDStretch.cpp 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythsoundtouch/TDStretch.h mythtv/libs/libmythsoundtouch/TDStretch.h --- mythtv-0.19/libs/libmythsoundtouch/TDStretch.h 2004-11-14 08:29:45.000000000 +1000 +++ mythtv/libs/libmythsoundtouch/TDStretch.h 2004-11-14 08:29:45.000000000 +1000 @@ -13,7 +13,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $ +// Last changed : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $ // File revision : $Revision: 4714 $ // // $Id: TDStretch.h 4714 2004-11-13 22:29:45Z ijr $ diff -pruN mythtv-0.19/libs/libmythtv/avformatdecoder.cpp mythtv/libs/libmythtv/avformatdecoder.cpp --- mythtv-0.19/libs/libmythtv/avformatdecoder.cpp 2006-02-07 04:09:58.000000000 +1000 +++ mythtv/libs/libmythtv/avformatdecoder.cpp 2006-03-31 11:55:22.000000000 +1000 @@ -725,7 +725,12 @@ int AvFormatDecoder::OpenFile(RingBuffer return -1; } + /* av_find_stream_info() eventually makes calls to avcodec_open() and avcodec_close() + so we have to use the avcodeclock */ + avcodeclock.lock(); int ret = av_find_stream_info(ic); + avcodeclock.unlock(); + if (ret < 0) { VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " + diff -pruN mythtv-0.19/libs/libmythtv/dummydtvrecorder.cpp mythtv/libs/libmythtv/dummydtvrecorder.cpp --- mythtv-0.19/libs/libmythtv/dummydtvrecorder.cpp 2005-12-15 01:54:48.000000000 +1000 +++ mythtv/libs/libmythtv/dummydtvrecorder.cpp 2006-04-20 23:52:51.000000000 +1000 @@ -125,7 +125,8 @@ void DummyDTVRecorder::StartRecording(vo // TRANSFER DATA while (_request_recording || _frames_seen_count <= 5) { - len = read(_stream_fd, &(_buffer[remainder]), _buffer_size - remainder); + len = read(_stream_fd, &(_buffer[remainder]), + _buffer_size - remainder); if (len == 0) { @@ -137,9 +138,8 @@ void DummyDTVRecorder::StartRecording(vo len += remainder; remainder = ProcessData(_buffer, len); - if (remainder > 0) // leftover bytes - memmove(_buffer, &(_buffer[_buffer_size - remainder]), - remainder); + if (remainder > 0 && (len > remainder)) // leftover bytes + memmove(_buffer, &(_buffer[len - remainder]), remainder); } FinishRecording(); diff -pruN mythtv-0.19/libs/libmythtv/dvbconfparser.cpp mythtv/libs/libmythtv/dvbconfparser.cpp --- mythtv-0.19/libs/libmythtv/dvbconfparser.cpp 2006-02-08 07:56:06.000000000 +1000 +++ mythtv/libs/libmythtv/dvbconfparser.cpp 2006-03-12 14:33:39.000000000 +1000 @@ -1,5 +1,5 @@ /* - * $Id: dvbconfparser.cpp 8901 2006-02-07 21:56:06Z danielk $ + * $Id: dvbconfparser.cpp 9335 2006-03-12 04:33:39Z danielk $ * vim: set expandtab tabstop=4 shiftwidth=4: * * Original Project @@ -193,10 +193,10 @@ bool DVBConfParser::parseConfQPSK(QStrin QStringList::Iterator end = tokens.end(); if (i != end) c.name = *i++; else return false; - if (i != end) c.frequency = (*i++).toInt(); else return false; + if (i != end) c.frequency = (*i++).toUInt()*1000; else return false; if (i == end || !c.polarity.parseConf(*i++)) return false; if (i == end ) return false; else i++; //Sat num - if (i != end) c.symbolrate = (*i++).toInt(); else return false; + if (i != end) c.symbolrate = (*i++).toUInt()*1000; else return false; if (i == end ) return false; else i++; if (i == end ) return false; else i++; if (i != end) c.serviceid = (*i++).toInt(); else return false; diff -pruN mythtv-0.19/libs/libmythtv/dvbsignalmonitor.cpp mythtv/libs/libmythtv/dvbsignalmonitor.cpp --- mythtv-0.19/libs/libmythtv/dvbsignalmonitor.cpp 2006-02-08 07:56:06.000000000 +1000 +++ mythtv/libs/libmythtv/dvbsignalmonitor.cpp 2006-04-20 23:46:13.000000000 +1000 @@ -348,8 +348,8 @@ void DVBSignalMonitor::RunTableMonitorTS len += remainder; remainder = GetStreamData()->ProcessData(buffer, len); - if (remainder > 0) // leftover bytes - memmove(buffer, &(buffer[buffer_size - remainder]), remainder); + if (remainder > 0 && (len > remainder)) // leftover bytes + memmove(buffer, &(buffer[len - remainder]), remainder); } VERBOSE(VB_CHANNEL, LOC + "RunTableMonitorTS(): " + "shutdown"); diff -pruN mythtv-0.19/libs/libmythtv/dvbtypes.cpp mythtv/libs/libmythtv/dvbtypes.cpp --- mythtv-0.19/libs/libmythtv/dvbtypes.cpp 2005-12-16 10:23:00.000000000 +1000 +++ mythtv/libs/libmythtv/dvbtypes.cpp 2006-02-17 08:41:02.000000000 +1000 @@ -202,7 +202,7 @@ DVBParamHelper::Tabl { {"TRANSMISSION_MODE_AUTO",TRANSMISSION_MODE_AUTO}, {"TRANSMISSION_MODE_2K",TRANSMISSION_MODE_2K}, - {"TRANSMISSION_MODE_8K",TRANSMISSION_MODE_2K}, + {"TRANSMISSION_MODE_8K",TRANSMISSION_MODE_8K}, {NULL,TRANSMISSION_MODE_AUTO}, }; @@ -210,7 +210,7 @@ DVBParamHelper::Tabl { {"999",TRANSMISSION_MODE_AUTO}, {"2",TRANSMISSION_MODE_2K}, - {"8",TRANSMISSION_MODE_2K}, + {"8",TRANSMISSION_MODE_8K}, {NULL,TRANSMISSION_MODE_AUTO}, }; @@ -218,7 +218,7 @@ DVBParamHelper::Tabl { {"auto",TRANSMISSION_MODE_AUTO}, {"2",TRANSMISSION_MODE_2K}, - {"8",TRANSMISSION_MODE_2K}, + {"8",TRANSMISSION_MODE_8K}, {NULL,TRANSMISSION_MODE_AUTO}, }; diff -pruN mythtv-0.19/libs/libmythtv/frequencytables.cpp mythtv/libs/libmythtv/frequencytables.cpp --- mythtv-0.19/libs/libmythtv/frequencytables.cpp 2006-01-19 02:46:14.000000000 +1000 +++ mythtv/libs/libmythtv/frequencytables.cpp 2006-04-13 00:21:41.000000000 +1000 @@ -283,104 +283,52 @@ static void init_freq_tables(freq_table_ "ATSC Channel %1", 70, 809000000, 887000000, 6000000, VSB_8); #endif // USING_DVB - // USA Cable, QAM 256 - fmap["atsc_qam256_uscable0"] = new FrequencyTable( - "QAM-256 Channel %1", 1, 75000000,1005000000, 6000000, QAM_256); - fmap["atsc_qam256_uscable1"] = new FrequencyTable( - "QAM-256 Channel T-%1", 7, 10000000, 52000000, 6000000, QAM_256); - - // USA Cable, QAM 256 ch 78+ - fmap["atsc_qam256_uscablehigh0"] = new FrequencyTable( - "QAM-256 Channel %1", 78,472000000,1005000000, 6000000, QAM_256); - - // USA Cable HRC, QAM 256 - fmap["atsc_qam256_ushrc0"] = new FrequencyTable( - "QAM-256 HRC %1", 1, 73750000, 73750001, 6000000, QAM_256); - fmap["atsc_qam256_ushrc1"] = new FrequencyTable( - "QAM-256 HRC %1", 2, 55750000, 67750000, 6000000, QAM_256); - fmap["atsc_qam256_ushrc2"] = new FrequencyTable( - "QAM-256 HRC %1", 5, 79750000, 85750000, 6000000, QAM_256); - fmap["atsc_qam256_ushrc3"] = new FrequencyTable( - "QAM-256 HRC %1", 7, 175750000, 643750000, 6000000, QAM_256); - fmap["atsc_qam256_ushrc4"] = new FrequencyTable( - "QAM-256 HRC %1", 95, 91750000, 114000000, 6000000, QAM_256); - fmap["atsc_qam256_ushrc5"] = new FrequencyTable( - "QAM-256 HRC %1", 100, 649750000, 799750000, 6000000, QAM_256); - fmap["atsc_qam256_ushrc6"] = new FrequencyTable( - "QAM-256 HRC T-%1", 7, 8175000, 50750000, 6000000, QAM_256); - - // USA Cable HRC, QAM 256 ch 78+ - fmap["atsc_qam256_ushrchigh0"] = new FrequencyTable( - "QAM-256 HRC %1", 78, 601750000, 643750000, 6000000, QAM_256); - fmap["atsc_qam256_ushrchigh1"] = new FrequencyTable( - "QAM-256 HRC %1", 100, 649750000, 799750000, 6000000, QAM_256); - - - - // USA Cable, QAM 128 - fmap["atsc_qam128_uscable0"] = new FrequencyTable( - "QAM-128 Channel %1", 1, 75000000,1005000000, 6000000, QAM_128); - fmap["atsc_qam128_uscable1"] = new FrequencyTable( - "QAM-128 Channel T-%1", 7, 10000000, 52000000, 6000000, QAM_128); - - // USA Cable, QAM 128 ch 78+ - fmap["atsc_qam128_uscablehigh0"] = new FrequencyTable( - "QAM-128 Channel %1", 78,472000000,1005000000, 6000000, QAM_128); - - // USA Cable HRC, QAM 128 - fmap["atsc_qam128_ushrc0"] = new FrequencyTable( - "QAM-128 HRC %1", 1, 73750000, 73750001, 6000000, QAM_128); - fmap["atsc_qam128_ushrc1"] = new FrequencyTable( - "QAM-128 HRC %1", 2, 55750000, 67750000, 6000000, QAM_128); - fmap["atsc_qam128_ushrc2"] = new FrequencyTable( - "QAM-128 HRC %1", 5, 79750000, 85750000, 6000000, QAM_128); - fmap["atsc_qam128_ushrc3"] = new FrequencyTable( - "QAM-128 HRC %1", 7, 175750000, 643750000, 6000000, QAM_128); - fmap["atsc_qam128_ushrc4"] = new FrequencyTable( - "QAM-128 HRC %1", 95, 91750000, 114000000, 6000000, QAM_128); - fmap["atsc_qam128_ushrc5"] = new FrequencyTable( - "QAM-128 HRC %1", 100, 649750000, 799750000, 6000000, QAM_128); - fmap["atsc_qam128_ushrc6"] = new FrequencyTable( - "QAM-128 HRC T-%1", 7, 8175000, 50750000, 6000000, QAM_128); - - // USA Cable HRC, QAM 128 ch 78+ - fmap["atsc_qam128_ushrchigh0"] = new FrequencyTable( - "QAM-128 HRC %1", 78, 601750000, 643750000, 6000000, QAM_128); - fmap["atsc_qam128_ushrchigh1"] = new FrequencyTable( - "QAM-128 HRC %1", 100, 649750000, 799750000, 6000000, QAM_128); - - - - - // USA Cable, QAM 64 - fmap["atsc_qam64_uscable0"] = new FrequencyTable( - "QAM-64 Channel %1", 1, 75000000,1005000000, 6000000, QAM_64); - fmap["atsc_qam64_uscable1"] = new FrequencyTable( - "QAM-64 Channel T-%1", 7, 10000000, 52000000, 6000000, QAM_64); - - // USA Cable, QAM 64 ch 78+ - fmap["atsc_qam64_uscablehigh0"] = new FrequencyTable( - "QAM-64 Channel %1", 78,472000000,1005000000, 6000000, QAM_64); - - // USA Cable HRC, QAM 64 - fmap["atsc_qam64_ushrc0"] = new FrequencyTable( - "QAM-64 HRC %1", 1, 73750000, 73750001, 6000000, QAM_64); - fmap["atsc_qam64_ushrc1"] = new FrequencyTable( - "QAM-64 HRC %1", 2, 55750000, 67750000, 6000000, QAM_64); - fmap["atsc_qam64_ushrc2"] = new FrequencyTable( - "QAM-64 HRC %1", 5, 79750000, 85750000, 6000000, QAM_64); - fmap["atsc_qam64_ushrc3"] = new FrequencyTable( - "QAM-64 HRC %1", 7, 175750000, 643750000, 6000000, QAM_64); - fmap["atsc_qam64_ushrc4"] = new FrequencyTable( - "QAM-64 HRC %1", 95, 91750000, 114000000, 6000000, QAM_64); - fmap["atsc_qam64_ushrc5"] = new FrequencyTable( - "QAM-64 HRC %1", 100, 649750000, 799750000, 6000000, QAM_64); - fmap["atsc_qam64_ushrc6"] = new FrequencyTable( - "QAM-64 HRC T-%1", 7, 8175000, 50750000, 6000000, QAM_64); - - // USA Cable HRC, QAM 64 ch 78+ - fmap["atsc_qam64_ushrchigh0"] = new FrequencyTable( - "QAM-64 HRC %1", 78, 601750000, 643750000, 6000000, QAM_64); - fmap["atsc_qam64_ushrchigh1"] = new FrequencyTable( - "QAM-64 HRC %1", 100, 649750000, 799750000, 6000000, QAM_64); + QString modStr[] = { "vsb8", "qam256", "qam128", "qam64", }; + uint mod[] = { VSB_8, QAM_256, QAM_128, QAM_64, }; + QString desc[] = { "ATSC ", "QAM-256 ", "QAM-128 ", "QAM-64 ", }; + +#define FREQ(A,B, C,D, E,F,G, H) \ + fmap[QString("atsc_%1_us%2").arg(A).arg(B)] = \ + new FrequencyTable(C+D, E, F, G, 6000000, H); + + for (uint i = 0; i < 3; i++) + { + // USA Cable, ch 1 to 155 and T.7 to T.14 + FREQ(modStr[i], "cable0", desc[i], "Channel %1", + 1, 75000000, 1005000000, mod[i]); + FREQ(modStr[i], "cable1", desc[i], "Channel T-%1", + 7, 10000000, 52000000, mod[i]); + // USA Cable, QAM 256 ch 78 to 155 + FREQ(modStr[i], "cablehigh0", desc[i], "Channel %1", + 78, 537000000,1005000000, mod[i]); + + QString std[] = { "hrc", "irc" }; + QString sdesc[] = { "HRC ", "IRC " }; + int off[] = { 0, 1250000 }; + + for (uint j = 0; j < 2; j++) + { + // USA Cable HRC/IRC, ch 1 to 125 + FREQ(modStr[i], std[j] + "0", desc[i], sdesc[j] + "%1", + 1, 73750000 + off[j], 73750001 + off[j], mod[i]); + FREQ(modStr[i], std[j] + "1", desc[i], sdesc[j] + "%1", + 2, 55750000 + off[j], 67750000 + off[j], mod[i]); + FREQ(modStr[i], std[j] + "2", desc[i], sdesc[j] + "%1", + 5, 79750000 + off[j], 85750000 + off[j], mod[i]); + FREQ(modStr[i], std[j] + "3", desc[i], sdesc[j] + "%1", + 7, 175750000 + off[j], 643750000 + off[j], mod[i]); + FREQ(modStr[i], std[j] + "4", desc[i], sdesc[j] + "%1", + 95, 91750000 + off[j], 114000000 + off[j], mod[i]); + FREQ(modStr[i], std[j] + "5", desc[i], sdesc[j] + "%1", + 100, 649750000 + off[j], 799750000 + off[j], mod[i]); + FREQ(modStr[i], std[j] + "6", desc[i], sdesc[j] + "T-%1", + 7, 8175000 + off[j], 50750000 + off[j], mod[i]); + + // USA Cable HRC/IRC, ch 67-125 + FREQ(modStr[i], std[j] + "high0", desc[i], sdesc[j] + "%1", + 67, 535750000 + off[j], 643750000 + off[j], mod[i]); + FREQ(modStr[i], std[j] + "high1", desc[i], sdesc[j] + "%1", + 100, 649750000 + off[j], 799750000 + off[j], mod[i]); + } + } } diff -pruN mythtv-0.19/libs/libmythtv/hdtvrecorder.cpp mythtv/libs/libmythtv/hdtvrecorder.cpp --- mythtv-0.19/libs/libmythtv/hdtvrecorder.cpp 2005-12-24 00:59:28.000000000 +1000 +++ mythtv/libs/libmythtv/hdtvrecorder.cpp 2006-04-20 23:46:13.000000000 +1000 @@ -627,9 +627,8 @@ void HDTVRecorder::StartRecording(void) len += remainder; remainder = ProcessData(_buffer, len); - if (remainder > 0) // leftover bytes - memmove(_buffer, &(_buffer[_buffer_size - remainder]), - remainder); + if (remainder > 0 && (len > remainder)) // leftover bytes + memmove(_buffer, &(_buffer[len - remainder]), remainder); } FinishRecording(); diff -pruN mythtv-0.19/libs/libmythtv/ivtvdecoder.cpp mythtv/libs/libmythtv/ivtvdecoder.cpp --- mythtv-0.19/libs/libmythtv/ivtvdecoder.cpp 2006-02-09 01:40:42.000000000 +1000 +++ mythtv/libs/libmythtv/ivtvdecoder.cpp 2006-03-23 00:35:05.000000000 +1000 @@ -270,7 +270,9 @@ int IvtvDecoder::OpenFile(RingBuffer *rb GetNVP()->SetVideoParams(720 /*width*/, (ntsc) ? 480 : 576 /*height*/, (ntsc) ? 29.97f : 25.0f, keyframedist, 1.33); - + + fps = (ntsc) ? 29.97f : 25.0f; // save for later length calculations + ringBuffer->UpdateRawBitrate(8000); if (m_playbackinfo || livetv || watchingrecording) diff -pruN mythtv-0.19/libs/libmythtv/jobqueue.cpp mythtv/libs/libmythtv/jobqueue.cpp --- mythtv-0.19/libs/libmythtv/jobqueue.cpp 2005-12-16 15:17:00.000000000 +1000 +++ mythtv/libs/libmythtv/jobqueue.cpp 2006-02-19 05:58:41.000000000 +1000 @@ -275,6 +275,11 @@ void JobQueue::ProcessQueue(void) (hostname != "") && (hostname != m_hostname)) { + // Setting the status here will prevent us from processing + // any other jobs for this recording until this one is + // completed on the remote host. + jobStatus[key] = status; + message = QString("JobQueue: Skipping '%1' job for chanid " "%2 @ %3, should run on '%4' instead") .arg(JobText(type)) diff -pruN mythtv-0.19/libs/libmythtv/libmythtv.pro mythtv/libs/libmythtv/libmythtv.pro --- mythtv-0.19/libs/libmythtv/libmythtv.pro 2006-01-13 18:11:45.000000000 +1000 +++ mythtv/libs/libmythtv/libmythtv.pro 2006-03-15 05:52:59.000000000 +1000 @@ -144,10 +144,10 @@ using_frontend { # On screen display (video output overlay) HEADERS += osd.h osdtypes.h HEADERS += osdsurface.h osdlistbtntype.h - HEADERS += udpnotify.h + HEADERS += osdimagecache.h udpnotify.h SOURCES += osd.cpp osdtypes.cpp SOURCES += osdsurface.cpp osdlistbtntype.cpp - SOURCES += udpnotify.cpp + SOURCES += osdimagecache.cpp udpnotify.cpp # Video output HEADERS += videooutbase.h videoout_null.h diff -pruN mythtv-0.19/libs/libmythtv/mpegrecorder.cpp mythtv/libs/libmythtv/mpegrecorder.cpp --- mythtv-0.19/libs/libmythtv/mpegrecorder.cpp 2005-12-24 00:59:28.000000000 +1000 +++ mythtv/libs/libmythtv/mpegrecorder.cpp 2006-05-11 15:51:20.000000000 +1000 @@ -363,9 +363,9 @@ bool MpegRecorder::OpenV4L2DeviceAsInput if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0) { - cerr << "Error setting codec params\n"; + cerr << "Warning, unable to set recording volume\n"; + cerr << "This is normal if you have an AVerMedia M179 card.\n"; perror("VIDIOC_S_CTRL:"); - return false; } if (vbimode) { @@ -481,6 +481,9 @@ void MpegRecorder::StartRecording(void) continue; case 0: printf("select timeout - ivtv driver has stopped responding\n"); + if(close(readfd) != 0) + perror("close"); + readfd = -1; // Force PVR card to be reopened on next iteration continue; default: break; } diff -pruN mythtv-0.19/libs/libmythtv/NuppelVideoPlayer.cpp mythtv/libs/libmythtv/NuppelVideoPlayer.cpp --- mythtv-0.19/libs/libmythtv/NuppelVideoPlayer.cpp 2006-02-08 07:56:06.000000000 +1000 +++ mythtv/libs/libmythtv/NuppelVideoPlayer.cpp 2006-04-27 01:23:01.000000000 +1000 @@ -147,6 +147,7 @@ NuppelVideoPlayer::NuppelVideoPlayer(QSt hascommbreaktable(false), deleteIter(deleteMap.end()), blankIter(blankMap.end()), commBreakIter(commBreakMap.end()), + forcePositionMapSync(false), // Playback (output) speed control decoder_lock(true), next_play_speed(1.0f), next_normal_speed(true), @@ -747,6 +748,8 @@ int NuppelVideoPlayer::OpenFile(bool ski SetDecoder(new IvtvDecoder(this, m_playbackinfo)); no_audio_out = true; // no audio with ivtv. audio_bits = 16; + audio_samplerate = 44100; + audio_channels = 2; } else if (forceVideoOutput == kVideoOutput_IVTV) { @@ -1113,7 +1116,7 @@ void NuppelVideoPlayer::ShutdownYUVResiz const unsigned char *NuppelVideoPlayer::GetScaledFrame(QSize &size) { QMutexLocker locker(&yuv_lock); - yuv_desired_size = size = QSize(size.width() & ~0x3, size.height() & ~0x3); + yuv_desired_size = size = QSize(size.width() & ~0x7, size.height() & ~0x7); if ((size.width() > 0) && (size.height() > 0)) { @@ -1920,7 +1923,7 @@ void NuppelVideoPlayer::DisplayNormalFra ShowText(); DisplaySubtitles(); } - else if (osdHasSubtitles || nonDisplayedSubtitles.size() > 20) + else if (osdHasSubtitles) { ClearSubtitles(); } @@ -2176,7 +2179,10 @@ void NuppelVideoPlayer::SwitchToProgram( } if (eof) + { discontinuity = true; + ClearSubtitles(); + } livetvchain->SetProgram(pginfo); @@ -2199,6 +2205,7 @@ void NuppelVideoPlayer::SwitchToProgram( } if (IsErrored()) { + VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram failed."); eof = true; return; } @@ -2265,6 +2272,8 @@ void NuppelVideoPlayer::JumpToProgram(vo ringBuffer->Pause(); ringBuffer->WaitForPause(); + ClearSubtitles(); + livetvchain->SetProgram(pginfo); ringBuffer->Reset(true); @@ -2284,6 +2293,7 @@ void NuppelVideoPlayer::JumpToProgram(vo if (errored || !GetDecoder()) { + VERBOSE(VB_IMPORTANT, LOC_ERR + "JumpToProgram failed."); errored = true; return; } @@ -2471,6 +2481,12 @@ void NuppelVideoPlayer::StartPlaying(voi JumpToProgram(); } + if (forcePositionMapSync) + { + forcePositionMapSync = false; + GetDecoder()->SyncPositionMap(); + } + if (IsErrored() || (nvr_enc && nvr_enc->GetErrorStatus())) { VERBOSE(VB_IMPORTANT, LOC_ERR + "Unknown error, exiting decoder"); @@ -4398,6 +4414,8 @@ void NuppelVideoPlayer::SetCommBreakMap( hascommbreaktable = !commBreakMap.isEmpty(); SetCommBreakIter(); commBreakMapLock.unlock(); + + forcePositionMapSync = true; } bool NuppelVideoPlayer::RebuildSeekTable(bool showPercentage, StatusCallback cb, void* cbData) @@ -4541,7 +4559,8 @@ int NuppelVideoPlayer::GetSecondsBehind( return (int)((float)(written - played) / video_frame_rate); } -void NuppelVideoPlayer::calcSliderPos(struct StatusPosInfo &posInfo) +void NuppelVideoPlayer::calcSliderPos(struct StatusPosInfo &posInfo, + bool paddedFields) { posInfo.desc = ""; posInfo.position = 0; @@ -4588,15 +4607,23 @@ void NuppelVideoPlayer::calcSliderPos(st int ssecs = (playbackLen - shours * 3600 - smins * 60); QString text1, text2; - if (shours > 0) + if (paddedFields) { - text1.sprintf("%d:%02d:%02d", phours, pmins, psecs); - text2.sprintf("%d:%02d:%02d", shours, smins, ssecs); + text1.sprintf("%02d:%02d:%02d", phours, pmins, psecs); + text2.sprintf("%02d:%02d:%02d", shours, smins, ssecs); } else { - text1.sprintf("%d:%02d", pmins, psecs); - text2.sprintf("%d:%02d", smins, ssecs); + if (shours > 0) + { + text1.sprintf("%d:%02d:%02d", phours, pmins, psecs); + text2.sprintf("%d:%02d:%02d", shours, smins, ssecs); + } + else + { + text1.sprintf("%d:%02d", pmins, psecs); + text2.sprintf("%d:%02d", smins, ssecs); + } } posInfo.desc = QObject::tr("%1 of %2").arg(text1).arg(text2); @@ -4654,6 +4681,7 @@ void NuppelVideoPlayer::AutoCommercialSk if (commBreakIter.key() == totalFrames) { + VERBOSE(VB_IMPORTANT, LOC + "Skipping commercial to end of file"); eof = true; } else @@ -4721,7 +4749,7 @@ bool NuppelVideoPlayer::DoSkipCommercial QString message = "COMMFLAG_REQUEST "; message += m_playbackinfo->chanid + " " + - m_playbackinfo->startts.toString(Qt::ISODate); + m_playbackinfo->recstartts.toString(Qt::ISODate); RemoteSendMessage(message); return false; @@ -5018,7 +5046,7 @@ void NuppelVideoPlayer::DisplaySubtitles QImage scaledImage = qImage.smoothScale(rect->w, rect->h); OSDTypeImage* image = new OSDTypeImage(); - image->SetPosition(QPoint(rect->x, rect->y)); + image->SetPosition(QPoint(rect->x, rect->y), hmult, vmult); image->LoadFromQImage(scaledImage); subtitleOSD->AddType(image); diff -pruN mythtv-0.19/libs/libmythtv/NuppelVideoPlayer.h mythtv/libs/libmythtv/NuppelVideoPlayer.h --- mythtv-0.19/libs/libmythtv/NuppelVideoPlayer.h 2006-02-03 04:06:32.000000000 +1000 +++ mythtv/libs/libmythtv/NuppelVideoPlayer.h 2006-03-18 08:22:45.000000000 +1000 @@ -150,7 +150,8 @@ class NuppelVideoPlayer // Complicated gets long long CalcMaxFFTime(long long ff, bool setjump = true) const; long long CalcRWTime(long long rw) const; - void calcSliderPos(struct StatusPosInfo &posInfo); + void calcSliderPos(struct StatusPosInfo &posInfo, + bool paddedFields = false); /// Non-const gets OSD *GetOSD(void) { return osd; } @@ -543,6 +544,7 @@ class NuppelVideoPlayer QMap::Iterator deleteIter; QMap::Iterator blankIter; QMap::Iterator commBreakIter; + bool forcePositionMapSync; // Playback (output) speed control /// Lock for next_play_speed and next_normal_speed diff -pruN mythtv-0.19/libs/libmythtv/NuppelVideoRecorder.cpp mythtv/libs/libmythtv/NuppelVideoRecorder.cpp --- mythtv-0.19/libs/libmythtv/NuppelVideoRecorder.cpp 2006-01-21 02:31:04.000000000 +1000 +++ mythtv/libs/libmythtv/NuppelVideoRecorder.cpp 2006-03-31 11:55:22.000000000 +1000 @@ -216,7 +216,10 @@ NuppelVideoRecorder::~NuppelVideoRecorde } if (mpa_codec) + { + QMutexLocker locker(&avcodeclock); avcodec_close(mpa_ctx); + } if (mpa_ctx) av_free(mpa_ctx); @@ -453,8 +456,11 @@ bool NuppelVideoRecorder::SetupAVCodec(v useavcodec = true; if (mpa_codec) + { + QMutexLocker locker(&avcodeclock); avcodec_close(mpa_ctx); - + } + if (mpa_ctx) av_free(mpa_ctx); mpa_ctx = NULL; @@ -626,13 +632,14 @@ int NuppelVideoRecorder::AudioInit(bool int frag, blocksize = 4096; int tmp; -#if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H) - VERBOSE(VB_IMPORTANT, QString("NVR::AudioInit() This Unix doesn't support" - " device files for audio access. Skipping")); - return 1; -#else if (!skipdevice) { +#if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H) + VERBOSE(VB_IMPORTANT, + QString("NVR::AudioInit() This Unix doesn't support" + " device files for audio access. Skipping")); + return 1; +#else if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK))) { VERBOSE(VB_IMPORTANT, QString("NVR: Error, cannot open DSP '%1'"). @@ -678,8 +685,8 @@ int NuppelVideoRecorder::AudioInit(bool } close(afd); - } #endif + } audio_bytes_per_sample = audio_channels * audio_bits / 8; blocksize *= 4; diff -pruN mythtv-0.19/libs/libmythtv/osd.cpp mythtv/libs/libmythtv/osd.cpp --- mythtv-0.19/libs/libmythtv/osd.cpp 2006-01-27 14:55:51.000000000 +1000 +++ mythtv/libs/libmythtv/osd.cpp 2006-02-19 07:26:06.000000000 +1000 @@ -154,7 +154,8 @@ void OSD::SetDefaults(void) } OSDTypeCC *ccpage = new OSDTypeCC(name, ccfont, sub_xoff, sub_yoff, - sub_dispw, sub_disph); + sub_dispw, sub_disph, + wmult, hmult); container->AddType(ccpage); } @@ -517,7 +518,7 @@ void OSD::parseBox(OSDSet *container, QD } } - OSDTypeBox *box = new OSDTypeBox(name, area); + OSDTypeBox *box = new OSDTypeBox(name, area, wmult, hmult); container->AddType(box); } @@ -658,7 +659,7 @@ void OSD::parseTextArea(OSDSet *containe return; } - OSDTypeText *text = new OSDTypeText(name, ttffont, "", area); + OSDTypeText *text = new OSDTypeText(name, ttffont, "", area, wmult, hmult); container->AddType(text); text->SetMultiLine(multiline); @@ -875,7 +876,7 @@ void OSD::parsePositionRects(OSDSet *con QRect area = parseRect(getFirstText(info)); normalizeRect(area); - rects->AddPosition(area); + rects->AddPosition(area, wmult, hmult); } else { @@ -919,7 +920,7 @@ void OSD::parsePositionImage(OSDSet *con pos.setX((int)(pos.x() * wmult + xoffset)); pos.setY((int)(pos.y() * hmult + yoffset)); - image->AddPosition(pos); + image->AddPosition(pos, wmult, hmult); } else if (info.tagName() == "staticsize") { @@ -1925,7 +1926,7 @@ void OSD::ShowEditArrow(long long number image = new OSDTypeImage(*editarrowright); } - image->SetPosition(QPoint(xpos, ypos)); + image->SetPosition(QPoint(xpos, ypos), wmult, hmult); set->AddType(image); set->Display(); diff -pruN mythtv-0.19/libs/libmythtv/osdimagecache.cpp mythtv/libs/libmythtv/osdimagecache.cpp --- mythtv-0.19/libs/libmythtv/osdimagecache.cpp 1970-01-01 10:00:00.000000000 +1000 +++ mythtv/libs/libmythtv/osdimagecache.cpp 2006-05-10 09:54:43.000000000 +1000 @@ -0,0 +1,296 @@ +// -*- Mode: c++ -*- +/** OSDImageCache + * Copyright (c) 2006 by Pekka Jääskeläinen, Daniel Thor Kristjansson + * Distributed as part of MythTV under GPL v2 and later. + */ + +// POSIX headers +#include + +// Qt headers +#include +#include +#include +#include +#include + +// MythTV headers +#include "mythcontext.h" +#include "osdimagecache.h" + +// Print statistics of OSD image access in the destructor of OSDImageCache +//#define PRINT_OSD_IMAGE_CACHE_STATS + +#define LOC QString("OSDImgCache: ") +#define LOC_ERR QString("OSDImgCache, Error: ") + +uint OSDImageCache::kMaximumMemoryCacheSize = 5 * 1024 * 1024; + +/** \fn OSDImageCacheValue::OSDImageCacheValue(unsigned char*,unsigned char*,unsighed char*,unsigned char*,unsighed char*, QRect) + * \brief The main constructor that takes the image data as arguments. + * + * The image data becomes property of the OSDImageCacheValue + * and will be deleted by it. + */ +OSDImageCacheValue::OSDImageCacheValue( + QString cacheKey, + unsigned char *yuv, unsigned char *ybuffer, + unsigned char *ubuffer, unsigned char *vbuffer, + unsigned char *alpha, QRect imagesize) : + m_yuv(yuv), m_ybuffer(ybuffer), + m_ubuffer(ubuffer), m_vbuffer(vbuffer), + m_alpha(alpha), m_imagesize(imagesize), + m_cacheKey(QDeepCopy(cacheKey)) +{ + uint yuv_size = m_imagesize.width() * m_imagesize.height() * 3 / 2; + m_size_in_bytes = + (sizeof(OSDImageCacheValue)) + yuv_size + + (m_imagesize.width() * m_imagesize.height()); +} + +/** \fn OSDImageCacheValue::~OSDImageCacheValue() + * \brief Destructor, frees the cached bitmaps. + */ +OSDImageCacheValue::~OSDImageCacheValue() +{ + delete [] m_yuv; + m_yuv = NULL; + delete [] m_alpha; + m_alpha = NULL; +} + +/** \fn OSDImageCache::OSDImageCache() + * \brief Constructor, initializes the internal cache structures. + */ +OSDImageCache::OSDImageCache() : + m_cacheLock(true), m_imageCache(kMaximumMemoryCacheSize, 50), + m_memHits(0), m_diskHits(0), m_misses(0) +{ + // When the cache gets too large, items are + // automatically deleted from it in LRU order. + m_imageCache.setAutoDelete(true); +} + +/** \fn OSDImageCache::~OSDImageCache() + * \brief Destructor, frees all cached OSD images. + */ +OSDImageCache::~OSDImageCache() +{ +#ifdef PRINT_OSD_IMAGE_CACHE_STATS + int totalAccess = m_memHits + m_diskHits + m_misses; + if (totalAccess == 0) + return; + +#define LOG_PREFIX "OSDImageCache: " + VERBOSE(VB_IMPORTANT, LOC << " Statistics: " << endl + << LOG_PREFIX << m_imageCache.totalCost() << " bytes in cache\n" + << LOG_PREFIX << " memory hits: " + << m_memHits << ", " << m_memHits*100.0/totalAccess << "%\n" + << LOG_PREFIX << " disk hits: " + << m_diskHits << ", " << m_diskHits*100.0/totalAccess << "%\n" + << LOG_PREFIX << " misses: " + << m_misses << ", " << m_misses*100.0/totalAccess << "%"); +#undef LOC_PREFIX +#endif + Reset(); +} + +/** \fn OSDImageCache::Contains(const QString&,bool) + * \brief Returns true if cached OSD image was found in the cache. + * + * \param key The key for this image. + * \param useFile If true, also look from the disk cache. + */ +bool OSDImageCache::Contains(const QString &key, bool useFile) const +{ + QMutexLocker locker(&m_cacheLock); + + if (m_imageCache.find(key) != NULL) + return true; + + if (!useFile) + return false; + + return InFileCache(key); +} + +bool OSDImageCache::InFileCache(const QString &key) const +{ + // check if cache file exists + QDir dir(MythContext::GetConfDir() + "/osdcache/"); + QFileInfo cFile(dir.path() + "/" + key); + if (!cFile.exists() || !cFile.isReadable()) + return false; + + // check if backing file exists + QString orig = ExtractOriginal(key); + if (orig.isEmpty()) + return false; + + QFileInfo oFile(orig); + if (!oFile.exists()) + { + VERBOSE(VB_IMPORTANT, LOC + QString("Can't find '%1'").arg(orig)); + return false; + } + + // if cache file is older than backing file, delete cache file + if (cFile.lastModified() < oFile.lastModified()) + { + cFile.dir().remove(cFile.baseName(true)); + return false; + } + + return true; +} + +/** \fn OSDImageCache::Get(const QString&,bool) + * \brief Returns OSD image data from cache. + * + * This also removes the image from the cache so it won't be deleted + * while in use. The deletion of the taken item becomes responsibility + * of the client. Returns NULL if item with the given key is not found. + * + * \param key The key for this image. + * \param useFile If true, also check the disk cache. + */ +OSDImageCacheValue *OSDImageCache::Get(const QString &key, bool useFile) +{ + QMutexLocker locker(&m_cacheLock); + OSDImageCacheValue* item = m_imageCache.find(key); + if (item) + { + m_memHits++; + return m_imageCache.take(key); + } + + if (!useFile || !InFileCache(key)) + { + m_misses++; + return NULL; + } + + QDir dir(MythContext::GetConfDir() + "/osdcache/"); + QFile cacheFile(dir.path() + "/" + key); + cacheFile.open(IO_ReadOnly); + uint32_t imwidth = 0; + uint32_t imheight = 0; + + QDataStream stream(&cacheFile); + stream >> imwidth >> imheight; + + uint yuv_size = imwidth * imheight * 3 / 2; + uint tot_size = (sizeof(imwidth) * 2) + yuv_size + (imwidth * imheight); + + if (cacheFile.size() != tot_size) + { + VERBOSE(VB_IMPORTANT, LOC_ERR + key + " wrong cache file size!" + << cacheFile.size() << " != " << tot_size); + return NULL; + } + + unsigned char *yuv = new unsigned char[yuv_size]; + unsigned char *alpha = new unsigned char[imwidth * imheight]; + stream.readRawBytes((char*)yuv, yuv_size); + stream.readRawBytes((char*)alpha, imwidth * imheight); + cacheFile.close(); + + OSDImageCacheValue* value = + new OSDImageCacheValue( + key, + yuv, yuv, + yuv + (imwidth * imheight), + yuv + (imwidth * imheight * 5 / 4), + alpha, QRect(0, 0, imwidth, imheight)); + + m_diskHits++; + return value; +} + +/** \fn OSDImageCache::Insert(OSDImageCacheValue*) + * \brief Inserts OSD image data to memory cache. + * + * The item becomes property of the OSDImageCache and may be + * deleted any time by it. + * + * \param value The cache item. + */ +void OSDImageCache::Insert(OSDImageCacheValue *value) +{ + if (!value) + return; + + QMutexLocker locker(&m_cacheLock); + if (!m_imageCache.insert(value->GetKey(), value, value->GetSize())) + { + VERBOSE(VB_IMPORTANT, + LOC_ERR + QString("inserting image to memory cache failed")); + } +} + + +/** \fn OSDImageCache::SaveToDisk(const OSDImageCacheValue*) + * \brief Saves OSD image data to disk cache. + * + * Item is not written to the memory cache, i.e., it stays as + * property of the client. + * + * \param value The cached OSD image to save. + */ +void OSDImageCache::SaveToDisk(const OSDImageCacheValue *value) +{ + if (InFileCache(value->GetKey())) + return; + + QDir dir(MythContext::GetConfDir() + "/osdcache/"); + if (!dir.exists() && !dir.mkdir(dir.path())) + { + VERBOSE(VB_IMPORTANT, LOC_ERR + "Creating osdcache directory failed."); + return; + } + + QFile cacheFile(dir.path() + "/" + value->GetKey()); + if (!cacheFile.open(IO_WriteOnly | IO_Truncate)) + { + VERBOSE(VB_IMPORTANT, LOC_ERR + "Creating osdcache file failed."); + return; + } + + uint32_t imwidth = value->m_imagesize.width(); + uint32_t imheight = value->m_imagesize.height(); + uint yuv_size = imwidth * imheight * 3 / 2; + + QDataStream stream(&cacheFile); + stream << imwidth << imheight; + stream.writeRawBytes((const char*)value->m_yuv, yuv_size); + stream.writeRawBytes((const char*)value->m_alpha, imwidth * imheight); + cacheFile.close(); +} + +/** \fn OSDImageCache::CreateKey(const QString&,float,float,int,int) + * \brief Generates a cache key from the given OSD image parameters. + * + * The returned key is a string that can be safely used as a file name. + */ +QString OSDImageCache::CreateKey(const QString &filename, float wmult, + float hmult, int scalew, int scaleh) +{ + QString tmp = filename; + return QString("cache_%1@%2_%3_%4_%5").arg(tmp.replace(QChar('/'), "+")) + .arg(wmult).arg(hmult).arg(scalew).arg(scaleh); +} + +QString OSDImageCache::ExtractOriginal(const QString &key) +{ + QString tmp0 = key.mid(6); + QString tmp1 = tmp0.left(tmp0.find("@")); + QString tmp2 = tmp1.replace(QChar('+'), "/"); + return tmp2; +} + +void OSDImageCache::Reset(void) +{ + QMutexLocker locker(&m_cacheLock); + // this also deletes the images due to setAutoDelete(true) + m_imageCache.clear(); +} diff -pruN mythtv-0.19/libs/libmythtv/osdimagecache.h mythtv/libs/libmythtv/osdimagecache.h --- mythtv-0.19/libs/libmythtv/osdimagecache.h 1970-01-01 10:00:00.000000000 +1000 +++ mythtv/libs/libmythtv/osdimagecache.h 2006-05-10 09:54:43.000000000 +1000 @@ -0,0 +1,74 @@ +// -*- Mode: c++ -*- + +// POSIX headers +#include + +// Qt headers +#include +#include +#include +#include +#include + +class OSDImageCacheValue +{ + public: + OSDImageCacheValue(QString cacheKey, + unsigned char *yuv, unsigned char *ybuffer, + unsigned char *ubuffer, unsigned char *vbuffer, + unsigned char *alpha, QRect imagesize); + + virtual ~OSDImageCacheValue(); + + uint GetSize(void) const { return m_size_in_bytes; } + QString GetKey(void) const { return m_cacheKey; } + + public: + unsigned char *m_yuv; + unsigned char *m_ybuffer; + unsigned char *m_ubuffer; + unsigned char *m_vbuffer; + unsigned char *m_alpha; + QRect m_imagesize; + + private: + uint m_size_in_bytes; + QString m_cacheKey; +}; + +typedef QAsciiCache img_cache_t; + +class OSDImageCache +{ + public: + OSDImageCache(); + virtual ~OSDImageCache(); + + bool InFileCache(const QString &key) const; + + bool Contains(const QString &key, bool useFile) const; + + OSDImageCacheValue *Get(const QString &key, bool useFile); + + void Insert(OSDImageCacheValue* value); + + void SaveToDisk(const OSDImageCacheValue *value); + + void Reset(void); + + static QString CreateKey(const QString &filename, + float wmult, float hmult, + int scalew, int scaleh); + + static QString ExtractOriginal(const QString &key); + + private: + mutable QMutex m_cacheLock; + img_cache_t m_imageCache; + int m_memHits; + int m_diskHits; + int m_misses; + + /// Limit on the maximum total size of OSD images cached in *memory*. + static uint kMaximumMemoryCacheSize; +}; diff -pruN mythtv-0.19/libs/libmythtv/osdlistbtntype.cpp mythtv/libs/libmythtv/osdlistbtntype.cpp --- mythtv-0.19/libs/libmythtv/osdlistbtntype.cpp 2005-12-05 11:39:09.000000000 +1000 +++ mythtv/libs/libmythtv/osdlistbtntype.cpp 2006-02-19 07:26:06.000000000 +1000 @@ -19,206 +19,148 @@ * * ============================================================ */ -#include +// ANSI C headers +#include +// C++ headers +#include +using namespace std; + +// Qt headers #include #include #include #include #include +// MythTV headers #include "mythcontext.h" #include "mythdialogs.h" - #include "osdlistbtntype.h" +#define LOC QString("OSDListTreeType: ") +#define LOC_ERR QString("OSDListTreeType, Error: ") -OSDGenericTree::OSDGenericTree(OSDGenericTree *parent, const QString &name, - const QString &action, int check, - OSDTypeImage *image, QString group) - : GenericTree(name) -{ - m_checkable = check; - m_action = action; - m_image = image; - m_parentButton = NULL; - - if (group != "") - m_group = group; - else - m_group = action; - - if (!action.isEmpty() && !action.isNull()) - setSelectable(true); - - if (parent) - parent->addNode(this); -} - -//////////////////////////////////////////////////////////////////////////// - -OSDListTreeType::OSDListTreeType(const QString &name, const QRect &area, - const QRect &levelsize, int levelspacing, - float wmult, float hmult) - : OSDType(name) +static QRect unbias(QRect rect, float wmult, float hmult) { - m_wmult = wmult; - m_hmult = hmult; - - m_totalarea = area; - m_levelsize = levelsize; - m_levelspacing = levelspacing; - - if (gContext->GetNumSetting("UseArrowAccels", 1)) - m_arrowAccel = true; - else - m_arrowAccel = false; - - levels = 0; - curlevel = -1; - - treetop = NULL; - currentpos = NULL; - - currentlevel = NULL; - - listLevels.setAutoDelete(true); - - m_active = NULL; - m_inactive = NULL; + return QRect((int)round(rect.x() / wmult), + (int)round(rect.y() / hmult), + (int)ceil( rect.width() / wmult), + (int)ceil( rect.height() / hmult)); +} + +static QRect bias(QRect rect, float wmult, float hmult) +{ + return QRect((int)round(rect.x() * wmult), + (int)round(rect.y() * hmult), + (int)ceil( rect.width() * wmult), + (int)ceil( rect.height() * hmult)); +} + +OSDListTreeType::OSDListTreeType( + const QString &name, const QRect &area, + const QRect &levelsize, int levelspacing, + float wmult, float hmult) + : OSDType(name), + treetop(NULL), currentpos(NULL), + m_active(NULL), m_inactive(NULL), + m_itemRegBeg(Qt::black), m_itemRegEnd(QColor(80,80,80)), + m_itemSelBeg(QColor(82,202,56)), m_itemSelEnd(QColor(52,152,56)), + m_itemRegAlpha(100), m_itemSelAlpha(255), + m_spacing(0), m_margin(0), + m_levelspacing(levelspacing), + m_totalarea(area), m_levelsize(levelsize), + m_unbiasedspacing(1.0f), m_unbiasedmargin(1.0f), + m_unbiasedarea(0,0,0,0), m_unbiasedsize(0,0,0,0), + m_wmult(wmult), m_hmult(hmult), + m_depth(0), m_levelnum(-1), + m_visible(true), + m_arrowAccel(gContext->GetNumSetting("UseArrowAccels", 1)) +{ + m_wmult = (wmult == 0.0f) ? 1.0f : wmult; + m_hmult = (hmult == 0.0f) ? 1.0f : hmult; + m_unbiasedarea = unbias(area, wmult, hmult); + m_unbiasedsize = unbias(levelsize, wmult, hmult); +} + +OSDListTreeType::~OSDListTreeType() +{ + OSDListBtnList::iterator it = listLevels.begin(); + for (; it != listLevels.end(); ++it) + delete *it; +} + +void OSDListTreeType::Reinit(float wmult, float hmult) +{ + m_wmult = (wmult == 0.0f) ? 1.0f : wmult; + m_hmult = (hmult == 0.0f) ? 1.0f : hmult; + m_spacing = (uint) round(m_unbiasedspacing * wmult); + m_margin = (uint) round(m_unbiasedmargin * wmult); + m_totalarea = bias(m_unbiasedarea, wmult, hmult); + m_levelsize = bias(m_unbiasedsize, wmult, hmult); + + if (!treetop || m_levelnum < 0) + return; + + // Save item indices + vector list; + for (uint i = 0; i <= (uint)m_levelnum; i++) + list.push_back(listLevels[i]->GetItemCurrentPos()); + + // Delete old OSD items + OSDListBtnList clone = listLevels; + listLevels.clear(); + OSDListBtnList::iterator it = clone.begin(); + for (; it != clone.end(); ++it) + delete *it; - SetItemRegColor(Qt::black,QColor(80,80,80),100); - SetItemSelColor(QColor(82,202,56),QColor(52,152,56),255); - - m_spacing = 0; - m_margin = 0; -} - -void OSDListTreeType::Reinit(float wchange, float hchange, float wmult, - float hmult) -{ - m_wmult = wmult; - m_hmult = hmult; - - m_spacing = (int)(m_spacing * wchange); - m_margin = (int)(m_margin * wchange); - - int width = (int)(m_totalarea.width() * wchange); - int height = (int)(m_totalarea.height() * hchange); - int x = (int)(m_totalarea.x() * wchange); - int y = (int)(m_totalarea.y() * hchange); - - m_totalarea = QRect(x, y, width, height); - - width = (int)(m_levelsize.width() * wchange); - height = (int)(m_levelsize.height() * hchange); - x = (int)(m_levelsize.x() * wchange); - y = (int)(m_levelsize.y() * hchange); - - m_levelsize = QRect(x, y, width, height); - - QPtrListIterator it(listLevels); - OSDListBtnType *child; - - while ((child = it.current()) != 0) - { - child->Reinit(wchange, hchange, wmult, hmult); - ++it; - } + // Create new OSD items + SetAsTree(treetop, &list); } void OSDListTreeType::SetGroupCheckState(QString group, int newState) { - QPtrListIterator it(listLevels); - OSDListBtnType *child; - while ((child = it.current()) != 0) - { - child->SetGroupCheckState(group, newState); - ++it; - } + OSDListBtnList::iterator it = listLevels.begin(); + for (; it != listLevels.end(); ++it) + (*it)->SetGroupCheckState(group, newState); } -void OSDListTreeType::SetItemRegColor(const QColor& beg, const QColor& end, - uint alpha) -{ - m_itemRegBeg = beg; - m_itemRegEnd = end; - m_itemRegAlpha = alpha; -} - -void OSDListTreeType::SetItemSelColor(const QColor& beg, const QColor& end, - uint alpha) -{ - m_itemSelBeg = beg; - m_itemSelEnd = end; - m_itemSelAlpha = alpha; -} - -void OSDListTreeType::SetFontActive(TTFFont *font) -{ - m_active = font; -} - -void OSDListTreeType::SetFontInactive(TTFFont *font) -{ - m_inactive = font; -} - -void OSDListTreeType::SetSpacing(int spacing) -{ - m_spacing = spacing; -} - -void OSDListTreeType::SetMargin(int margin) -{ - m_margin = margin; -} - -void OSDListTreeType::SetAsTree(OSDGenericTree *toplevel) +void OSDListTreeType::SetAsTree(OSDGenericTree *toplevel, + vector *select_list) { if (treetop) { listLevels.clear(); - currentlevel = NULL; - treetop = NULL; - currentpos = NULL; - levels = 0; - curlevel = -1; + treetop = NULL; + currentpos = NULL; + m_depth = 0; + m_levelnum = -1; } - levels = toplevel->calculateDepth(0) - 1; - - if (levels <= 0) + m_depth = toplevel->calculateDepth(0) - 1; + if (m_depth <= 0) { - cerr << "Need at least one level\n"; + VERBOSE(VB_IMPORTANT, LOC_ERR + "SetAsTree: Need at least one level"); return; } - currentpos = (OSDGenericTree *)toplevel->getChildAt(0); - + currentpos = (OSDGenericTree*) toplevel->getChildAt(0); if (!currentpos) { - cerr << "No top-level children?\n"; + VERBOSE(VB_IMPORTANT, LOC_ERR + "SetAsTree: Need top-level children"); return; } - treetop = toplevel; - - // just for now, remove later - if (levels > 2) - levels = 3; - - for (int i = 0; i < levels; i++) + // Create OSD buttons for all levels + for (uint i = 0; i < (uint)m_depth; i++) { QString levelname = QString("level%1").arg(i + 1); - QRect curlevelarea = m_levelsize; curlevelarea.moveBy(m_totalarea.x(), m_totalarea.y()); - curlevelarea.moveBy((m_levelsize.width() + m_levelspacing) * i, 0); - OSDListBtnType *newlevel = new OSDListBtnType(levelname, curlevelarea, - m_wmult, m_hmult, true); + OSDListBtnType *newlevel = new OSDListBtnType( + levelname, curlevelarea, m_wmult, m_hmult, true); newlevel->SetFontActive(m_active); newlevel->SetFontInactive(m_inactive); @@ -227,229 +169,200 @@ void OSDListTreeType::SetAsTree(OSDGener newlevel->SetSpacing(m_spacing); newlevel->SetMargin(m_margin); - listLevels.append(newlevel); + listLevels.push_back(newlevel); } - currentlevel = GetLevel(0); + // Set up needed levels and selects + vector slist; + slist.push_back(0); + if (select_list) + slist = *select_list; - if (!currentlevel) + currentpos = treetop = toplevel; + for (m_levelnum = 0; m_levelnum < (int)slist.size(); m_levelnum++) { - cerr << "Something is seriously wrong (currentlevel = NULL)\n"; - return; + FillLevelFromTree(currentpos, m_levelnum); + GetLevel(m_levelnum)->SetActive(true); + GetLevel(m_levelnum)->SetVisible(true); + if (slist[m_levelnum]) + GetLevel(m_levelnum)->SetItemCurrent(slist[m_levelnum]); + EnterItem(); // updates currentpos } - - FillLevelFromTree(toplevel, currentlevel); - - currentlevel->SetVisible(true); - currentlevel->SetActive(true); - - currentpos = (OSDGenericTree *)(currentlevel->GetItemFirst()->getData()); - curlevel = 0; - - emit itemEntered(this, currentpos); + m_levelnum--; } -OSDGenericTree *OSDListTreeType::GetCurrentPosition(void) +static bool has_action(QString action, const QStringList &actions) { - return currentpos; + QStringList::const_iterator it; + for (it = actions.begin(); it != actions.end(); ++it) + { + if (action == *it) + return true; + } + return false; } bool OSDListTreeType::HandleKeypress(QKeyEvent *e) { - if (!currentlevel) + QStringList actions; + bool ok = gContext->GetMainWindow()->TranslateKeyPress( + "TV Playback", e, actions); + + if (!ok || ((uint)m_levelnum >= listLevels.size())) return false; + else if (has_action("UP", actions)) + { + GetLevel(m_levelnum)->MoveUp(); + EnterItem(); + } + else if (has_action("DOWN", actions)) + { + GetLevel(m_levelnum)->MoveDown(); + EnterItem(); + } + else if (has_action("LEFT", actions) && (m_levelnum > 0)) + { + GetLevel(m_levelnum)->Reset(); + GetLevel(m_levelnum)->SetVisible(false); - bool handled = false; - QStringList actions; - if (gContext->GetMainWindow()->TranslateKeyPress("TV Playback", e, - actions)) + m_levelnum--; + EnterItem(); + } + else if ((has_action("LEFT", actions) && m_arrowAccel) || + has_action("ESCAPE", actions) || + has_action("CLEAROSD", actions) || + has_action("MENU", actions)) { - for (unsigned int i = 0; i < actions.size() && !handled; i++) - { - QString action = actions[i]; - handled = true; + m_visible = false; + } + else if (has_action("RIGHT", actions) && + (m_levelnum + 1 < m_depth) && + (currentpos->childCount() > 0)) + { + GetLevel(m_levelnum)->SetActive(false); + m_levelnum++; - if (action == "UP") - { - currentlevel->MoveUp(); - SetCurrentPosition(); - } - else if (action == "DOWN") - { - currentlevel->MoveDown(); - SetCurrentPosition(); - } - else if (action == "LEFT") - { - if (curlevel > 0) - { - currentlevel->Reset(); - currentlevel->SetVisible(false); - - curlevel--; - - currentlevel = GetLevel(curlevel); - currentlevel->SetActive(true); - SetCurrentPosition(); - } - else if (m_arrowAccel) - { - m_visible = false; - } - } - else if (action == "RIGHT") - { - // FIXME: create new levels if needed.. - if (curlevel + 1 < levels && currentpos->childCount() > 0) - { - currentlevel->SetActive(false); - - curlevel++; - - currentlevel = GetLevel(curlevel); - - FillLevelFromTree(currentpos, currentlevel); - - currentlevel->SetVisible(true); - currentlevel->SetActive(true); - SetCurrentPosition(); - } - else if (m_arrowAccel) - { - SetGroupCheckState(currentpos->getGroup(), - OSDListBtnTypeItem::NotChecked); - currentpos->getParentButton()->setChecked( - OSDListBtnTypeItem::FullChecked); - emit itemSelected(this, currentpos); - } - } - else if (action == "ESCAPE" || action == "MENU" || - action == "CLEAROSD") - m_visible = false; - else if (action == "SELECT") - { - SetGroupCheckState(currentpos->getGroup(), - OSDListBtnTypeItem::NotChecked); - currentpos->getParentButton()->setChecked( - OSDListBtnTypeItem::FullChecked); - emit itemSelected(this, currentpos); - } - else - handled = false; - } + FillLevelFromTree(currentpos, m_levelnum); + GetLevel(m_levelnum)->SetVisible(true); + EnterItem(); + } + else if ((has_action("RIGHT", actions) && m_arrowAccel) || + has_action("SELECT", actions)) + { + SelectItem(); + } + else + { + return false; } - return handled; + return true; } void OSDListTreeType::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff) { - QPtrListIterator it(listLevels); - OSDListBtnType *child; - - while ((child = it.current()) != 0) - { - child->Draw(surface, fade, maxfade, xoff, yoff); - ++it; - } + OSDListBtnList::iterator it = listLevels.begin(); + for (; it != listLevels.end(); ++it) + (*it)->Draw(surface, fade, maxfade, xoff, yoff); } void OSDListTreeType::FillLevelFromTree(OSDGenericTree *item, - OSDListBtnType *list) + uint level_num) { + OSDListBtnType *list = GetLevel(level_num); if (!list) { - VERBOSE(VB_IMPORTANT, "OSDListTreeType::FillLevelFromTree() " - "called with no list. Ignoring call."); + VERBOSE(VB_IMPORTANT, LOC_ERR + "FillLevelFromTree() " + "called with no list, ignoring."); return; } list->Reset(); QPtrList *itemlist = item->getAllChildren(); - QPtrListIterator it(*itemlist); - GenericTree *child; - while ((child = it.current()) != 0) - { - OSDGenericTree *osdchild = (OSDGenericTree *)child; + OSDGenericTree *child = (OSDGenericTree*) it.current(); + OSDListBtnTypeItem *newitem = NULL; + for (;(child = (OSDGenericTree*) it.current()); ++it) + { + OSDTypeImage *im = child->getImage(); + QString label = child->getString(); + QString group = child->getGroup(); + bool canCheck = child->getCheckable() >= 0; + bool hasCheck = child->getCheckable() == 1; + bool hasChild = child->childCount() > 0; - OSDListBtnTypeItem *newitem; - newitem = new OSDListBtnTypeItem(list, child->getString(), - osdchild->getImage(), - (osdchild->getCheckable() >= 0), - (child->childCount() > 0)); - if (osdchild->getCheckable() == 1) + newitem = new OSDListBtnTypeItem(list, label, im, canCheck, hasChild); + + if (hasCheck) newitem->setChecked(OSDListBtnTypeItem::FullChecked); - newitem->setGroup(osdchild->getGroup()); - newitem->setData(osdchild); - osdchild->setParentButton(newitem); + newitem->setGroup(group); + newitem->setData(child); - ++it; + child->setParentButton(newitem); } } -OSDListBtnType *OSDListTreeType::GetLevel(int levelnum) +OSDListBtnType *OSDListTreeType::GetLevel(uint levelnum) { - if ((uint)levelnum > listLevels.count()) - { - cerr << "OOB GetLevel call\n"; - return NULL; - } + if (levelnum < listLevels.size()) + return listLevels[levelnum]; - return listLevels.at(levelnum); + VERBOSE(VB_IMPORTANT, LOC_ERR + "GetLevel("<= listLevels.size()) return; - OSDListBtnTypeItem *lbt = currentlevel->GetItemCurrent(); + listLevels[m_levelnum]->SetActive(true); + OSDListBtnTypeItem *lbt = listLevels[m_levelnum]->GetItemCurrent(); + if (lbt) + { + currentpos = (OSDGenericTree*) (lbt->getData()); + emit itemEntered(this, currentpos); + } +} - if (!lbt) +void OSDListTreeType::SelectItem(void) +{ + if (!currentpos) return; - currentpos = (OSDGenericTree *)(lbt->getData()); - emit itemEntered(this, currentpos); + SetGroupCheckState(currentpos->getGroup(), OSDListBtnTypeItem::NotChecked); + currentpos->getParentButton()->setChecked(OSDListBtnTypeItem::FullChecked); + emit itemSelected(this, currentpos); } - + +#undef LOC_ERR +#undef LOC + ////////////////////////////////////////////////////////////////////////// OSDListBtnType::OSDListBtnType(const QString &name, const QRect &area, float wmult, float hmult, bool showScrollArrows) - : OSDType(name) + : OSDType(name), + m_order(0), m_rect(area), + m_contentsRect(0,0,0,0), m_arrowsRect(0,0,0,0), + m_wmult(wmult), m_hmult(hmult), + m_itemHeight(0), m_itemSpacing(0), + m_itemMargin(0), m_itemsVisible(0), + m_active(false), m_showScrollArrows(showScrollArrows), + m_showUpArrow(false), m_showDnArrow(false), + m_initialized(false), m_clearing(false), + m_visible(false), + m_itemRegBeg(Qt::black), m_itemRegEnd(QColor(80,80,80)), + m_itemSelBeg(QColor(82,202,56)), m_itemSelEnd(QColor(52,152,56)), + m_itemRegAlpha(100), m_itemSelAlpha(255), + m_fontActive(NULL), m_fontInactive(NULL), + m_topIndx(0), m_selIndx(0), + m_update(true) { - m_rect = area; - - m_wmult = wmult; - m_hmult = hmult; - - m_showScrollArrows = showScrollArrows; - - m_active = false; - m_showUpArrow = false; - m_showDnArrow = false; - - m_itemList.setAutoDelete(false); - m_topItem = 0; - m_selItem = 0; - - m_initialized = false; - m_clearing = false; - m_itemSpacing = 0; - m_itemMargin = 0; - m_itemHeight = 0; - m_itemsVisible = 0; - m_fontActive = 0; - m_fontInactive = 0; - - SetItemRegColor(Qt::black,QColor(80,80,80),100); - SetItemSelColor(QColor(82,202,56),QColor(52,152,56),255); - - m_visible = false; } OSDListBtnType::~OSDListBtnType() @@ -457,316 +370,198 @@ OSDListBtnType::~OSDListBtnType() Reset(); } -void OSDListBtnType::Reinit(float wchange, float hchange, float wmult, - float hmult) -{ - m_wmult = wmult; - m_hmult = hmult; - - m_itemHeight = (int)(m_itemHeight * hchange); - m_itemSpacing = (int)(m_itemSpacing * wchange); - m_itemMargin = (int)(m_itemMargin * wchange); - - int width = (int)(m_rect.width() * wchange); - int height = (int)(m_rect.height() * hchange); - int x = (int)(m_rect.x() * wchange); - int y = (int)(m_rect.y() * hchange); - - m_rect = QRect(x, y, width, height); - - Init(); - - OSDListBtnTypeItem* item = 0; - for (item = m_itemList.first(); item; item = m_itemList.next()) { - item->Reinit(wchange, hchange, wmult, hmult); - } - -} - void OSDListBtnType::SetGroupCheckState(QString group, int newState) { - OSDListBtnTypeItem* item = 0; - for (item = m_itemList.first(); item; item = m_itemList.next()) { - if (item->getGroup() == group) - item->setChecked((OSDListBtnTypeItem::CheckState)newState); - } -} - -void OSDListBtnType::SetItemRegColor(const QColor& beg, const QColor& end, - uint alpha) -{ - m_itemRegBeg = beg; - m_itemRegEnd = end; - m_itemRegAlpha = alpha; -} - -void OSDListBtnType::SetItemSelColor(const QColor& beg, const QColor& end, - uint alpha) -{ - m_itemSelBeg = beg; - m_itemSelEnd = end; - m_itemSelAlpha = alpha; -} - -void OSDListBtnType::SetFontActive(TTFFont *font) -{ - m_fontActive = font; -} - -void OSDListBtnType::SetFontInactive(TTFFont *font) -{ - m_fontInactive = font; -} - -void OSDListBtnType::SetSpacing(int spacing) -{ - m_itemSpacing = spacing; -} - -void OSDListBtnType::SetMargin(int margin) -{ - m_itemMargin = margin; + OSDListBtnItemList::iterator it; + for (it = m_itemList.begin(); it != m_itemList.end(); ++it) + if ((*it)->getGroup() == group) + (*it)->setChecked((OSDListBtnTypeItem::CheckState) newState); } -void OSDListBtnType::SetActive(bool active) -{ - m_active = active; -} - -void OSDListBtnType::Reset() +void OSDListBtnType::Reset(void) { QMutexLocker lock(&m_update); m_clearing = true; - - OSDListBtnTypeItem* item = 0; - for (item = m_itemList.first(); item; item = m_itemList.next()) { - delete item; - } - - m_clearing = false; + OSDListBtnItemList::iterator it; + OSDListBtnItemList clone = m_itemList; m_itemList.clear(); - - m_topItem = 0; - m_selItem = 0; + for (it = clone.begin(); it != clone.end(); ++it) + delete (*it); + m_clearing = false; + + m_topIndx = 0; + m_selIndx = 0; m_showUpArrow = false; m_showDnArrow = false; } void OSDListBtnType::InsertItem(OSDListBtnTypeItem *item) { - OSDListBtnTypeItem* lastItem = m_itemList.last(); - m_itemList.append(item); - - if (m_showScrollArrows && m_itemList.count() > m_itemsVisible) - m_showDnArrow = true; - else - m_showDnArrow = false; - - if (!lastItem) - { - m_topItem = item; - m_selItem = item; + QMutexLocker lock(&m_update); + m_itemList.push_back(item); + m_showDnArrow = m_showScrollArrows && m_itemList.size() > m_itemsVisible; + if (m_itemList.size() == 1) emit itemSelected(item); - } +} + +int find(const OSDListBtnItemList &list, const OSDListBtnTypeItem *item) +{ + for (uint i = 0; i < list.size(); i++) + if (list[i] == item) + return i; + return -1; } void OSDListBtnType::RemoveItem(OSDListBtnTypeItem *item) { + QMutexLocker lock(&m_update); if (m_clearing) return; - - if (m_itemList.find(item) == -1) - return; - m_topItem = m_itemList.first(); - m_selItem = m_itemList.first(); + int i = find(m_itemList, item); + if (i < 0) + return; - m_itemList.remove(item); + m_itemList.erase(m_itemList.begin()+i); m_showUpArrow = false; - - if (m_showScrollArrows && m_itemList.count() > m_itemsVisible) - m_showDnArrow = true; - else - m_showDnArrow = false; + m_showDnArrow = m_itemList.size() > m_itemsVisible; + m_selIndx = 0; + m_topIndx = 0; - if (m_selItem) { - emit itemSelected(m_selItem); - } + if (m_itemList.size()) + emit itemSelected(m_itemList[m_selIndx]); } -void OSDListBtnType::SetItemCurrent(OSDListBtnTypeItem* item) +void OSDListBtnType::SetItemCurrent(const OSDListBtnTypeItem* item) { - bool locked = m_update.tryLock(); + QMutexLocker lock(&m_update); + int i = find(m_itemList, item); + if (i >= 0) + SetItemCurrent(i); +} - if (m_itemList.find(item) == -1) +void OSDListBtnType::SetItemCurrent(uint current) +{ + QMutexLocker lock(&m_update); + if (current >= m_itemList.size()) return; - m_topItem = item; - m_selItem = item; - - if (m_showScrollArrows && m_itemList.count() > m_itemsVisible) - m_showDnArrow = true; - else - m_showDnArrow = false; - - emit itemSelected(m_selItem); - - if (locked) - m_update.unlock(); + m_selIndx = current; + m_topIndx = max(m_selIndx - (int)m_itemsVisible, 0); + m_showUpArrow = m_topIndx; + m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size(); + emit itemSelected(m_itemList[m_selIndx]); } -void OSDListBtnType::SetItemCurrent(int current) +int OSDListBtnType::GetItemCurrentPos(void) const { QMutexLocker lock(&m_update); - - OSDListBtnTypeItem* item = m_itemList.at(current); - if (!item) - item = m_itemList.first(); - - SetItemCurrent(item); + return (m_itemList.size()) ? m_selIndx : -1; } -OSDListBtnTypeItem* OSDListBtnType::GetItemCurrent() +OSDListBtnTypeItem* OSDListBtnType::GetItemCurrent(void) { - return m_selItem; + QMutexLocker lock(&m_update); + if (!m_itemList.size()) + return NULL; + return m_itemList[m_selIndx]; } -OSDListBtnTypeItem* OSDListBtnType::GetItemFirst() +OSDListBtnTypeItem* OSDListBtnType::GetItemFirst(void) { - return m_itemList.first(); + QMutexLocker lock(&m_update); + if (!m_itemList.size()) + return NULL; + return m_itemList[0]; } -OSDListBtnTypeItem* OSDListBtnType::GetItemNext(OSDListBtnTypeItem *item) +OSDListBtnTypeItem* OSDListBtnType::GetItemNext(const OSDListBtnTypeItem *item) { QMutexLocker lock(&m_update); - - if (m_itemList.find(item) == -1) - return 0; - - return m_itemList.next(); + int i = find(m_itemList, item) + 1; + if (i <= 0 || i >= (int)m_itemList.size()) + return NULL; + return m_itemList[i]; } -int OSDListBtnType::GetCount() +int OSDListBtnType::GetCount(void) const { - return m_itemList.count(); + QMutexLocker lock(&m_update); + return m_itemList.size(); } OSDListBtnTypeItem* OSDListBtnType::GetItemAt(int pos) { - return m_itemList.at(pos); + QMutexLocker lock(&m_update); + return m_itemList[pos]; } -int OSDListBtnType::GetItemPos(OSDListBtnTypeItem* item) +int OSDListBtnType::GetItemPos(const OSDListBtnTypeItem *item) const { QMutexLocker lock(&m_update); - - return m_itemList.find(item); + return find(m_itemList, item); } -void OSDListBtnType::MoveUp() +void OSDListBtnType::MoveUp(void) { QMutexLocker lock(&m_update); - - if (m_itemList.find(m_selItem) == -1) + if (!m_itemList.size()) return; - OSDListBtnTypeItem *item = m_itemList.prev(); - if (!item) + if (--m_selIndx < 0) { - item = m_itemList.last(); - if (!item) - return; - - if (m_itemList.count() > m_itemsVisible) - m_topItem = m_itemList.at(m_itemList.count() - m_itemsVisible); - else - m_topItem = m_itemList.first(); + m_selIndx = m_itemList.size() - 1; + m_topIndx = (m_itemList.size() > m_itemsVisible) ? + m_itemList.size() - m_itemsVisible : 0; } - m_selItem = item; - - if (m_itemList.find(m_selItem) < m_itemList.find(m_topItem)) - m_topItem = m_selItem; - - if (m_topItem != m_itemList.first()) - m_showUpArrow = true; - else - m_showUpArrow = false; - - if (m_itemList.find(m_topItem) + m_itemsVisible < m_itemList.count()) - m_showDnArrow = true; - else - m_showDnArrow = false; + m_topIndx = (m_selIndx < m_topIndx) ? m_selIndx : m_topIndx; + m_showUpArrow = m_topIndx; + m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size(); - emit itemSelected(m_selItem); + emit itemSelected(m_itemList[m_selIndx]); } -void OSDListBtnType::MoveDown() +void OSDListBtnType::MoveDown(void) { QMutexLocker lock(&m_update); - - if (m_itemList.find(m_selItem) == -1) + if (!m_itemList.size()) return; - OSDListBtnTypeItem *item = m_itemList.next(); - if (!item) - { - item = m_itemList.first(); - if (!item) - return; - - m_topItem = item; - } - - m_selItem = item; + if (++m_selIndx >= (int)m_itemList.size()) + m_selIndx = m_topIndx = 0; - if (m_itemList.find(m_topItem) + m_itemsVisible <= - (unsigned int)m_itemList.find(m_selItem)) - { - m_topItem = m_itemList.at(m_itemList.find(m_topItem) + 1); - } - - if (m_topItem != m_itemList.first()) - m_showUpArrow = true; - else - m_showUpArrow = false; - - if (m_itemList.find(m_topItem) + m_itemsVisible < m_itemList.count()) - m_showDnArrow = true; - else - m_showDnArrow = false; + bool scroll_down = m_topIndx + (int)m_itemsVisible <= m_selIndx; + m_topIndx = (scroll_down) ? m_topIndx + 1 : m_topIndx; + + m_showUpArrow = m_topIndx; + m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size(); - emit itemSelected(m_selItem); + emit itemSelected(m_itemList[m_selIndx]); } -void OSDListBtnType::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, - int yoff) +void OSDListBtnType::Draw(OSDSurface *surface, + int fade, int maxfade, + int xoff, int yoff) { - (void)xoff; - (void)yoff; - + QMutexLocker lock(&m_update); if (!m_visible) return; - - QMutexLocker lock(&m_update); - if (!m_initialized) Init(); TTFFont *font = m_active ? m_fontActive : m_fontInactive; int y = m_rect.y(); - m_itemList.find(m_topItem); - OSDListBtnTypeItem *it = m_itemList.current(); - while (it && (y - m_rect.y()) <= (m_contentsRect.height() - m_itemHeight)) + for (uint i = m_topIndx; i < m_itemList.size(); i++) { - it->paint(surface, font, fade, maxfade, m_rect.x()+ xoff, y + yoff); - + if (!((y - m_rect.y()) <= (m_contentsRect.height() - m_itemHeight))) + break; + m_itemList[i]->paint(surface, font, fade, maxfade, + m_rect.x() + xoff, y + yoff); y += m_itemHeight + m_itemSpacing; - - it = m_itemList.next(); } if (m_showScrollArrows) @@ -792,13 +587,12 @@ void OSDListBtnType::Draw(OSDSurface *su } } -void OSDListBtnType::Init() +void OSDListBtnType::Init(void) { int sz1 = m_fontActive->Size() * 3 / 2; int sz2 = m_fontInactive->Size() * 3 / 2; - m_itemHeight = QMAX(sz1, sz2) + (int)(2 * m_itemMargin); - - m_itemHeight = (m_itemHeight / 2) * 2; + m_itemHeight = max(sz1, sz2) + (int)(2 * m_itemMargin); + m_itemHeight = m_itemHeight & ~0x1; if (m_showScrollArrows) { @@ -838,11 +632,7 @@ void OSDListBtnType::Init() InitItem(m_itemSelActPix, itemWidth, m_itemHeight, m_itemSelBeg, m_itemSelEnd, 255); - if (m_itemList.count() > m_itemsVisible && m_showScrollArrows) - m_showDnArrow = true; - else - m_showDnArrow = false; - + m_showDnArrow = m_itemList.size() > m_itemsVisible && m_showScrollArrows; m_initialized = true; } @@ -885,68 +675,57 @@ void OSDListBtnType::InitItem( void OSDListBtnType::LoadPixmap(OSDTypeImage& pix, const QString& fileName) { - QString file = gContext->GetThemesParentDir() + "default/lb-" + fileName + ".png"; - pix.LoadImage(file, m_wmult, m_hmult); + QString path = gContext->GetThemesParentDir() + "default/lb-"; + pix.LoadImage(path + fileName + ".png", m_wmult, m_hmult); } ///////////////////////////////////////////////////////////////////////////// -OSDListBtnTypeItem::OSDListBtnTypeItem(OSDListBtnType* lbtype, - const QString& text, - OSDTypeImage *pixmap, bool checkable, - bool showArrow, CheckState state) -{ - m_parent = lbtype; - m_text = text; - m_pixmap = pixmap; - m_checkable = checkable; - m_state = state; - m_showArrow = showArrow; - m_data = 0; - +OSDListBtnTypeItem::OSDListBtnTypeItem( + OSDListBtnType *lbtype, const QString &text, + OSDTypeImage *pixmap, bool checkable, + bool showArrow, CheckState state) + : m_parent(lbtype), m_pixmap(pixmap), + m_data(NULL), m_text(text), + m_group(QString::null), m_state(state), + m_showArrow(showArrow), m_checkable(checkable), + m_checkRect(0,0,0,0), m_arrowRect(0,0,0,0), + m_pixmapRect(0,0,0,0), m_textRect(0,0,0,0) +{ if (!m_parent->m_initialized) m_parent->Init(); - int margin = m_parent->m_itemMargin; - int width = m_parent->m_rect.width(); - int height = m_parent->m_itemHeight; + OSDTypeImage &checkPix = m_parent->m_checkNonePix; + OSDTypeImage &arrowPix = m_parent->m_arrowPix; + + int margin = m_parent->m_itemMargin; + int width = m_parent->m_rect.width(); + int height = m_parent->m_itemHeight; + int cw = checkPix.ImageSize().width(); + int ch = checkPix.ImageSize().height(); + int aw = arrowPix.ImageSize().width(); + int ah = arrowPix.ImageSize().height(); + int pw = m_pixmap ? m_pixmap->ImageSize().width() : 0; + int ph = m_pixmap ? m_pixmap->ImageSize().height() : 0; - OSDTypeImage& checkPix = m_parent->m_checkNonePix; - OSDTypeImage& arrowPix = m_parent->m_arrowPix; - - int cw = checkPix.ImageSize().width(); - int ch = checkPix.ImageSize().height(); - int aw = arrowPix.ImageSize().width(); - int ah = arrowPix.ImageSize().height(); - int pw = m_pixmap ? m_pixmap->ImageSize().width() : 0; - int ph = m_pixmap ? m_pixmap->ImageSize().height() : 0; - if (m_checkable) - m_checkRect = QRect(margin, (height - ch)/2, cw, ch); - else - m_checkRect = QRect(0,0,0,0); + m_checkRect = QRect(margin, (height - ch)/2, cw, ch); if (m_showArrow) - m_arrowRect = QRect(width - aw - margin, (height - ah)/2, - aw, ah); - else - m_arrowRect = QRect(0,0,0,0); + m_arrowRect = QRect(width - aw - margin, (height - ah)/2, aw, ah); - if (m_pixmap) - m_pixmapRect = QRect(m_checkable ? (2*margin + m_checkRect.width()) : - margin, (height - ph)/2, - pw, ph); - else - m_pixmapRect = QRect(0,0,0,0); + if (m_pixmap) + { + int tmp = (m_checkable) ? (2 * margin + m_checkRect.width()) : margin; + m_pixmapRect = QRect(tmp, (height - ph)/2, pw, ph); + } - m_textRect = QRect(margin + - (m_checkable ? m_checkRect.width() + margin : 0) + - (m_pixmap ? m_pixmapRect.width() + margin : 0), - 0, - width - 2*margin - - (m_checkable ? m_checkRect.width() + margin : 0) - - (m_showArrow ? m_arrowRect.width() + margin : 0) - - (m_pixmap ? m_pixmapRect.width() + margin : 0), - height); + int tx = margin, tw = width - (2 * margin); + tx += (m_checkable) ? m_checkRect.width() + margin : 0; + tx += (m_pixmap) ? m_pixmapRect.width() + margin : 0; + tw -= (m_checkable) ? m_checkRect.width() + margin : 0; + tw -= (m_showArrow) ? m_arrowRect.width() + margin : 0; + tw -= (m_pixmap) ? m_pixmapRect.width() + margin : 0; + m_textRect = QRect(tx, 0, tw, height); m_parent->InsertItem(this); } @@ -957,52 +736,10 @@ OSDListBtnTypeItem::~OSDListBtnTypeItem( m_parent->RemoveItem(this); } -QString OSDListBtnTypeItem::text() const -{ - return m_text; -} - -const OSDTypeImage* OSDListBtnTypeItem::pixmap() const -{ - return m_pixmap; -} - -bool OSDListBtnTypeItem::checkable() const -{ - return m_checkable; -} - -OSDListBtnTypeItem::CheckState OSDListBtnTypeItem::state() const -{ - return m_state; -} - -OSDListBtnType* OSDListBtnTypeItem::parent() const -{ - return m_parent; -} - -void OSDListBtnTypeItem::setChecked(CheckState state) -{ - if (!m_checkable) - return; - m_state = state; -} - -void OSDListBtnTypeItem::setData(void *data) -{ - m_data = data; -} - -void* OSDListBtnTypeItem::getData() -{ - return m_data; -} - void OSDListBtnTypeItem::paint(OSDSurface *surface, TTFFont *font, int fade, int maxfade, int x, int y) { - if (this == m_parent->m_selItem) + if (this == m_parent->GetItemCurrent()) { if (m_parent->m_active) m_parent->m_itemSelActPix.Draw(surface, fade, maxfade, x, y); @@ -1030,11 +767,14 @@ void OSDListBtnTypeItem::paint(OSDSurfac cr.moveBy(x, y); if (m_state == HalfChecked) - m_parent->m_checkHalfPix.Draw(surface, fade, maxfade, cr.x(), cr.y()); + m_parent->m_checkHalfPix.Draw(surface, fade, maxfade, + cr.x(), cr.y()); else if (m_state == FullChecked) - m_parent->m_checkFullPix.Draw(surface, fade, maxfade, cr.x(), cr.y()); + m_parent->m_checkFullPix.Draw(surface, fade, maxfade, + cr.x(), cr.y()); else - m_parent->m_checkNonePix.Draw(surface, fade, maxfade, cr.x(), cr.y()); + m_parent->m_checkNonePix.Draw(surface, fade, maxfade, + cr.x(), cr.y()); } if (m_pixmap) @@ -1049,39 +789,3 @@ void OSDListBtnTypeItem::paint(OSDSurfac tr.moveBy(0, font->Size() / 4); font->DrawString(surface, tr.x(), tr.y(), m_text, tr.right(), tr.bottom()); } - -void OSDListBtnTypeItem::Reinit(float wchange, float hchange, - float wmult, float hmult) -{ - (void)wmult; - (void)hmult; - - int width = (int)(m_checkRect.width() * wchange); - int height = (int)(m_checkRect.height() * hchange); - int x = (int)(m_checkRect.x() * wchange); - int y = (int)(m_checkRect.y() * hchange); - - m_checkRect = QRect(x, y, width, height); - - width = (int)(m_pixmapRect.width() * wchange); - height = (int)(m_pixmapRect.height() * hchange); - x = (int)(m_pixmapRect.x() * wchange); - y = (int)(m_pixmapRect.y() * hchange); - - m_pixmapRect = QRect(x, y, width, height); - - width = (int)(m_textRect.width() * wchange); - height = (int)(m_textRect.height() * hchange); - x = (int)(m_textRect.x() * wchange); - y = (int)(m_textRect.y() * hchange); - - m_textRect = QRect(x, y, width, height); - - width = (int)(m_arrowRect.width() * wchange); - height = (int)(m_arrowRect.height() * hchange); - x = (int)(m_arrowRect.x() * wchange); - y = (int)(m_arrowRect.y() * hchange); - - m_arrowRect = QRect(x, y, width, height); -} - diff -pruN mythtv-0.19/libs/libmythtv/osdlistbtntype.h mythtv/libs/libmythtv/osdlistbtntype.h --- mythtv-0.19/libs/libmythtv/osdlistbtntype.h 2005-12-05 11:39:09.000000000 +1000 +++ mythtv/libs/libmythtv/osdlistbtntype.h 2006-02-19 07:26:06.000000000 +1000 @@ -1,3 +1,4 @@ +// -*- Mode: c++ -*- /* ============================================================ * File : uilistbtntype.h * Author: Renchi Raju @@ -22,38 +23,57 @@ #ifndef OSDLISTBTNTYPE_H #define OSDLISTBTNTYPE_H -#include "osdtypes.h" -#include "ttfont.h" +#include +using namespace std; + +// Qt headers #include #include #include #include +#include + +// MythTV headers +#include "osdtypes.h" +#include "ttfont.h" #include "generictree.h" -class OSDListBtnTypeItem; class OSDListBtnType; +class OSDListBtnTypeItem; +typedef vector OSDListBtnList; +typedef vector OSDListBtnItemList; class OSDGenericTree : public GenericTree { public: // This class will _not_ delete the image it's given, if any. - OSDGenericTree(OSDGenericTree *parent, const QString &name, - const QString &action = "", int check = -1, - OSDTypeImage *image = NULL, QString group = ""); - - OSDTypeImage *getImage(void) { return m_image; } - QString getAction(void) { return m_action; } - int getCheckable(void) { return m_checkable; } - QString getGroup(void) { return m_group; } + OSDGenericTree(OSDGenericTree *parent, const QString &name, + const QString &action = "", int check = -1, + OSDTypeImage *image = NULL, QString group = "") : + GenericTree(name), m_image(image), m_action(action), + m_group(group), m_checkable(check), m_parentButton(NULL) + { + m_group = (m_group.isEmpty()) ? action : m_group; + setSelectable(!action.isEmpty()); + if (parent) + parent->addNode(this); + } + + QString getAction(void) const { return m_action; } + QString getGroup(void) const { return m_group; } + int getCheckable(void) const { return m_checkable; } + + OSDTypeImage *getImage(void) { return m_image; } + OSDListBtnTypeItem *getParentButton(void) { return m_parentButton; } + void setParentButton(OSDListBtnTypeItem *button) - { m_parentButton = button; }; - OSDListBtnTypeItem *getParentButton(void) { return m_parentButton; }; + { m_parentButton = button; } private: - OSDTypeImage *m_image; - QString m_action; - int m_checkable; - QString m_group; + OSDTypeImage *m_image; + QString m_action; + QString m_group; + int m_checkable; OSDListBtnTypeItem *m_parentButton; }; @@ -62,52 +82,48 @@ class OSDListTreeType : public OSDType { Q_OBJECT public: - OSDListTreeType(const QString &name, const QRect &area, - const QRect &levelsize, int levelspacing, - float wmult, float hmult); + OSDListTreeType(const QString &name, const QRect &area, + const QRect &levelsize, int levelspacing, + float wmult, float hmult); + ~OSDListTreeType(); - void Reinit(float wchange, float hchange, float wmult, float hmult); - void SetGroupCheckState(QString group, int newState = 0); - - void SetFontActive(TTFFont *font); - void SetFontInactive(TTFFont *font); - void SetSpacing(int spacing); - void SetMargin(int margin); - void SetItemRegColor(const QColor& beg, const QColor& end, uint alpha); - void SetItemSelColor(const QColor& beg, const QColor& end, uint alpha); + bool IsVisible(void) const { return m_visible; } + + void SetFontActive(TTFFont *font) { m_active = font; } + void SetFontInactive(TTFFont *font) { m_inactive = font; } - void SetAsTree(OSDGenericTree *toplevel); + void SetGroupCheckState(QString group, int newState = 0); + void SetSpacing(uint spacing) + { m_unbiasedspacing = (m_spacing = spacing) / m_wmult; } + void SetMargin(uint margin) + { m_unbiasedmargin = (m_margin = margin) / m_wmult; } + void SetItemRegColor(const QColor& beg, const QColor& end, uint alpha) + { m_itemRegBeg = beg; m_itemRegEnd = end; m_itemRegAlpha = alpha; } + void SetItemSelColor(const QColor& beg, const QColor& end, uint alpha) + { m_itemSelBeg = beg; m_itemSelEnd = end; m_itemSelAlpha = alpha; } + void SetVisible(bool visible) { m_visible = visible; } + void SetAsTree(OSDGenericTree *toplevel, vector *select = NULL); - OSDGenericTree *GetCurrentPosition(void); - + void Reinit(float wmult, float hmult); bool HandleKeypress(QKeyEvent *e); - void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff); - bool IsVisible(void) { return m_visible; } - void SetVisible(bool visible) { m_visible = visible; } - signals: void itemSelected(OSDListTreeType *parent, OSDGenericTree *item); void itemEntered(OSDListTreeType *parent, OSDGenericTree *item); private: - void FillLevelFromTree(OSDGenericTree *item, OSDListBtnType *list); - OSDListBtnType *GetLevel(int levelnum); - void SetCurrentPosition(void); - - int levels; - int curlevel; + void FillLevelFromTree(OSDGenericTree *item, uint levelnum); + OSDListBtnType *GetLevel(uint levelnum); + void EnterItem(void); + void SelectItem(void); OSDGenericTree *treetop; OSDGenericTree *currentpos; + TTFFont *m_active; + TTFFont *m_inactive; - QPtrList listLevels; - - OSDListBtnType *currentlevel; - - TTFFont *m_active; - TTFFont *m_inactive; + OSDListBtnList listLevels; QColor m_itemRegBeg; QColor m_itemRegEnd; @@ -116,62 +132,76 @@ class OSDListTreeType : public OSDType uint m_itemRegAlpha; uint m_itemSelAlpha; - int m_spacing; - int m_margin; - - QRect m_totalarea; - QRect m_levelsize; - int m_levelspacing; + uint m_spacing; + uint m_margin; + int m_levelspacing; + + QRect m_totalarea; + QRect m_levelsize; + + float m_unbiasedspacing; + float m_unbiasedmargin; + QRect m_unbiasedarea; + QRect m_unbiasedsize; - float m_wmult; - float m_hmult; + float m_wmult; + float m_hmult; - bool m_visible; - bool m_arrowAccel; + int m_depth; + int m_levelnum; + bool m_visible; + bool m_arrowAccel; }; class OSDListBtnType : public OSDType { + friend class OSDListBtnTypeItem; Q_OBJECT + public: OSDListBtnType(const QString &name, const QRect& area, float wmult, float hmult, bool showScrollArrows = false); ~OSDListBtnType(); - void Reinit(float wchange, float hchange, float wmult, float hmult); - void SetGroupCheckState(QString group, int newState = 0); + // General Gets + bool IsVisible() const { return m_visible; } - void SetFontActive(TTFFont *font); - void SetFontInactive(TTFFont *font); - void SetSpacing(int spacing); - void SetMargin(int margin); - void SetItemRegColor(const QColor& beg, const QColor& end, uint alpha); - void SetItemSelColor(const QColor& beg, const QColor& end, uint alpha); - - void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff); - - void SetActive(bool active); - void Reset(); + // General Sets + void SetFontActive(TTFFont *font) { m_fontActive = font; } + void SetFontInactive(TTFFont *font) { m_fontInactive = font; } + void SetSpacing(int spacing) { m_itemSpacing = spacing; } + void SetMargin(int margin) { m_itemMargin = margin; } + void SetActive(bool active) { m_active = active; } + void SetVisible(bool vis) { m_visible = vis; } + void SetItemRegColor(const QColor& beg, const QColor& end, uint alpha) + { m_itemRegBeg = beg; m_itemRegEnd = end; m_itemRegAlpha = alpha; } + void SetItemSelColor(const QColor& beg, const QColor& end, uint alpha) + { m_itemSelBeg = beg; m_itemSelEnd = end; m_itemSelAlpha = alpha; } + void SetGroupCheckState(QString group, int newState = 0); + void SetItemCurrent(const OSDListBtnTypeItem* item); + void SetItemCurrent(uint pos); - void SetItemCurrent(OSDListBtnTypeItem* item); - void SetItemCurrent(int pos); - OSDListBtnTypeItem* GetItemCurrent(); - OSDListBtnTypeItem* GetItemFirst(); - OSDListBtnTypeItem* GetItemNext(OSDListBtnTypeItem *item); + // Item Gets + int GetCount(void) const; + int GetItemPos(const OSDListBtnTypeItem* item) const; + int GetItemCurrentPos() const; + OSDListBtnTypeItem* GetItemCurrent(void); + OSDListBtnTypeItem* GetItemFirst(void); + OSDListBtnTypeItem* GetItemNext(const OSDListBtnTypeItem *item); OSDListBtnTypeItem* GetItemAt(int pos); - int GetItemPos(OSDListBtnTypeItem* item); - int GetCount(); - void MoveDown(); - void MoveUp(); + // Item Sets/Commands + void MoveDown(void); + void MoveUp(void); - bool IsVisible() { return m_visible; } - void SetVisible(bool vis) { m_visible = vis; } + // General Commands + void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff); + void Reinit(float,float) {} + void Reset(void); private: - - void Init(); + void Init(void); void InitItem(OSDTypeImage &osdImg, uint width, uint height, QColor beg, QColor end, int alpha); void LoadPixmap(OSDTypeImage& pix, const QString& fileName); @@ -179,23 +209,34 @@ class OSDListBtnType : public OSDType void InsertItem(OSDListBtnTypeItem *item); void RemoveItem(OSDListBtnTypeItem *item); - int m_order; - QRect m_rect; - QRect m_contentsRect; - QRect m_arrowsRect; - - float m_wmult; - float m_hmult; - - int m_itemHeight; - int m_itemSpacing; - int m_itemMargin; - uint m_itemsVisible; - - bool m_active; - bool m_showScrollArrows; - bool m_showUpArrow; - bool m_showDnArrow; + private: + int m_order; + QRect m_rect; + QRect m_contentsRect; + QRect m_arrowsRect; + + float m_wmult; + float m_hmult; + + int m_itemHeight; + int m_itemSpacing; + int m_itemMargin; + uint m_itemsVisible; + + bool m_active; + bool m_showScrollArrows; + bool m_showUpArrow; + bool m_showDnArrow; + bool m_initialized; + bool m_clearing; + bool m_visible; + + QColor m_itemRegBeg; + QColor m_itemRegEnd; + QColor m_itemSelBeg; + QColor m_itemSelEnd; + uint m_itemRegAlpha; + uint m_itemSelAlpha; OSDTypeImage m_itemRegPix; OSDTypeImage m_itemSelActPix; @@ -209,43 +250,30 @@ class OSDListBtnType : public OSDType OSDTypeImage m_checkHalfPix; OSDTypeImage m_checkFullPix; - QColor m_itemRegBeg; - QColor m_itemRegEnd; - QColor m_itemSelBeg; - QColor m_itemSelEnd; - uint m_itemRegAlpha; - uint m_itemSelAlpha; - - TTFFont* m_fontActive; - TTFFont* m_fontInactive; - - bool m_initialized; - bool m_clearing; + TTFFont *m_fontActive; + TTFFont *m_fontInactive; - OSDListBtnTypeItem* m_topItem; - OSDListBtnTypeItem* m_selItem; - QPtrList m_itemList; + int m_topIndx; + int m_selIndx; - QMutex m_update; + OSDListBtnItemList m_itemList; - bool m_visible; + mutable QMutex m_update; - friend class OSDListBtnTypeItem; - signals: - void itemSelected(OSDListBtnTypeItem* item); }; class OSDListBtnTypeItem { + friend class OSDListBtnType; public: - - enum CheckState { - NotChecked=0, + enum CheckState + { + NotChecked = 0, HalfChecked, - FullChecked + FullChecked, }; OSDListBtnTypeItem(OSDListBtnType* lbtype, const QString& text, @@ -253,41 +281,36 @@ class OSDListBtnTypeItem bool showArrow = false, CheckState state = NotChecked); ~OSDListBtnTypeItem(); - OSDListBtnType* parent() const; - QString text() const; - const OSDTypeImage* pixmap() const; - bool checkable() const; - CheckState state() const; - - void setChecked(CheckState state); - void setData(void *data); - void* getData(); - void setGroup(QString group) { m_group = group; }; - QString getGroup(void) { return m_group; } + OSDListBtnType* parent(void) const { return m_parent; } + QString text(void) const { return m_text; } + const OSDTypeImage* pixmap(void) const { return m_pixmap; } + bool checkable(void) const { return m_checkable; } + CheckState state(void) const { return m_state; } + QString getGroup(void) const { return m_group; } + void *getData(void) { return m_data; } + + void setData(void *data) { m_data = data; } + void setGroup(QString grp) { m_group = grp; } + void setChecked(CheckState state) + { m_state = (m_checkable) ? state : m_state; } - void Reinit(float wchange, float hchange, float wmult, float hmult); - + void Reinit(float,float) {} void paint(OSDSurface *surface, TTFFont *font, int fade, int maxfade, int x, int y); protected: - OSDListBtnType *m_parent; - QString m_text; - OSDTypeImage *m_pixmap; - bool m_checkable; - CheckState m_state; - void *m_data; - QString m_group; - - QRect m_checkRect; - QRect m_pixmapRect; - QRect m_textRect; - QRect m_arrowRect; - - bool m_showArrow; - - friend class OSDListBtnType; + OSDTypeImage *m_pixmap; + void *m_data; + QString m_text; + QString m_group; + CheckState m_state; + bool m_showArrow; + bool m_checkable; + QRect m_checkRect; + QRect m_arrowRect; + QRect m_pixmapRect; + QRect m_textRect; }; diff -pruN mythtv-0.19/libs/libmythtv/osdtypes.cpp mythtv/libs/libmythtv/osdtypes.cpp --- mythtv-0.19/libs/libmythtv/osdtypes.cpp 2005-12-05 16:40:28.000000000 +1000 +++ mythtv/libs/libmythtv/osdtypes.cpp 2006-05-14 01:45:17.000000000 +1000 @@ -14,6 +14,9 @@ using namespace std; #include "mythcontext.h" +/// Shared OSD image cache +OSDImageCache OSDTypeImage::c_cache; + OSDSet::OSDSet(const QString &name, bool cache, int screenwidth, int screenheight, float wmult, float hmult, int frint) : QObject() @@ -160,9 +163,6 @@ void OSDSet::Reinit(int screenwidth, int int displaywidth, int displayheight, float wmult, float hmult, int frint) { - float wchange = wmult / m_wmult; - float hchange = hmult / m_hmult; - m_frameint = frint; m_screenwidth = screenwidth; @@ -175,57 +175,12 @@ void OSDSet::Reinit(int screenwidth, int vector::iterator iter = allTypes->begin(); for (;iter != allTypes->end(); iter++) { - OSDType *type = (*iter); - if (OSDTypeText *item = dynamic_cast(type)) - { - item->Reinit(wchange, hchange); - } - else if (OSDTypePositionImage *item = - dynamic_cast(type)) - { - item->Reinit(wchange, hchange, wmult, hmult); - } - else if (OSDTypePosSlider *item = dynamic_cast(type)) - { - item->Reinit(wchange, hchange, wmult, hmult); - } - else if (OSDTypeFillSlider *item = - dynamic_cast(type)) - { - item->Reinit(wchange, hchange, wmult, hmult); - } - else if (OSDTypeEditSlider *item = - dynamic_cast(type)) - { - item->Reinit(wchange, hchange, wmult, hmult); - } - else if (OSDTypeImage *item = dynamic_cast(type)) - { - item->Reinit(wchange, hchange, wmult, hmult); - } - else if (OSDTypeBox *item = dynamic_cast(type)) - { - item->Reinit(wchange, hchange); - } - else if (OSDTypePositionRectangle *item = - dynamic_cast(type)) - { - item->Reinit(wchange, hchange); - } - else if (OSDTypeCC *item = dynamic_cast(type)) - { - item->Reinit(xoff, yoff, displaywidth, displayheight); - } - else if (OSDListTreeType *item = dynamic_cast(type)) - { - item->Reinit(wchange, hchange, wmult, hmult); - } + if (OSDTypeCC *cc608 = dynamic_cast(*iter)) + cc608->Reinit(xoff, yoff, displaywidth, displayheight, + wmult, hmult); else - { - cerr << "Unknown conversion\n"; - } + (*iter)->Reinit(wmult, hmult); } - } OSDType *OSDSet::GetType(const QString &name) @@ -443,7 +398,8 @@ OSDType::~OSDType() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OSDTypeText::OSDTypeText(const QString &name, TTFFont *font, - const QString &text, QRect displayrect) + const QString &text, QRect displayrect, + float wmult, float hmult) : OSDType(name) { m_message = text; @@ -464,6 +420,12 @@ OSDTypeText::OSDTypeText(const QString & m_scrollinit = false; m_linespacing = 1.5; + + m_unbiasedsize = + QRect((int)round(m_screensize.x() / wmult), + (int)round(m_screensize.y() / hmult), + (int)ceil( m_screensize.width() / wmult), + (int)ceil( m_screensize.height() / hmult)); } OSDTypeText::OSDTypeText(const OSDTypeText &other) @@ -507,14 +469,13 @@ void OSDTypeText::SetDefaultText(const Q m_scrollinit = false; } -void OSDTypeText::Reinit(float wchange, float hchange) +void OSDTypeText::Reinit(float wmult, float hmult) { - int width = (int)(m_screensize.width() * wchange); - int height = (int)(m_screensize.height() * hchange); - int x = (int)(m_screensize.x() * wchange); - int y = (int)(m_screensize.y() * hchange); - - m_displaysize = m_screensize = QRect(x, y, width, height); + m_displaysize = m_screensize = + QRect((int)round(m_unbiasedsize.x() * wmult), + (int)round(m_unbiasedsize.y() * hmult), + (int)ceil( m_unbiasedsize.width() * wmult), + (int)ceil( m_unbiasedsize.height() * hmult)); } void OSDTypeText::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, @@ -708,7 +669,7 @@ OSDTypeImage::OSDTypeImage(const QString m_onlyusefirst = false; m_filename = filename; - m_displaypos = displaypos; + SetPosition(displaypos, wmult, hmult); m_yuv = m_alpha = NULL; m_isvalid = false; @@ -716,6 +677,7 @@ OSDTypeImage::OSDTypeImage(const QString m_scalew = scalew; m_scaleh = scaleh; + m_cacheitem = NULL; LoadImage(filename, wmult, hmult, scalew, scaleh); } @@ -733,6 +695,7 @@ OSDTypeImage::OSDTypeImage(const OSDType m_name = other.m_name; m_scalew = other.m_scalew; m_scaleh = other.m_scaleh; + m_cacheitem = NULL; m_alpha = m_yuv = NULL; if (m_isvalid) @@ -760,6 +723,8 @@ OSDTypeImage::OSDTypeImage(const QString m_onlyusefirst = false; m_displaypos = QPoint(0, 0); + m_unbiasedpos = QPoint(0, 0); + m_cacheitem = NULL; m_yuv = NULL; m_alpha = NULL; @@ -778,6 +743,8 @@ OSDTypeImage::OSDTypeImage(void) m_onlyusefirst = false; m_displaypos = QPoint(0, 0); + m_unbiasedpos = QPoint(0, 0); + m_cacheitem = NULL; m_yuv = NULL; m_alpha = NULL; @@ -790,10 +757,14 @@ OSDTypeImage::OSDTypeImage(void) OSDTypeImage::~OSDTypeImage() { - if (m_yuv) - delete [] m_yuv; - if (m_alpha) - delete [] m_alpha; + // In case we have a cache item in hand, it's safe to delete it, + // as it should not be in OSDImageCache anymore and it should have + // been written to the file cache for faster access in the future. + if (m_cacheitem) + { + delete m_cacheitem; + m_cacheitem = NULL; + } } void OSDTypeImage::SetName(const QString &name) @@ -801,13 +772,19 @@ void OSDTypeImage::SetName(const QString m_name = name; } -void OSDTypeImage::Reinit(float wchange, float hchange, float wmult, float hmult) +void OSDTypeImage::SetPosition(QPoint pos, float wmult, float hmult) { - int x = (int)(m_displaypos.x() * wchange); - int y = (int)(m_displaypos.y() * hchange); + m_displaypos = pos; + m_unbiasedpos = + QPoint((int)round(pos.x() / wmult), + (int)round(pos.y() / hmult)); +} - m_displaypos.setX(x); - m_displaypos.setY(y); +void OSDTypeImage::Reinit(float wmult, float hmult) +{ + m_displaypos = + QPoint((int)round(m_unbiasedpos.x() * wmult), + (int)round(m_unbiasedpos.y() * hmult)); LoadImage(m_filename, wmult, hmult, m_scalew, m_scaleh); } @@ -815,20 +792,44 @@ void OSDTypeImage::Reinit(float wchange, void OSDTypeImage::LoadImage(const QString &filename, float wmult, float hmult, int scalew, int scaleh) { - if (m_isvalid) + QString ckey; + + if (!filename.isEmpty() && filename.length() >= 2) { - if (m_yuv) - delete [] m_yuv; - if (m_alpha) - delete [] m_alpha; - - m_isvalid = false; - m_yuv = NULL; - m_alpha = NULL; + ckey = OSDImageCache::CreateKey( + filename, wmult, hmult, scalew, scaleh); + } + else + { + // this method requires a backing file + return; } + + // Get the item from the cache so it's not freed while in use + OSDImageCacheValue* value = c_cache.Get(ckey, true); + + if (value != NULL) + { + m_yuv = value->m_yuv; + m_ybuffer = value->m_ybuffer; + m_ubuffer = value->m_ubuffer; + m_vbuffer = value->m_vbuffer; + m_alpha = value->m_alpha; + m_imagesize = value->m_imagesize; + m_isvalid = true; + + // Put the old image back to the cache so it can be reused in the + // future, and possibly freed by the cache system if the size limit + // is reached + if (!m_cacheitem) + c_cache.Insert(m_cacheitem); + m_cacheitem = value; - if (filename.length() < 2) return; + } + + // scaled image was not found in cache, have to create it + QImage tmpimage(filename); @@ -867,17 +868,32 @@ void OSDTypeImage::LoadImage(const QStri imwidth, imheight, tmp2.width()); m_imagesize = QRect(0, 0, imwidth, imheight); + + // put the old image back to the cache so it can be reused in the + // future, and possibly freed by the cache system if the size limit + // is reached + if (m_cacheitem) + c_cache.Insert(m_cacheitem); + + m_cacheitem = new OSDImageCacheValue( + ckey, + m_yuv, m_ybuffer, m_ubuffer, + m_vbuffer, m_alpha, m_imagesize); + + // save the new cache item to the file cache + if (!filename.isEmpty()) + c_cache.SaveToDisk(m_cacheitem); } void OSDTypeImage::LoadFromQImage(const QImage &img) { + // this method is not cached as it's used mostly for + // subtitles which are displayed only once anyways, caching + // would probably only slow things down overall if (m_isvalid) { - if (m_yuv) - delete [] m_yuv; - if (m_alpha) - delete [] m_alpha; - + delete m_cacheitem; + m_cacheitem = NULL; m_isvalid = false; m_yuv = NULL; m_alpha = NULL; @@ -1043,23 +1059,25 @@ OSDTypePosSlider::OSDTypePosSlider(const m_maxval = 1000; m_curval = 0; m_displayrect = displayrect; + m_unbiasedrect = + QRect((int)round(m_displayrect.x() / wmult), + (int)round(m_displayrect.y() / hmult), + (int)ceil( m_displayrect.width() / wmult), + (int)ceil( m_displayrect.height() / hmult)); } OSDTypePosSlider::~OSDTypePosSlider() { } -void OSDTypePosSlider::Reinit(float wchange, float hchange, float wmult, - float hmult) +void OSDTypePosSlider::Reinit(float wmult, float hmult) { - int width = (int)(m_displayrect.width() * wchange); - int height = (int)(m_displayrect.height() * hchange); - int x = (int)(m_displayrect.x() * wchange); - int y = (int)(m_displayrect.y() * hchange); - - m_displayrect = QRect(x, y, width, height); - - OSDTypeImage::Reinit(wchange, hchange, wmult, hmult); + m_displayrect = + QRect((int)round(m_unbiasedrect.x() * wmult), + (int)round(m_unbiasedrect.y() * hmult), + (int)ceil( m_unbiasedrect.width() * wmult), + (int)ceil( m_unbiasedrect.height() * hmult)); + OSDTypeImage::Reinit(wmult, hmult); } void OSDTypePosSlider::SetPosition(int pos) @@ -1092,23 +1110,25 @@ OSDTypeFillSlider::OSDTypeFillSlider(con m_drawwidth = 0; m_onlyusefirst = true; m_displayrect = displayrect; + m_unbiasedrect = + QRect((int)round(m_displayrect.x() / wmult), + (int)round(m_displayrect.y() / hmult), + (int)ceil( m_displayrect.width() / wmult), + (int)ceil( m_displayrect.height() / hmult)); } OSDTypeFillSlider::~OSDTypeFillSlider() { } -void OSDTypeFillSlider::Reinit(float wchange, float hchange, float wmult, - float hmult) +void OSDTypeFillSlider::Reinit(float wmult, float hmult) { - int width = (int)(m_displayrect.width() * wchange); - int height = (int)(m_displayrect.height() * hchange); - int x = (int)(m_displayrect.x() * wchange); - int y = (int)(m_displayrect.y() * hchange); - - m_displayrect = QRect(x, y, width, height); - - OSDTypeImage::Reinit(wchange, hchange, wmult, hmult); + m_displayrect = + QRect((int)round(m_unbiasedrect.x() * wmult), + (int)round(m_unbiasedrect.y() * hmult), + (int)ceil( m_unbiasedrect.width() * wmult), + (int)ceil( m_unbiasedrect.height() * hmult)); + OSDTypeImage::Reinit(wmult, hmult); } void OSDTypeFillSlider::SetPosition(int pos) @@ -1143,6 +1163,11 @@ OSDTypeEditSlider::OSDTypeEditSlider(con m_maxval = 1000; m_curval = 0; m_displayrect = displayrect; + m_unbiasedrect = + QRect((int)round(m_displayrect.x() / wmult), + (int)round(m_displayrect.y() / hmult), + (int)ceil( m_displayrect.width() / wmult), + (int)ceil( m_displayrect.height() / hmult)); m_drawwidth = displayrect.width(); m_drawMap = new unsigned char[m_drawwidth + 1]; @@ -1162,6 +1187,7 @@ OSDTypeEditSlider::OSDTypeEditSlider(con m_scalew = scalew; m_scaleh = scaleh; + m_cacheitem = NULL; LoadImage(m_redname, wmult, hmult, scalew, scaleh); if (m_isvalid) @@ -1184,22 +1210,16 @@ OSDTypeEditSlider::OSDTypeEditSlider(con OSDTypeEditSlider::~OSDTypeEditSlider() { delete [] m_drawMap; - - if (m_ryuv) - delete [] m_ryuv; - if (m_ralpha) - delete [] m_ralpha; } -void OSDTypeEditSlider::Reinit(float wchange, float hchange, float wmult, - float hmult) +void OSDTypeEditSlider::Reinit(float wmult, float hmult) { - int width = (int)(m_displayrect.width() * wchange); - int height = (int)(m_displayrect.height() * hchange); - int x = (int)(m_displayrect.x() * wchange); - int y = (int)(m_displayrect.y() * hchange); + m_displayrect = + QRect((int)round(m_unbiasedrect.x() * wmult), + (int)round(m_unbiasedrect.y() * hmult), + (int)ceil( m_unbiasedrect.width() * wmult), + (int)ceil( m_unbiasedrect.height() * hmult)); - m_displayrect = QRect(x, y, width, height); m_drawwidth = m_displayrect.width(); delete [] m_drawMap; @@ -1210,11 +1230,6 @@ void OSDTypeEditSlider::Reinit(float wch m_displaypos = m_displayrect.topLeft(); - if (m_ryuv) - delete [] m_ryuv; - if (m_ralpha) - delete [] m_ralpha; - LoadImage(m_redname, wmult, hmult, m_scalew, m_scaleh); if (m_isvalid) { @@ -1360,30 +1375,46 @@ void OSDTypeEditSlider::Draw(OSDSurface //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -OSDTypeBox::OSDTypeBox(const QString &name, QRect displayrect) - : OSDType(name) +OSDTypeBox::OSDTypeBox(const QString &name, QRect displayrect, + float wmult, float hmult) + : OSDType(name) { size = displayrect; + m_unbiasedsize = + QRect((int)round(size.x() / wmult), + (int)round(size.y() / hmult), + (int)ceil( size.width() / wmult), + (int)ceil( size.height() / hmult)); +} + +void OSDTypeBox::SetRect(QRect newrect, float wmult, float hmult) +{ + size = newrect; + m_unbiasedsize = + QRect((int)round(size.x() / wmult), + (int)round(size.y() / hmult), + (int)ceil( size.width() / wmult), + (int)ceil( size.height() / hmult)); } OSDTypeBox::OSDTypeBox(const OSDTypeBox &other) : OSDType(other.m_name) { size = other.size; + m_unbiasedsize = other.m_unbiasedsize; } OSDTypeBox::~OSDTypeBox() { } -void OSDTypeBox::Reinit(float wchange, float hchange) +void OSDTypeBox::Reinit(float wmult, float hmult) { - int width = (int)(size.width() * wchange); - int height = (int)(size.height() * hchange); - int x = (int)(size.x() * wchange); - int y = (int)(size.y() * hchange); - - size = QRect(x, y, width, height); + size = + QRect((int)round(m_unbiasedsize.x() * wmult), + (int)round(m_unbiasedsize.y() * hmult), + (int)ceil( m_unbiasedsize.width() * wmult), + (int)ceil( m_unbiasedsize.height() * hmult)); } void OSDTypeBox::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, @@ -1498,44 +1529,52 @@ OSDTypePositionRectangle::OSDTypePositio } OSDTypePositionRectangle::OSDTypePositionRectangle( - const OSDTypePositionRectangle &other) - : OSDType(other.m_name), OSDTypePositionIndicator(other) + const OSDTypePositionRectangle &other) + : OSDType(other.m_name), OSDTypePositionIndicator(other) { for (int i = 0; i < m_numpositions; i++) { QRect tmp = other.positions[i]; positions.push_back(tmp); } + for (int i = 0; i < m_numpositions; i++) + { + QRect tmp = other.unbiasedpos[i]; + unbiasedpos.push_back(tmp); + } } OSDTypePositionRectangle::~OSDTypePositionRectangle() { } -void OSDTypePositionRectangle::Reinit(float wchange, float hchange) +void OSDTypePositionRectangle::Reinit(float wmult, float hmult) { for (int i = 0; i < m_numpositions; i++) { - QRect tmp = positions[i]; - - int width = (int)(tmp.width() * wchange); - int height = (int)(tmp.height() * hchange); - int x = (int)(tmp.x() * wchange); - int y = (int)(tmp.y() * hchange); - - tmp = QRect(x, y, width, height); - positions[i] = tmp; + QRect tmp = unbiasedpos[i]; + positions[i] = + QRect((int)round(tmp.x() * wmult), + (int)round(tmp.y() * hmult), + (int)ceil( tmp.width() * wmult), + (int)ceil( tmp.height() * hmult)); } } -void OSDTypePositionRectangle::AddPosition(QRect rect) +void OSDTypePositionRectangle::AddPosition( + QRect rect, float wmult, float hmult) { positions.push_back(rect); + unbiasedpos.push_back( + QRect((int)round(rect.x() / wmult), + (int)round(rect.y() / hmult), + (int)ceil( rect.width() / wmult), + (int)ceil( rect.height() / hmult))); m_numpositions++; } -void OSDTypePositionRectangle::Draw(OSDSurface *surface, int fade, int maxfade, - int xoff, int yoff) +void OSDTypePositionRectangle::Draw( + OSDSurface *surface, int fade, int maxfade, int xoff, int yoff) { fade = fade; maxfade = maxfade; @@ -1618,17 +1657,21 @@ void OSDTypePositionRectangle::Draw(OSDS //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OSDTypePositionImage::OSDTypePositionImage(const QString &name) - : OSDTypeImage(name), OSDTypePositionIndicator() + : OSDTypeImage(name), OSDTypePositionIndicator(), + m_wmult(0.0f), m_hmult(0.0f) { } OSDTypePositionImage::OSDTypePositionImage(const OSDTypePositionImage &other) : OSDTypeImage(other), OSDTypePositionIndicator(other) { + m_wmult = other.m_wmult; + m_hmult = other.m_hmult; + for (int i = 0; i < m_numpositions; i++) { - QPoint tmp = other.positions[i]; - positions.push_back(tmp); + positions.push_back(other.positions[i]); + unbiasedpos.push_back(other.unbiasedpos[i]); } } @@ -1636,45 +1679,61 @@ OSDTypePositionImage::~OSDTypePositionIm { } -void OSDTypePositionImage::Reinit(float wchange, float hchange, float wmult, - float hmult) +void OSDTypePositionImage::Reinit(float wmult, float hmult) { - OSDTypeImage::Reinit(wchange, hchange, wmult, hmult); + m_wmult = wmult; + m_hmult = hmult; + + OSDTypeImage::Reinit(wmult, hmult); for (int i = 0; i < m_numpositions; i++) { - QPoint tmp = positions[i]; - - int x = (int)(tmp.x() * wchange); - int y = (int)(tmp.y() * hchange); - - positions[i].setX(x); - positions[i].setY(y); + positions[i] = + QPoint((int)round(unbiasedpos[i].x() * wmult), + (int)round(unbiasedpos[i].y() * hmult)); } } -void OSDTypePositionImage::AddPosition(QPoint pos) +void OSDTypePositionImage::AddPosition(QPoint pos, float wmult, float hmult) { + if (m_wmult == 0.0f || m_hmult == 0.0f) + { + m_wmult = wmult; + m_hmult = hmult; + } positions.push_back(pos); + unbiasedpos.push_back( + QPoint((int)round(pos.x() / wmult), + (int)round(pos.y() / hmult))); + + VERBOSE(VB_IMPORTANT, + "OSDTypePositionImage::AddPosition["<= m_numpositions) return; QPoint pos = positions[m_curposition]; - OSDTypeImage::SetPosition(pos); + OSDTypeImage::SetPosition(pos, m_wmult, m_hmult); OSDTypeImage::Draw(surface, fade, maxfade, xoff, yoff); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OSDTypeCC::OSDTypeCC(const QString &name, TTFFont *font, int xoff, int yoff, - int dispw, int disph) + int dispw, int disph, float wmult, float hmult) : OSDType(name) { m_font = font; @@ -1683,9 +1742,11 @@ OSDTypeCC::OSDTypeCC(const QString &name yoffset = yoff; displaywidth = dispw; displayheight = disph; + m_wmult = wmult; + m_hmult = hmult; QRect rect = QRect(0, 0, 0, 0); - m_box = new OSDTypeBox("cc_background", rect); + m_box = new OSDTypeBox("cc_background", rect, wmult, hmult); m_ccbackground = gContext->GetNumSetting("CCBackground", 0); } @@ -1695,12 +1756,23 @@ OSDTypeCC::~OSDTypeCC() delete m_box; } -void OSDTypeCC::Reinit(int x, int y, int dispw, int disph) +void OSDTypeCC::Reinit(float wmult, float hmult) +{ + (void) wmult; + (void) hmult; + VERBOSE(VB_IMPORTANT, "Programmer error: " + "Call to OSDTypeCC::Reinit(float,float)"); +} + +void OSDTypeCC::Reinit(int x, int y, int dispw, int disph, + float wmult, float hmult) { xoffset = x; yoffset = y; displaywidth = dispw; displayheight = disph; + m_wmult = wmult; + m_hmult = hmult; } void OSDTypeCC::AddCCText(const QString &text, int x, int y, int color, @@ -1875,7 +1947,7 @@ void OSDTypeCC::Draw(OSDSurface *surface { QRect rect = QRect(0, 0, textlength + 4, (m_font->Size() * 3 / 2) + 3); - m_box->SetRect(rect); + m_box->SetRect(rect, m_wmult, m_hmult); m_box->Draw(surface, 0, 0, x - 2, y - 2); } diff -pruN mythtv-0.19/libs/libmythtv/osdtypes.h mythtv/libs/libmythtv/osdtypes.h --- mythtv-0.19/libs/libmythtv/osdtypes.h 2005-12-05 16:40:28.000000000 +1000 +++ mythtv/libs/libmythtv/osdtypes.h 2006-05-10 09:54:43.000000000 +1000 @@ -8,6 +8,7 @@ #include #include #include +#include "osdimagecache.h" using namespace std; @@ -137,6 +138,8 @@ class OSDType : public QObject QString Name() { return m_name; } + virtual void Reinit(float wmult, float hmult) = 0; + virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff) = 0; @@ -150,11 +153,11 @@ class OSDTypeText : public OSDType { public: OSDTypeText(const QString &name, TTFFont *font, const QString &text, - QRect displayrect); + QRect displayrect, float wmult, float hmult); OSDTypeText(const OSDTypeText &text); ~OSDTypeText(); - void Reinit(float wchange, float hchange); + void Reinit(float wmult, float hmult); void SetAltFont(TTFFont *font); void SetUseAlt(bool usealt) { m_usingalt = usealt; } @@ -190,6 +193,7 @@ class OSDTypeText : public OSDType QRect m_displaysize; QRect m_screensize; + QRect m_unbiasedsize; QString m_message; QString m_default_msg; @@ -231,7 +235,7 @@ class OSDTypeImage : public OSDType virtual ~OSDTypeImage(); void SetName(const QString &name); - void Reinit(float wchange, float hchange, float wmult, float hmult); + void Reinit(float wmult, float hmult); void LoadImage(const QString &filename, float wmult, float hmult, int scalew = -1, int scaleh = -1); @@ -239,14 +243,12 @@ class OSDTypeImage : public OSDType void SetStaticSize(int scalew, int scaleh) { m_scalew = scalew; m_scaleh = scaleh; } + void SetPosition(QPoint pos, float wmult, float hmult); - QPoint DisplayPos() { return m_displaypos; } - void SetPosition(QPoint pos) { m_displaypos = pos; } - - QRect ImageSize() { return m_imagesize; } - - int width() { return m_imagesize.width(); } - int height() { return m_imagesize.height(); } + QPoint DisplayPos() const { return m_displaypos; } + QRect ImageSize() const { return m_imagesize; } + int width() const { return m_imagesize.width(); } + int height() const { return m_imagesize.height(); } virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff); @@ -254,6 +256,7 @@ class OSDTypeImage : public OSDType protected: QRect m_imagesize; QPoint m_displaypos; + QPoint m_unbiasedpos; QString m_filename; @@ -270,6 +273,9 @@ class OSDTypeImage : public OSDType int m_drawwidth; bool m_onlyusefirst; + + static OSDImageCache c_cache; + OSDImageCacheValue *m_cacheitem; }; class OSDTypePosSlider : public OSDTypeImage @@ -280,7 +286,7 @@ class OSDTypePosSlider : public OSDTypeI int scalew = -1, int scaleh = -1); ~OSDTypePosSlider(); - void Reinit(float wchange, float hchange, float wmult, float hmult); + void Reinit(float wmult, float hmult); void SetRectangle(QRect rect) { m_displayrect = rect; } QRect ImageSize() { return m_imagesize; } @@ -290,6 +296,7 @@ class OSDTypePosSlider : public OSDTypeI private: QRect m_displayrect; + QRect m_unbiasedrect; int m_maxval; int m_curval; }; @@ -302,7 +309,7 @@ class OSDTypeFillSlider : public OSDType int scalew = -1, int scaleh = -1); ~OSDTypeFillSlider(); - void Reinit(float wchange, float hchange, float wmult, float hmult); + void Reinit(float wmult, float hmult); void SetRectangle(QRect rect) { m_displayrect = rect; } QRect ImageSize() { return m_imagesize; } @@ -314,6 +321,7 @@ class OSDTypeFillSlider : public OSDType private: QRect m_displayrect; + QRect m_unbiasedrect; int m_maxval; int m_curval; }; @@ -327,7 +335,7 @@ class OSDTypeEditSlider : public OSDType int scalew = -1, int scaleh = -1); ~OSDTypeEditSlider(); - void Reinit(float wchange, float hchange, float wmult, float hmult); + void Reinit(float wmult, float hmult); void SetRectangle(QRect rect) { m_displayrect = rect; } QRect ImageSize() { return m_imagesize; } @@ -339,6 +347,7 @@ class OSDTypeEditSlider : public OSDType private: QRect m_displayrect; + QRect m_unbiasedrect; int m_maxval; int m_curval; @@ -360,17 +369,19 @@ class OSDTypeEditSlider : public OSDType class OSDTypeBox : public OSDType { public: - OSDTypeBox(const QString &name, QRect displayrect); + OSDTypeBox(const QString &name, QRect displayrect, + float wmult, float hmult); OSDTypeBox(const OSDTypeBox &other); ~OSDTypeBox(); - void Reinit(float wchange, float hchange); - void SetRect(QRect newrect) { size = newrect; } + void Reinit(float wmult, float hmult); + void SetRect(QRect newrect, float wmult, float hmult); void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff); private: QRect size; + QRect m_unbiasedsize; }; class OSDTypePositionIndicator @@ -403,14 +414,15 @@ class OSDTypePositionRectangle : public OSDTypePositionRectangle(const OSDTypePositionRectangle &other); ~OSDTypePositionRectangle(); - void AddPosition(QRect rect); + void AddPosition(QRect rect, float wmult, float hmult); - void Reinit(float wchange, float hchange); + void Reinit(float wmult, float hmult); void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff); private: - vector positions; + vector positions; + vector unbiasedpos; }; class OSDTypePositionImage : public virtual OSDTypeImage, @@ -421,14 +433,17 @@ class OSDTypePositionImage : public virt OSDTypePositionImage(const OSDTypePositionImage &other); ~OSDTypePositionImage(); - void Reinit(float wchange, float hchange, float wmult, float hmult); + void Reinit(float wmult, float hmult); - void AddPosition(QPoint pos); + void AddPosition(QPoint pos, float wmult, float hmult); void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff); private: vector positions; + vector unbiasedpos; + float m_wmult; + float m_hmult; }; class ccText @@ -445,10 +460,14 @@ class OSDTypeCC : public OSDType { public: OSDTypeCC(const QString &name, TTFFont *font, int xoff, int yoff, - int dispw, int disph); + int dispw, int disph, float wmult, float hmult); ~OSDTypeCC(); - void Reinit(int xoff, int yoff, int dispw, int disph); + void Reinit(float wmult, float hmult); + + void Reinit(int xoff, int yoff, + int dispw, int disph, + float wmult, float hmult); void AddCCText(const QString &text, int x, int y, int color, bool teletextmode = false); @@ -464,7 +483,7 @@ class OSDTypeCC : public OSDType vector *m_textlist; OSDTypeBox *m_box; int m_ccbackground; - + float m_wmult, m_hmult; int xoffset, yoffset, displaywidth, displayheight; }; diff -pruN mythtv-0.19/libs/libmythtv/pchdtvsignalmonitor.cpp mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp --- mythtv-0.19/libs/libmythtv/pchdtvsignalmonitor.cpp 2006-02-08 07:56:06.000000000 +1000 +++ mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp 2006-04-20 23:46:13.000000000 +1000 @@ -108,8 +108,8 @@ void pcHDTVSignalMonitor::RunTableMonito len += remainder; remainder = GetStreamData()->ProcessData(buffer, len); - if (remainder > 0) // leftover bytes - memmove(buffer, &(buffer[buffer_size - remainder]), remainder); + if (remainder > 0 && (len > remainder)) // leftover bytes + memmove(buffer, &(buffer[len - remainder]), remainder); } DBG_SM("RunTableMonitor()", "end"); } diff -pruN mythtv-0.19/libs/libmythtv/RingBuffer.cpp mythtv/libs/libmythtv/RingBuffer.cpp --- mythtv-0.19/libs/libmythtv/RingBuffer.cpp 2006-02-08 07:56:06.000000000 +1000 +++ mythtv/libs/libmythtv/RingBuffer.cpp 2006-04-13 11:22:30.000000000 +1000 @@ -145,6 +145,12 @@ void RingBuffer::OpenFile(const QString VERBOSE(VB_PLAYBACK, LOC + QString("OpenFile(%1, %1)") .arg(lfilename).arg(retryCount)); + if ((filename.right(4).lower() == ".png") || + (filename.right(4).lower() == ".gif")) + { + retryCount = 0; + } + uint openAttempts = retryCount + 1; filename = lfilename; @@ -162,6 +168,7 @@ void RingBuffer::OpenFile(const QString bool is_local = false; bool is_dvd = false; + if ((filename.left(7) == "myth://") && (filename.length() > 7 )) { @@ -271,6 +278,11 @@ void RingBuffer::OpenFile(const QString remotefile = NULL; } } + + setswitchtonext = false; + ateof = false; + commserror = false; + numfailures = 0; } /** \fn RingBuffer::IsOpen(void) const @@ -727,7 +739,7 @@ void RingBuffer::ReadAheadThread(void) loops = 0; pthread_rwlock_rdlock(&rwlock); - if (totfree > readblocksize && !commserror) + if (totfree > readblocksize && !commserror && !ateof && !setswitchtonext) { // limit the read size totfree = readblocksize; @@ -737,6 +749,9 @@ void RingBuffer::ReadAheadThread(void) if (remotefile) { + if (livetvchain && livetvchain->HasNext()) + remotefile->SetTimeout(true); + ret = safe_read(remotefile, readAheadBuffer + rbwpos, totfree); internalreadpos += ret; @@ -785,8 +800,16 @@ void RingBuffer::ReadAheadThread(void) totfree = 0; } - if (!readsallowed && used >= fill_min) + if (!readsallowed && (used >= fill_min || setswitchtonext)) + { readsallowed = true; + VERBOSE(VB_PLAYBACK, QString("reads allowed (%1 %2)").arg(used) + .arg(fill_min)); + } + else if (!readsallowed) + VERBOSE(VB_PLAYBACK, QString("buffering (%1 %2 %3)").arg(used) + .arg(fill_min) + .arg(ret)); if (readsallowed && used < fill_min && !ateof && !setswitchtonext) { @@ -808,8 +831,11 @@ void RingBuffer::ReadAheadThread(void) pthread_rwlock_unlock(&rwlock); - if ((used >= fill_threshold || wantseek) && !pausereadthread) + if ((used >= fill_threshold || wantseek || ateof || setswitchtonext) && + !pausereadthread) + { usleep(500); + } } delete [] readAheadBuffer; @@ -853,15 +879,15 @@ int RingBuffer::ReadFromBuf(void *buf, i VERBOSE(VB_IMPORTANT, LOC + "Taking too long to be allowed to read.."); readErr++; - + // HACK Sometimes the readhead thread gets borked on startup. - /* if ((readErr % 2) && (rbrpos ==0)) + if ((readErr > 2 && readErr % 2) && (rbrpos ==0)) { VERBOSE(VB_IMPORTANT, "restarting readhead thread.."); KillReadAheadThread(); StartupReadAheadThread(); } - */ + if (readErr > 10) { VERBOSE(VB_IMPORTANT, LOC_ERR + "Took more than " @@ -895,6 +921,12 @@ int RingBuffer::ReadFromBuf(void *buf, i VERBOSE(VB_IMPORTANT, LOC + "Waited " + QString("%1").arg(elapsed/1000) + " seconds for data to become available..."); + if (livetvchain) + { + VERBOSE(VB_IMPORTANT, "Checking to see if there's a " + "new livetv program to switch to.."); + livetvchain->ReloadAll(); + } } bool quit = livetvchain && (livetvchain->NeedsToSwitch() || @@ -923,7 +955,7 @@ int RingBuffer::ReadFromBuf(void *buf, i availWaitMutex.unlock(); avail = ReadBufAvail(); - if (ateof && avail < count) + if ((ateof || setswitchtonext) && avail < count) count = avail; if (commserror) diff -pruN mythtv-0.19/libs/libmythtv/RingBuffer.h mythtv/libs/libmythtv/RingBuffer.h --- mythtv-0.19/libs/libmythtv/RingBuffer.h 2006-02-07 14:31:49.000000000 +1000 +++ mythtv/libs/libmythtv/RingBuffer.h 2006-02-23 17:54:05.000000000 +1000 @@ -91,6 +91,7 @@ class RingBuffer long long GetTotalReadPosition(void); long long SetAdjustFilesize(void); + void SetTimeout(bool fast) { oldfile = fast; } protected: static void *StartReader(void *type); diff -pruN mythtv-0.19/libs/libmythtv/scanwizard.cpp mythtv/libs/libmythtv/scanwizard.cpp --- mythtv-0.19/libs/libmythtv/scanwizard.cpp 2005-12-17 05:58:46.000000000 +1000 +++ mythtv/libs/libmythtv/scanwizard.cpp 2006-04-26 05:50:59.000000000 +1000 @@ -1,5 +1,5 @@ /* - * $Id: scanwizard.cpp 8292 2005-12-16 19:58:46Z danielk $ + * $Id: scanwizard.cpp 9799 2006-04-25 19:50:59Z danielk $ * vim: set expandtab tabstop=4 shiftwidth=4: * * Original Project @@ -518,7 +518,9 @@ void ScanWizardScanner::scan() "SELECT dvb_diseqc_type, diseqc_port, diseqc_pos, " " lnb_lof_switch, lnb_lof_hi, lnb_lof_lo " "FROM cardinput, capturecard " - "WHERE capturecard.cardid=%1 and cardinput.sourceid=%2") + "WHERE capturecard.cardid = %1 AND " + " cardinput.sourceid = %2 AND " + " capturecard.cardid = cardinput.cardid") .arg(parent->captureCard()).arg(nVideoSource)); if (query.exec() && query.isActive() && query.size() > 0) diff -pruN mythtv-0.19/libs/libmythtv/scanwizardhelpers.h mythtv/libs/libmythtv/scanwizardhelpers.h --- mythtv-0.19/libs/libmythtv/scanwizardhelpers.h 2006-02-02 02:56:06.000000000 +1000 +++ mythtv/libs/libmythtv/scanwizardhelpers.h 2006-04-13 00:21:41.000000000 +1000 @@ -1,5 +1,5 @@ /* -*- Mode: c++ -*- - * $Id: scanwizardhelpers.h 8817 2006-02-01 16:56:06Z danielk $ + * $Id: scanwizardhelpers.h 9685 2006-04-12 14:21:41Z danielk $ * vim: set expandtab tabstop=4 shiftwidth=4: * * Original Project @@ -272,11 +272,13 @@ class ScanFrequencyTable: public ComboBo public: ScanFrequencyTable() { - addSelection(QObject::tr("Broadcast"), "us", true); - addSelection(QObject::tr("Cable") +" 78+", "uscablehigh", false); - addSelection(QObject::tr("Cable HRC")+" 78+", "uscablehrchigh",false); - addSelection(QObject::tr("Cable"), "uscable", false); - addSelection(QObject::tr("Cable HRC"), "ushrc", false); + addSelection(QObject::tr("Broadcast"), "us", true); + addSelection(QObject::tr("Cable") +" 78+", "uscablehigh", false); + addSelection(QObject::tr("Cable HRC")+" 67+", "ushrchigh", false); + addSelection(QObject::tr("Cable IRC")+" 67+", "usirchigh", false); + addSelection(QObject::tr("Cable"), "uscable", false); + addSelection(QObject::tr("Cable HRC"), "ushrc", false); + addSelection(QObject::tr("Cable IRC"), "usirc", false); setLabel(QObject::tr("Frequency Table")); setHelpText(QObject::tr("Frequency table to use.") + " " + diff -pruN mythtv-0.19/libs/libmythtv/tv_play.cpp mythtv/libs/libmythtv/tv_play.cpp --- mythtv-0.19/libs/libmythtv/tv_play.cpp 2006-02-08 07:56:06.000000000 +1000 +++ mythtv/libs/libmythtv/tv_play.cpp 2006-04-22 07:08:11.000000000 +1000 @@ -247,7 +247,7 @@ TV::TV(void) browsechannum(""), browsechanid(""), browsestarttime(""), // Program Info for currently playing video recorderPlaybackInfo(NULL), - playbackinfo(NULL), inputFilename(""), playbackLen(0), + playbackinfo(NULL), playbackLen(0), lastProgram(NULL), jumpToProgram(false), // Video Players nvp(NULL), pipnvp(NULL), activenvp(NULL), @@ -578,19 +578,7 @@ bool TV::RequestNextRecorder(bool showDi if (!testrec->IsValidRecorder()) { if (showDialogs) - { - QString title = tr("MythTV is already using all available " - "inputs for recording. If you want to " - "watch an in-progress recording, select one " - "from the playback menu. If you want to " - "watch live TV, cancel one of the " - "in-progress recordings from the delete " - "menu."); - - DialogBox diag(gContext->GetMainWindow(), title); - diag.AddButton(tr("Cancel and go back to the TV menu")); - diag.exec(); - } + ShowNoRecorderDialog(); delete testrec; @@ -659,8 +647,6 @@ int TV::Playback(ProgramInfo *rcinfo) if (internalState != kState_None) return 0; - inputFilename = rcinfo->pathname; - playbackLen = rcinfo->CalculateLength(); playbackinfo = new ProgramInfo(*rcinfo); @@ -844,9 +830,10 @@ void TV::HandleStateChange(void) } else { - tvchain->SetProgram(playbackinfo); + QString playbackURL = playbackinfo->GetPlaybackURL(); - prbuffer = new RingBuffer(playbackinfo->pathname, false); + tvchain->SetProgram(playbackinfo); + prbuffer = new RingBuffer(playbackURL, false); prbuffer->SetLiveMode(tvchain); } @@ -895,7 +882,14 @@ void TV::HandleStateChange(void) else if (TRANSITION(kState_None, kState_WatchingPreRecorded) || TRANSITION(kState_None, kState_WatchingRecording)) { - prbuffer = new RingBuffer(inputFilename, false); + QString playbackURL; + if ((playbackinfo->pathname.left(4) == "dvd:") || + (playbackinfo->isVideo)) + playbackURL = playbackinfo->pathname; + else + playbackURL = playbackinfo->GetPlaybackURL(); + + prbuffer = new RingBuffer(playbackURL, false); if (prbuffer->IsOpen()) { gContext->DisableScreensaver(); @@ -924,7 +918,7 @@ void TV::HandleStateChange(void) { QString message = "COMMFLAG_REQUEST "; message += playbackinfo->chanid + " " + - playbackinfo->startts.toString(Qt::ISODate); + playbackinfo->recstartts.toString(Qt::ISODate); RemoteSendMessage(message); } } @@ -1222,10 +1216,10 @@ void TV::SetupPlayer(bool isWatchingReco nvp->SetParentPlayer(this); nvp->SetRingBuffer(prbuffer); nvp->SetRecorder(recorder); - nvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate")); + nvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate", 44100)); nvp->SetAudioDevice(gContext->GetSetting("AudioOutputDevice")); nvp->SetLength(playbackLen); - nvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking")); + nvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking", 0)); nvp->SetAutoCommercialSkip(autoCommercialSkip); nvp->SetLiveTVChain(tvchain); @@ -1296,9 +1290,9 @@ void TV::SetupPipPlayer(void) pipnvp->SetAsPIP(); pipnvp->SetRingBuffer(piprbuffer); pipnvp->SetRecorder(piprecorder); - pipnvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate")); + pipnvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate", 44100)); pipnvp->SetAudioDevice(gContext->GetSetting("AudioOutputDevice")); - pipnvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking")); + pipnvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking", 0)); pipnvp->SetLiveTVChain(piptvchain); pipnvp->SetLength(playbackLen); @@ -1454,6 +1448,30 @@ void TV::RunTV(void) lastSignalMsg.clear(); } UpdateOSDTimeoutMessage(); + + if (!tvchainUpdate.isEmpty()) + { + tvchainUpdateLock.lock(); + for (QStringList::Iterator it = tvchainUpdate.begin(); + it != tvchainUpdate.end(); ++it) + { + if (tvchain && nvp && *it == tvchain->GetID()) + { + tvchain->ReloadAll(); + if (nvp->GetTVChain()) + nvp->CheckTVChain(); + } + if (piptvchain && pipnvp && *it == piptvchain->GetID()) + { + piptvchain->ReloadAll(); + if (pipnvp->GetTVChain()) + pipnvp->CheckTVChain(); + } + } + tvchainUpdate.clear(); + tvchainUpdateLock.unlock(); + } + osdlock.unlock(); } @@ -2743,7 +2761,7 @@ void TV::processNetworkControlCommand(QS speedStr = QString("%1X").arg(normal_speed); struct StatusPosInfo posInfo; - nvp->calcSliderPos(posInfo); + nvp->calcSliderPos(posInfo, true); QDateTime respDate = mythCurrentDateTime(); QString infoStr = ""; @@ -2806,8 +2824,10 @@ void TV::TogglePIPView(void) } else { + QString playbackURL = playbackinfo->GetPlaybackURL(); + piptvchain->SetProgram(playbackinfo); - piprbuffer = new RingBuffer(playbackinfo->pathname, false); + piprbuffer = new RingBuffer(playbackURL, false); piprbuffer->SetLiveMode(piptvchain); } @@ -3472,8 +3492,10 @@ void TV::SwitchCards(uint chanid, QStrin } else { + QString playbackURL = playbackinfo->GetPlaybackURL(); + tvchain->SetProgram(playbackinfo); - prbuffer = new RingBuffer(playbackinfo->pathname, false); + prbuffer = new RingBuffer(playbackURL, false); prbuffer->SetLiveMode(tvchain); } @@ -4627,7 +4649,8 @@ void TV::ChangeTimeStretch(int dir, bool normal_speed = new_normal_speed; - activenvp->Play(normal_speed, true); + if (!paused) + activenvp->Play(normal_speed, true); QString text = QString(tr("Time Stretch %1X")).arg(normal_speed); @@ -4911,29 +4934,14 @@ void TV::customEvent(QCustomEvent *e) } else if (tvchain && message.left(12) == "LIVETV_CHAIN") { - // Get osdlock, while intended for the OSD this ensures that - // the nvp & pipnvp are not deleted while we are using it.. - while (!osdlock.tryLock() && nvp) - usleep(2500); - message = message.simplifyWhiteSpace(); QStringList tokens = QStringList::split(" ", message); if (tokens[1] == "UPDATE") { - if (tvchain && nvp && tokens[2] == tvchain->GetID()) - { - tvchain->ReloadAll(); - if (nvp->GetTVChain()) - nvp->CheckTVChain(); - } - if (piptvchain && pipnvp && tokens[2] == piptvchain->GetID()) - { - piptvchain->ReloadAll(); - if (pipnvp->GetTVChain()) - pipnvp->CheckTVChain(); - } + tvchainUpdateLock.lock(); + tvchainUpdate += QDeepCopy(tokens[2]); + tvchainUpdateLock.unlock(); } - osdlock.unlock(); } else if (nvp && message.left(12) == "EXIT_TO_MENU") { @@ -4983,7 +4991,7 @@ void TV::customEvent(QCustomEvent *e) QDateTime evstartts = QDateTime::fromString(tokens[2], Qt::ISODate); if ((playbackinfo->chanid == evchanid) && - (playbackinfo->startts == evstartts)) + (playbackinfo->recstartts == evstartts)) { QString msg = "COMMFLAG_REQUEST "; msg += tokens[1] + " " + tokens[2]; @@ -5000,7 +5008,7 @@ void TV::customEvent(QCustomEvent *e) QDateTime evstartts = QDateTime::fromString(tokens[2], Qt::ISODate); if ((playbackinfo->chanid == evchanid) && - (playbackinfo->startts == evstartts)) + (playbackinfo->recstartts == evstartts)) { QMap newMap; QStringList mark; @@ -6067,9 +6075,22 @@ void TV::ShowNoRecorderDialog(void) "in-progress recordings from the delete " "menu."); - MythPopupBox::showOkPopup( + if (embedWinID) + { + VERBOSE(VB_IMPORTANT, errorText); + } + else if (GetOSD()) + { + dialogname = "infobox"; + QStringList options("OK"); + GetOSD()->NewDialogBox(dialogname, errorText, options, 0); + } + else + { + MythPopupBox::showOkPopup( gContext->GetMainWindow(), QObject::tr("Channel Change Error"), errorText); + } } /** \fn TV::PauseLiveTV(void) diff -pruN mythtv-0.19/libs/libmythtv/tv_play.h mythtv/libs/libmythtv/tv_play.h --- mythtv-0.19/libs/libmythtv/tv_play.h 2006-02-02 02:40:46.000000000 +1000 +++ mythtv/libs/libmythtv/tv_play.h 2006-02-23 17:54:05.000000000 +1000 @@ -456,7 +456,6 @@ class TV : public QObject ProgramInfo *recorderPlaybackInfo; ///< info requested from recorder ProgramInfo *playbackinfo; ///< info sent in via Playback() QMutex pbinfoLock; - QString inputFilename; ///< playbackinfo->pathname int playbackLen; ///< initial playbackinfo->CalculateLength() ProgramInfo *lastProgram; ///< last program played with this player bool jumpToProgram; @@ -485,6 +484,8 @@ class TV : public QObject // LiveTVChain LiveTVChain *tvchain; LiveTVChain *piptvchain; + QStringList tvchainUpdate; + QMutex tvchainUpdateLock; // RingBuffers RingBuffer *prbuffer; diff -pruN mythtv-0.19/libs/libmythtv/videosource.cpp mythtv/libs/libmythtv/videosource.cpp --- mythtv-0.19/libs/libmythtv/videosource.cpp 2006-02-08 07:56:06.000000000 +1000 +++ mythtv/libs/libmythtv/videosource.cpp 2006-04-13 00:21:41.000000000 +1000 @@ -32,6 +32,7 @@ #include "videosource.h" #include "datadirect.h" #include "scanwizard.h" +#include "frequencies.h" #ifdef USING_DVB #include @@ -574,22 +575,10 @@ FreqTableSelector::FreqTableSelector(con { setLabel(QObject::tr("Channel frequency table")); addSelection("default"); - addSelection("us-cable"); - addSelection("us-bcast"); - addSelection("us-cable-hrc"); - addSelection("japan-bcast"); - addSelection("japan-cable"); - addSelection("europe-west"); - addSelection("europe-east"); - addSelection("italy"); - addSelection("newzealand"); - addSelection("australia"); - addSelection("ireland"); - addSelection("france"); - addSelection("china-bcast"); - addSelection("southafrica"); - addSelection("argentina"); - addSelection("australia-optus"); + + for (uint i = 0; chanlists[i].name; i++) + addSelection(chanlists[i].name); + setHelpText(QObject::tr("Use default unless this source uses a " "different frequency table than the system wide table " "defined in the General settings.")); diff -pruN mythtv-0.19/programs/mythbackend/autoexpire.cpp mythtv/programs/mythbackend/autoexpire.cpp --- mythtv-0.19/programs/mythbackend/autoexpire.cpp 2006-02-08 07:53:46.000000000 +1000 +++ mythtv/programs/mythbackend/autoexpire.cpp 2006-03-19 05:32:52.000000000 +1000 @@ -291,7 +291,8 @@ void AutoExpire::ExpireLiveTV(int type) if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0) { - QString msg = QString("ERROR: Could not calculate free space."); + QString msg = QString("ERROR: Could not calculate free space for %1.") + .arg(record_file_prefix); VERBOSE(VB_IMPORTANT, LOC + msg); gContext->LogEntry("mythbackend", LP_WARNING, "Autoexpire Recording", msg); diff -pruN mythtv-0.19/programs/mythbackend/filetransfer.cpp mythtv/programs/mythbackend/filetransfer.cpp --- mythtv-0.19/programs/mythbackend/filetransfer.cpp 2006-02-07 01:35:33.000000000 +1000 +++ mythtv/programs/mythbackend/filetransfer.cpp 2006-02-23 17:54:05.000000000 +1000 @@ -131,3 +131,9 @@ long long FileTransfer::GetFileSize(void return size; } + +void FileTransfer::SetTimeout(bool fast) +{ + rbuffer->SetTimeout(fast); +} + diff -pruN mythtv-0.19/programs/mythbackend/filetransfer.h mythtv/programs/mythbackend/filetransfer.h --- mythtv-0.19/programs/mythbackend/filetransfer.h 2006-02-07 01:35:33.000000000 +1000 +++ mythtv/programs/mythbackend/filetransfer.h 2006-02-23 17:54:05.000000000 +1000 @@ -35,6 +35,8 @@ class FileTransfer long long GetFileSize(void); + void SetTimeout(bool fast); + private: bool readthreadlive; QMutex readthreadLock; diff -pruN mythtv-0.19/programs/mythbackend/housekeeper.cpp mythtv/programs/mythbackend/housekeeper.cpp --- mythtv-0.19/programs/mythbackend/housekeeper.cpp 2005-12-27 15:20:47.000000000 +1000 +++ mythtv/programs/mythbackend/housekeeper.cpp 2006-03-14 03:52:00.000000000 +1000 @@ -138,7 +138,6 @@ void HouseKeeper::RunHouseKeeping(void) while (1) { - VERBOSE(VB_IMPORTANT, "Running HouseKeeping"); gContext->LogEntry("mythbackend", LP_DEBUG, "Running housekeeping thread", ""); diff -pruN mythtv-0.19/programs/mythbackend/mainserver.cpp mythtv/programs/mythbackend/mainserver.cpp --- mythtv-0.19/programs/mythbackend/mainserver.cpp 2006-01-29 09:49:24.000000000 +1000 +++ mythtv/programs/mythbackend/mainserver.cpp 2006-03-06 12:41:13.000000000 +1000 @@ -1919,11 +1919,8 @@ void MainServer::HandleGetPendingRecordi if (m_sched) { if (table == "") m_sched->getAllPending(strList); else { - // We need a different connection from the scheduler proper - // DDCon exists, although it's designed for other purposes. - MSqlQueryInfo dbconn = MSqlQuery::DDCon(); - Scheduler *sched = new Scheduler(false, encoderList, - table, &dbconn, m_sched); + Scheduler *sched = new Scheduler(false, encoderList, + table, m_sched); sched->FillRecordListFromDB(recordid); sched->getAllPending(strList); delete sched; @@ -2940,6 +2937,12 @@ void MainServer::HandleFileTransferQuery long long ret = ft->Seek(curpos, pos, whence); encodeLongLong(retlist, ret); } + else if (command == "SET_TIMEOUT") + { + bool fast = slist[2].toInt(); + ft->SetTimeout(fast); + retlist << "ok"; + } else { VERBOSE(VB_IMPORTANT, QString("Unknown command: %1").arg(command)); diff -pruN mythtv-0.19/programs/mythbackend/scheduler.cpp mythtv/programs/mythbackend/scheduler.cpp --- mythtv-0.19/programs/mythbackend/scheduler.cpp 2006-02-09 16:27:56.000000000 +1000 +++ mythtv/programs/mythbackend/scheduler.cpp 2006-03-06 14:05:21.000000000 +1000 @@ -35,8 +35,7 @@ using namespace std; #define LOC_ERR QString("Scheduler, Error: ") Scheduler::Scheduler(bool runthread, QMap *tvList, - QString recordTbl, MSqlQueryInfo *databaseConnection, - Scheduler *master_sched) + QString recordTbl, Scheduler *master_sched) { hasconflicts = false; m_tvList = tvList; @@ -48,8 +47,11 @@ Scheduler::Scheduler(bool runthread, QMa master_sched->getAllPending(&reclist); } - if (databaseConnection) dbConn = *databaseConnection; - else dbConn = MSqlQuery::SchedCon(); + // Only the master scheduler should use SchedCon() + if (runthread) + dbConn = MSqlQuery::SchedCon(); + else + dbConn = MSqlQuery::DDCon(); recordTable = recordTbl; @@ -1136,6 +1138,10 @@ void Scheduler::RunScheduler(void) if (reschedQueue.count()) { + // We might have been inactive for a long time, so make + // sure our DB connection is fresh before continuing. + dbConn = MSqlQuery::SchedCon(); + gettimeofday(&fillstart, NULL); QString msg; while (reschedQueue.count()) @@ -1827,10 +1833,10 @@ void Scheduler::UpdateMatches(int record QString query = QString( "INSERT INTO recordmatch (recordid, chanid, starttime, manualid) " "SELECT RECTABLE.recordid, program.chanid, program.starttime, " -" IF(search = %1, recordid, 0) " -"FROM RECTABLE, program ").arg(kManualSearch) + fromclauses[clause] + QString( -" INNER JOIN channel ON (channel.chanid = program.chanid) " -"WHERE ") + whereclauses[clause] + QString(" AND channel.visible = 1 AND " +" IF(search = %1, recordid, 0) ").arg(kManualSearch) + QString( +"FROM (RECTABLE, program INNER JOIN channel " +" ON channel.chanid = program.chanid) ") + fromclauses[clause] + QString( +" WHERE ") + whereclauses[clause] + QString(" AND channel.visible = 1 AND " "((RECTABLE.type = %1 " // allrecord "OR RECTABLE.type = %2 " // findonerecord "OR RECTABLE.type = %3 " // finddailyrecord diff -pruN mythtv-0.19/programs/mythbackend/scheduler.h mythtv/programs/mythbackend/scheduler.h --- mythtv-0.19/programs/mythbackend/scheduler.h 2006-02-08 07:53:46.000000000 +1000 +++ mythtv/programs/mythbackend/scheduler.h 2006-03-06 12:41:13.000000000 +1000 @@ -23,8 +23,7 @@ class Scheduler : public QObject { public: Scheduler(bool runthread, QMap *tvList, - QString recordTbl = "record", MSqlQueryInfo *dbConnUse = NULL, - Scheduler *master_sched = NULL); + QString recordTbl = "record", Scheduler *master_sched = NULL); ~Scheduler(); void Reschedule(int recordid); diff -pruN mythtv-0.19/programs/mythcommflag/main.cpp mythtv/programs/mythcommflag/main.cpp --- mythtv-0.19/programs/mythcommflag/main.cpp 2006-02-08 16:42:13.000000000 +1000 +++ mythtv/programs/mythcommflag/main.cpp 2006-02-28 16:58:05.000000000 +1000 @@ -895,9 +895,6 @@ int main(int argc, char *argv[]) return COMMFLAG_EXIT_INVALID_CMDLINE; } - if (queueJobInstead) - return QueueCommFlagJob(chanid, starttime); - if (copyToCutlist) return CopySkipListToCutList(chanid, starttime); @@ -1009,7 +1006,10 @@ int main(int argc, char *argv[]) if ( allRecorded ) { - FlagCommercials(chanid, starttime); + if (queueJobInstead) + QueueCommFlagJob(chanid, starttime); + else + FlagCommercials(chanid, starttime); } else { @@ -1063,7 +1063,12 @@ int main(int argc, char *argv[]) if ((flagStatus == COMM_FLAG_NOT_FLAGGED) && (marksFound == 0)) - FlagCommercials(chanid, starttime); + { + if (queueJobInstead) + QueueCommFlagJob(chanid, starttime); + else + FlagCommercials(chanid, starttime); + } } } } diff -pruN mythtv-0.19/programs/mythfilldatabase/filldata.cpp mythtv/programs/mythfilldatabase/filldata.cpp --- mythtv-0.19/programs/mythfilldatabase/filldata.cpp 2006-02-08 07:53:46.000000000 +1000 +++ mythtv/programs/mythfilldatabase/filldata.cpp 2006-05-12 07:07:54.000000000 +1000 @@ -337,7 +337,7 @@ void UpdateSourceIcons(int sourceid) MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT ch.chanid, nim.url " - "FROM channel ch, callsignnetworkmap csm " + "FROM (channel ch, callsignnetworkmap csm) " "RIGHT JOIN networkiconmap nim ON csm.network = nim.network " "WHERE ch.callsign = csm.callsign AND " "(icon = :NOICON OR icon = '') AND ch.sourceid = :SOURCEID"); @@ -2174,7 +2174,8 @@ void handleChannels(int id, QValueListLogEntry("mythfilldatabase", LP_WARNING, "Failed to fetch some program info", ""); - return FILLDB_EXIT_DB_ERROR; } else VERBOSE(VB_IMPORTANT, "Data fetching complete."); diff -pruN mythtv-0.19/programs/mythfrontend/customrecord.cpp mythtv/programs/mythfrontend/customrecord.cpp --- mythtv-0.19/programs/mythfrontend/customrecord.cpp 2006-01-22 14:16:48.000000000 +1000 +++ mythtv/programs/mythfrontend/customrecord.cpp 2006-03-06 14:05:21.000000000 +1000 @@ -149,7 +149,7 @@ CustomRecord::CustomRecord(MythMainWindo m_cfrom << ""; m_csql << "program.stars >= 0.75 "; - m_clause->insertItem(tr("Person named in the credits")); + m_clause->insertItem(tr("Person named in the credits (Data Direct)")); m_cfrom << ", people, credits"; m_csql << QString("people.name = 'Tom Hanks' \n" "AND credits.person = people.person \n" @@ -447,8 +447,8 @@ bool CustomRecord::checkSyntax(void) else { MSqlQuery query(MSqlQuery::InitCon()); - query.prepare(QString("SELECT NULL FROM program,channel %1 WHERE\n%2") - .arg(from).arg(desc)); + query.prepare(QString("SELECT NULL FROM (program,channel) " + "%1 WHERE\n%2").arg(from).arg(desc)); if (query.exec() && query.isActive()) { diff -pruN mythtv-0.19/programs/mythfrontend/networkcontrol.cpp mythtv/programs/mythfrontend/networkcontrol.cpp --- mythtv-0.19/programs/mythfrontend/networkcontrol.cpp 2006-02-10 06:21:59.000000000 +1000 +++ mythtv/programs/mythfrontend/networkcontrol.cpp 2006-03-17 19:17:32.000000000 +1000 @@ -469,7 +469,7 @@ QString NetworkControl::processPlay(QStr message = "NETWORK_CONTROL SEEK BACKWARD"; else if (tokens[2].contains(QRegExp("^\\d\\d:\\d\\d:\\d\\d$"))) { - int hours = tokens[2].left(0).toInt(); + int hours = tokens[2].mid(0, 2).toInt(); int minutes = tokens[2].mid(3, 2).toInt(); int seconds = tokens[2].mid(6, 2).toInt(); message = QString("NETWORK_CONTROL SEEK POSITION %1") diff -pruN mythtv-0.19/programs/mythfrontend/playbackbox.cpp mythtv/programs/mythfrontend/playbackbox.cpp --- mythtv-0.19/programs/mythfrontend/playbackbox.cpp 2006-02-08 03:21:33.000000000 +1000 +++ mythtv/programs/mythfrontend/playbackbox.cpp 2006-04-01 02:11:33.000000000 +1000 @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -140,6 +141,7 @@ PlaybackBox::PlaybackBox(BoxType ltype, // Main Recording List support fillListTimer(new QTimer(this)), connected(false), titleIndex(0), progIndex(0), + progsInDB(0), // Other state curitem(NULL), delitem(NULL), lastProgram(NULL), @@ -261,7 +263,9 @@ PlaybackBox::PlaybackBox(BoxType ltype, setNoErase(); gContext->addListener(this); - if (!recGroupPassword.isEmpty() || (titleList.count() <= 1) || initialFilt) + if ((!recGroupPassword.isEmpty()) || + ((titleList.count() <= 1) && (progsInDB > 0)) || + (initialFilt)) showRecGroupChooser(); gContext->addCurrentLocation((type == Delete)? "DeleteBox":"PlaybackBox"); @@ -890,9 +894,13 @@ void PlaybackBox::updateVideo(QPainter * !playingSomething) { QSize size = drawVideoBounds.size(); + float saspect = ((float)size.width()) / ((float)size.height()); + float vaspect = previewVideoNVP->GetVideoAspect(); + size.setHeight((int) ceil(size.height() * (saspect / vaspect))); + size.setHeight(((size.height() + 7) / 8) * 8); + size.setWidth( ((size.width() + 7) / 8) * 8); const QImage &img = previewVideoNVP->GetARGBFrame(size); - uint xoff = max((size.width() - drawVideoBounds.width()) / 2, 0); - p->drawImage(drawVideoBounds.x() + xoff, drawVideoBounds.y(), img); + p->drawImage(drawVideoBounds.x(), drawVideoBounds.y(), img); } /* have we timed out waiting for nvp to start? */ @@ -1380,6 +1388,7 @@ bool PlaybackBox::FillList() asCache[asKey] = p->availableStatus; } + progsInDB = 0; titleList.clear(); progLists.clear(); // Clear autoDelete for the "all" list since it will share the @@ -1402,6 +1411,7 @@ bool PlaybackBox::FillList() vector::iterator i = infoList->begin(); for ( ; i != infoList->end(); i++) { + progsInDB++; p = *i; if ((((p->recgroup == recGroup) || ((recGroup == "All Programs") && @@ -4129,8 +4139,7 @@ void PlaybackBox::recGroupChooserListBox if (!recGroupListBox) return; - QString item = - recGroupListBox->currentText().section('[', 0, 0).simplifyWhiteSpace(); + QString item = recGroupListBox->currentText().section(" [", 0, 0); if (item.left(5) == "-----") { @@ -4147,8 +4156,7 @@ void PlaybackBox::recGroupChooserListBox void PlaybackBox::setGroupFilter(void) { - recGroup = - recGroupListBox->currentText().section('[', 0, 0).simplifyWhiteSpace(); + recGroup = recGroupListBox->currentText().section(" [", 0, 0); if (groupnameAsAllProg) groupDisplayName = recGroup; diff -pruN mythtv-0.19/programs/mythfrontend/playbackbox.h mythtv/programs/mythfrontend/playbackbox.h --- mythtv-0.19/programs/mythfrontend/playbackbox.h 2006-02-02 12:43:31.000000000 +1000 +++ mythtv/programs/mythfrontend/playbackbox.h 2006-02-28 11:06:40.000000000 +1000 @@ -337,6 +337,7 @@ class PlaybackBox : public MythDialog int progIndex; ///< Index of selected item index on page QStringList titleList; ///< list of pages ProgramMap progLists; ///< lists of programs by page + int progsInDB; ///< total number of recordings in DB // Play List support QStringList playList; ///< list of selected items "play list" diff -pruN mythtv-0.19/programs/mythfrontend/tv_schedule.xml mythtv/programs/mythfrontend/tv_schedule.xml --- mythtv-0.19/programs/mythfrontend/tv_schedule.xml 2006-02-02 01:28:40.000000000 +1000 +++ mythtv/programs/mythfrontend/tv_schedule.xml 2006-03-11 10:52:28.000000000 +1000 @@ -26,7 +26,7 @@ Guia EPG Guide - Dagskrá + Dagskrá Gids Guide ガイド diff -pruN mythtv-0.19/programs/mythtranscode/mpeg2fix.cpp mythtv/programs/mythtranscode/mpeg2fix.cpp --- mythtv-0.19/programs/mythtranscode/mpeg2fix.cpp 2006-01-27 02:42:44.000000000 +1000 +++ mythtv/programs/mythtranscode/mpeg2fix.cpp 2006-03-07 11:49:33.000000000 +1000 @@ -1776,6 +1776,7 @@ int MPEG2fixup::Start() if (vFrame.count() && (file_end || vFrame.getLast()->isSequence)) { + MPEG2frame *seqFrame; if (ptsIncrement != vFrame.first()->mpeg2_seq.frame_period / 300) { VERBOSE(MPF_IMPORTANT, @@ -1786,6 +1787,11 @@ int MPEG2fixup::Start() } displayFrame->toFirst(); + // since we might reorder the frames when coming out of a cutpoint + // me need to save the first frame here, as it is gauranteed to + // have a sequence header. + seqFrame = vFrame.current(); + while (vFrame.current() != vFrame.getLast()) { bool ptsorder_eq_dtsorder = false; @@ -1941,7 +1947,7 @@ int MPEG2fixup::Start() if (! new_discard_state) { - AddSequence(markedFrame, vFrame.first()); + AddSequence(markedFrame, seqFrame); RenumberFrames(frame_pos + Lreorder.at(), - GetFrameNum(markedFrame)); } diff -pruN mythtv-0.19/programs/mythtv/main.cpp mythtv/programs/mythtv/main.cpp --- mythtv-0.19/programs/mythtv/main.cpp 2006-01-05 01:45:55.000000000 +1000 +++ mythtv/programs/mythtv/main.cpp 2006-02-19 05:56:39.000000000 +1000 @@ -132,6 +132,7 @@ int main(int argc, char *argv[]) ProgramInfo *pginfo = new ProgramInfo(); pginfo->endts = QDateTime::currentDateTime().addSecs(-180); pginfo->pathname = filename; + pginfo->isVideo = true; tv->Playback(pginfo); } diff -pruN mythtv-0.19/setup/backendsettings.cpp mythtv/setup/backendsettings.cpp --- mythtv-0.19/setup/backendsettings.cpp 2005-12-30 04:16:07.000000000 +1000 +++ mythtv/setup/backendsettings.cpp 2006-04-13 00:21:41.000000000 +1000 @@ -1,6 +1,7 @@ #include #include "backendsettings.h" +#include "frequencies.h" #include "libmyth/mythcontext.h" #include "libmyth/settings.h" #include @@ -110,23 +111,10 @@ static GlobalComboBox *FreqTable() { GlobalComboBox *gc = new GlobalComboBox("FreqTable"); gc->setLabel(QObject::tr("Channel frequency table")); - gc->addSelection("us-cable"); - gc->addSelection("us-bcast"); - gc->addSelection("us-cable-hrc"); - gc->addSelection("us-cable-irc"); - gc->addSelection("japan-bcast"); - gc->addSelection("japan-cable"); - gc->addSelection("europe-west"); - gc->addSelection("europe-east"); - gc->addSelection("italy"); - gc->addSelection("newzealand"); - gc->addSelection("australia"); - gc->addSelection("ireland"); - gc->addSelection("france"); - gc->addSelection("china-bcast"); - gc->addSelection("southafrica"); - gc->addSelection("argentina"); - gc->addSelection("australia-optus"); + + for (uint i = 0; chanlists[i].name; i++) + gc->addSelection(chanlists[i].name); + gc->setHelpText(QObject::tr("Select the appropriate frequency table for " "your system. If you have an antenna, use a \"-bcast\" " "frequency."));