Olaf Dietsche <olaf--mail.dvb...@olafdietsche.de> writes:

> I recently switched from Debian Squeeze to Ubuntu 12.04 and had to
> recompile dvbcut. Attached is a patch to make r179 compile on Ubuntu.

On top of that patch, the following patch implements the frame sequence,
search for duplicate pictures and memory only index file, I implemented
and published earlier (r166, 2009).

Regards, Olaf

Index: src/dvbcut.h
===================================================================
--- src/dvbcut.h	(revision 179)
+++ src/dvbcut.h	(working copy)
@@ -31,6 +31,7 @@
 
 class QProcess;
 class imageprovider;
+class framesequence;
 
 class dvbcut: public dvbcutbase
   {
@@ -102,6 +103,7 @@
   int exportformat; 
   bool start_bof; 
   bool stop_eof; 
+  framesequence *frameseq_;
 
 protected:
   //   QPixmap getpixmap(int picture, bool allgop=false);
@@ -145,6 +147,10 @@
   // static dvbcut *New(std::string filename=std::string(), std::string idxfilename=std::string());
   void addStartStopItems(std::vector<int>, int option=0);
   int getTimePerFrame() { return timeperframe>0 && timeperframe<5000 ? timeperframe : 3003; };
+  int string2frameno(const QString &s, int default_value);
+  int string2frameno(bool &valid, const QString &s);
+  void gotoFrame(int frameno);
+  void updateframeseqbuttons();
 
 public slots:
   virtual void fileNew();
@@ -165,6 +171,7 @@
   virtual void editConvert(int);
   virtual void abouttoshoweditconvert();
   virtual void viewDifference();
+  virtual void searchDuplicate();
   virtual void viewUnscaled();
   virtual void viewNormal();
   virtual void zoomIn();
@@ -186,6 +193,10 @@
   virtual void mplayer_readstdout();
   virtual void clickedgo();
   virtual void clickedgo2();
+  virtual void clickedframeseq();
+  virtual void clickedframeseqprev();
+  virtual void clickedframeseqnext();
+  virtual void clickedframeseqhome();
   virtual void updateimagedisplay();
   virtual void audiotrackchosen(int id);
   virtual void loadrecentfile(int id);
Index: src/settings.cpp
===================================================================
--- src/settings.cpp	(revision 179)
+++ src/settings.cpp	(working copy)
@@ -58,6 +58,13 @@
 #define DVBCUT_DEFAULT_PIPE_LABEL \
         "DVD-Video titleset (dvdauthor)"
 #define DVBCUT_DEFAULT_PIPE_FORMAT (0)
+
+#define DVBCUT_DEFAULT_FRAMESEQ_NFRAMES 7
+#define DVBCUT_DEFAULT_FRAMESEQ_HOME_DISTANCE "1:0"
+#define DVBCUT_DEFAULT_FRAMESEQ_DISTANCES "1 0:1 0:10 1:0 5:0"
+#define DVBCUT_DEFAULT_FRAMESEQ_BUTTON_MINWIDTH 50
+	
+#define DVBCUT_DEFAULT_SEARCH_DUPS_RANGE 1500
 /* 
 // SOME OTHER EXAMPLES for the settings file ~/.qt/dvbcut.sf.netrc 
 // (ok, for time consuming conversions one does not save any time, but it may be convenient...) 
@@ -130,6 +137,7 @@
       prjfilter = readEntry("/prjfilter", DVBCUT_DEFAULT_PRJFILTER);
       loadfilter = readEntry("/loadfilter", DVBCUT_DEFAULT_LOADFILTER);
     endGroup();	// filter
+    search_dups_range = readNumEntry("/search_dups_range", DVBCUT_DEFAULT_SEARCH_DUPS_RANGE);
   }
   else {
     // old (unnumbered) config format
@@ -234,6 +242,7 @@
   endGroup();	// labels
   start_bof = readBoolEntry("/start_bof", true);
   stop_eof = readBoolEntry("/stop_eof", true);
+  create_index_file = readBoolEntry("create_index_file", true);
   beginGroup("/snapshots");
     snapshot_type = readEntry("/type", "PNG");
     snapshot_quality = readNumEntry("/quality", -1);
@@ -284,6 +293,12 @@
     // minimal length of a chapter
     chapter_minimum = readNumEntry("/minimum", 200*25);
   endGroup();	// auto chapters
+  beginGroup("/frameseq");
+    frameseq_nframes = readNumEntry("/nframes", DVBCUT_DEFAULT_FRAMESEQ_NFRAMES);
+    frameseq_home_distance = readEntry("/home_distance", DVBCUT_DEFAULT_FRAMESEQ_HOME_DISTANCE);
+    frameseq_distances = readEntry("/distances", DVBCUT_DEFAULT_FRAMESEQ_DISTANCES);
+    frameseq_button_minwidth = readNumEntry("/button_minwidth", DVBCUT_DEFAULT_FRAMESEQ_BUTTON_MINWIDTH);
+  endGroup();	// frameseq
 }
 
 void
@@ -352,6 +367,7 @@
   endGroup();	// labels
   writeEntry("/start_bof", start_bof);
   writeEntry("/stop_eof", stop_eof);
+  writeEntry("/create_index_file", create_index_file);
   beginGroup("/snapshots");
     writeEntry("/type", snapshot_type);
     writeEntry("/quality", snapshot_quality);
@@ -380,6 +396,13 @@
     writeEntry("/threshold", chapter_threshold);
     writeEntry("/minimum", chapter_minimum);
   endGroup();	// auto chapters
+  beginGroup("/frameseq");
+    writeEntry("/nframes", frameseq_nframes);
+    writeEntry("/home_distance", frameseq_home_distance);
+    writeEntry("/distances", frameseq_distances);
+    writeEntry("/button_minwidth", frameseq_button_minwidth);
+  endGroup();	// frameseq
+  writeEntry("/search_dups_range", search_dups_range);
 }
 
 // private settings variable
Index: src/dvbcutbase.ui
===================================================================
--- src/dvbcutbase.ui	(revision 179)
+++ src/dvbcutbase.ui	(working copy)
@@ -363,6 +363,105 @@
                             </widget>
                         </hbox>
                     </widget>
+                    <widget class="QLayoutWidget">
+                        <property name="name">
+                            <cstring>layout6</cstring>
+                        </property>
+                        <hbox>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <spacer>
+                                <property name="name">
+                                    <cstring>spacer6</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Horizontal</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Expanding</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>2</width>
+                                        <height>10</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                            <widget class="QPushButton">
+                                <property name="name">
+                                    <cstring>frameseqprev</cstring>
+                                </property>
+                                <property name="enabled">
+                                    <bool>false</bool>
+                                </property>
+                                <property name="text">
+                                    <string>Previous</string>
+                                </property>
+                            </widget>
+			    <widget class="QComboBox">
+				<property name="name">
+				    <cstring>frameseqinput</cstring>
+				</property>
+				<property name="editable">
+				    <bool>true</bool>
+				</property>
+				<property name="duplicatesEnabled">
+				    <bool>false</bool>
+				</property>
+			    </widget>
+                            <widget class="QPushButton">
+                                <property name="name">
+                                    <cstring>frameseqbutton</cstring>
+                                </property>
+                                <property name="enabled">
+                                    <bool>false</bool>
+                                </property>
+                                <property name="text">
+                                    <string>go</string>
+                                </property>
+                            </widget>
+                            <widget class="QPushButton">
+                                <property name="name">
+                                    <cstring>frameseqnext</cstring>
+                                </property>
+                                <property name="enabled">
+                                    <bool>false</bool>
+                                </property>
+                                <property name="text">
+                                    <string>Next</string>
+                                </property>
+                            </widget>
+                            <widget class="QPushButton">
+                                <property name="name">
+                                    <cstring>frameseqhome</cstring>
+                                </property>
+                                <property name="enabled">
+                                    <bool>false</bool>
+                                </property>
+                                <property name="text">
+                                    <string>Home</string>
+                                </property>
+                            </widget>
+                            <spacer>
+                                <property name="name">
+                                    <cstring>spacer6</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Horizontal</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Expanding</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>2</width>
+                                        <height>10</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                        </hbox>
+                    </widget>
                 </vbox>
             </widget>
         </widget>
@@ -470,6 +569,7 @@
         <action name="viewNormalAction"/>
         <action name="viewUnscaledAction"/>
         <action name="viewDifferenceAction"/>
+        <action name="searchDuplicateAction"/>
         <separator/>
         <action name="zoomInAction"/>
         <action name="zoomOutAction"/>
@@ -860,6 +960,14 @@
     </action>
     <action>
         <property name="name">
+            <cstring>searchDuplicateAction</cstring>
+        </property>
+        <property name="text">
+            <string>Search duplicate of current picture</string>
+        </property>
+    </action>
+    <action>
+        <property name="name">
             <cstring>viewFullSizeAction</cstring>
         </property>
         <property name="toggleAction">
@@ -1004,6 +1112,48 @@
 	    <string>F1</string>
 	</property>
     </action>
+    <action>
+	<property name="name">
+	    <cstring>frameseqhomeAction</cstring>
+	</property>
+	<property name="text">
+	    <string>&amp;Home</string>
+	</property>
+	<property name="toolTip">
+	    <string>Home</string>
+	</property>
+	<property name="accel">
+	    <string>H</string>
+	</property>
+    </action>
+    <action>
+	<property name="name">
+	    <cstring>frameseqnextAction</cstring>
+	</property>
+	<property name="text">
+	    <string>&amp;Next</string>
+	</property>
+	<property name="toolTip">
+	    <string>Next</string>
+	</property>
+	<property name="accel">
+	    <string>J</string>
+	</property>
+    </action>
+    <action>
+	<property name="name">
+	    <cstring>frameseqprevAction</cstring>
+	</property>
+	<property name="text">
+	    <string>&amp;Previous</string>
+	</property>
+	<property name="toolTip">
+	    <string>Previous</string>
+	</property>
+	<property name="accel">
+	    <string>K</string>
+	</property>
+    </action>
 </actions>
 <images>
     <image name="image0">
@@ -1159,6 +1309,54 @@
         <slot>clickedgo2()</slot>
     </connection>
     <connection>
+        <sender>frameseqbutton</sender>
+        <signal>clicked()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseq()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqinput</sender>
+        <signal>activated(const QString&amp;)</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseq()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqprev</sender>
+        <signal>clicked()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqprev()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqnext</sender>
+        <signal>clicked()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqnext()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqhome</sender>
+        <signal>clicked()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqhome()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqprevAction</sender>
+        <signal>activated()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqprev()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqnextAction</sender>
+        <signal>activated()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqnext()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqhomeAction</sender>
+        <signal>activated()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqhome()</slot>
+    </connection>
+    <connection>
         <sender>playPlayAction</sender>
         <signal>activated()</signal>
         <receiver>dvbcutbase</receiver>
@@ -1207,6 +1405,12 @@
         <slot>viewDifference()</slot>
     </connection>
     <connection>
+        <sender>searchDuplicateAction</sender>
+        <signal>activated()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>searchDuplicate()</slot>
+    </connection>
+    <connection>
         <sender>viewNormalAction</sender>
         <signal>activated()</signal>
         <receiver>dvbcutbase</receiver>
@@ -1306,6 +1510,10 @@
     <slot>eventlistcontextmenu(QListBoxItem *, const QPoint &amp;)</slot>
     <slot>clickedgo()</slot>
     <slot>clickedgo2()</slot>
+    <slot>clickedframeseq()</slot>
+    <slot>clickedframeseqprev()</slot>
+    <slot>clickedframeseqnext()</slot>
+    <slot>clickedframeseqhome()</slot>
     <slot>playPlay()</slot>
     <slot>playStop()</slot>
     <slot>playAudio1()</slot>
@@ -1319,6 +1527,7 @@
     <slot>viewNormal()</slot>
     <slot>viewUnscaled()</slot>
     <slot>viewDifference()</slot>
+    <slot>searchDuplicate()</slot>
     <slot>fileExport()</slot>
     <slot>audiotrackchosen(int)</slot>
     <slot>loadrecentfile(int)</slot>
Index: src/dvbcut.cpp
===================================================================
--- src/dvbcut.cpp	(revision 179)
+++ src/dvbcut.cpp	(working copy)
@@ -51,6 +51,7 @@
 #include <qsettings.h>
 #include <qregexp.h>
 #include <qstatusbar.h>
+#include <qlayout.h>
 
 #include "port.h"
 #include "dvbcut.h"
@@ -68,6 +69,7 @@
 #include "exportdialog.h"
 #include "settings.h"
 #include "exception.h"
+#include "framesequence.h"
 
 #include "version.h"
 
@@ -131,8 +133,23 @@
     jogsliding(false), jogmiddlepic(0),
     mplayer_process(0), imgp(0), busy(0),
     viewscalefactor(1.0),
-    nogui(false)
+    nogui(false),
+    frameseq_(0)
 {
+  frameseq_ = new framesequence(imagedisplay->parentWidget(), settings().frameseq_nframes, this);
+  layout7->addLayout(frameseq_->layout());
+  QStringList distances = QStringList::split(' ', settings().frameseq_distances);
+  for (QStringList::iterator i = distances.begin(); i != distances.end(); ++i)
+    frameseqinput->insertItem(*i);
+
+  frameseqinput->setCurrentText(settings().frameseq_home_distance);
+  frameseqhome->setText(settings().frameseq_home_distance);
+  frameseq_->distance(string2frameno(settings().frameseq_home_distance, 1500));
+  frameseqprev->setMinimumWidth(settings().frameseq_button_minwidth);
+  frameseqnext->setMinimumWidth(settings().frameseq_button_minwidth);
+  frameseqhome->setMinimumWidth(settings().frameseq_button_minwidth);
+  
+  updateframeseqbuttons();
 #ifndef HAVE_LIB_AO
   playAudio1Action->setEnabled(false);
   playAudio2Action->setEnabled(false);
@@ -187,6 +204,8 @@
     delete imgp;
   if (mpg)
     delete mpg;
+
+  delete frameseq_;
 }
 
 // **************************************************************************
@@ -1050,7 +1069,85 @@
   updateimagedisplay();
 }
 
+namespace {
+inline int square(int x)
+{
+	return x * x;
+}
 
+unsigned long calc_distance(QImage baseimg, QImage im)
+{
+	if (im.size() != baseimg.size())
+		im = im.scale(baseimg.size());
+
+	unsigned long distance = 0;
+	if (im.depth() == 32 && baseimg.depth() == 32)
+		for (int y = 0; y < baseimg.height(); ++y) {
+			QRgb *imd = (QRgb*) im.scanLine(y);
+			QRgb *bimd = (QRgb*) baseimg.scanLine(y);
+
+			for (int x = im.width(); x > 0; --x) {
+				int dist = square(qRed(*imd) - qRed(*bimd)) + square(qGreen(*imd) - qGreen(*bimd)) + square(qBlue(*imd) - qBlue(*bimd));
+				if (dist > 1000)
+					dist = 1000;
+
+				distance += dist;
+				++imd;
+				++bimd;
+			}
+		}
+
+	return distance;
+}
+
+int getNextEvent(const QListBox *eventlist, const int picture, const EventListItem::eventtype evtype)
+{
+	for (QListBoxItem *item = eventlist->firstItem(); item; item = item->next())
+		if (item->rtti() == EventListItem::RTTI()) {
+			EventListItem *eli = (EventListItem*)item;
+			if (eli->geteventtype() == evtype && eli->getpicture() > picture)
+				return eli->getpicture();
+		}
+
+	return picture + 1;
+}
+};
+
+void dvbcut::searchDuplicate()
+{
+	progressstatusbar psb(statusBar());
+	psb.print("Searching ...");
+	psb.setprogress(0);
+//	dvbcutbusy busy(this);
+//	busy.setbusy(true);
+	imageprovider imgp(*mpg);
+	QImage baseimg = imgp.getimage(curpic);
+	int pic = getNextEvent(eventlist, curpic, EventListItem::start);
+	gotoFrame(pic);
+	unsigned long min = calc_distance(baseimg, imgp.getimage(pic, true));
+	static const long n = settings().search_dups_range;
+	for (long i = 0; i < n; ++i) {
+		unsigned long d = calc_distance(baseimg, imgp.getimage(++pic, true));
+		if (d < min) {
+			min = d;
+			gotoFrame(pic);
+		}
+
+		psb.setprogress(i * 1000 / n);
+		if (psb.cancelled()) {
+			// FIXME
+			break;
+		}
+	}
+
+//	busy.setbusy(false);
+	if (psb.cancelled()) {
+		// FIXME
+		return;
+	}
+}
+
+
 void dvbcut::viewUnscaled()
 {
   viewNormalAction->setOn(false);
@@ -1122,6 +1219,11 @@
   goinput->setEnabled(false);
   gobutton2->setEnabled(false);
   goinput2->setEnabled(false);
+  frameseqbutton->setEnabled(false);
+  frameseqinput->setEnabled(false);
+  frameseqprev->setEnabled(false);
+  frameseqnext->setEnabled(false);
+  frameseqhome->setEnabled(false);
 
 #ifdef HAVE_LIB_AO
 
@@ -1429,15 +1531,8 @@
 void dvbcut::clickedgo()
 {
   QString text=goinput->text();
-  text.stripWhiteSpace();
   bool okay=false;
-  int inpic;
-  if (text.contains(':') || text.contains('.')) {
-    okay=true;
-    inpic=string2pts(text)/getTimePerFrame();
-  }
-  else
-    inpic=text.toInt(&okay,0);
+  int inpic = string2frameno(okay, text);
   if (okay) {
     fine=true;
     linslider->setValue(inpic);
@@ -1449,15 +1544,8 @@
 void dvbcut::clickedgo2()
 {
   QString text=goinput2->text();
-  text.stripWhiteSpace();
   bool okay=false;
-  int inpic, outpic;
-  if (text.contains(':') || text.contains('.')) {
-    okay=true;
-    outpic=string2pts(text)/getTimePerFrame();
-  }
-  else
-    outpic=text.toInt(&okay,0);
+  int inpic, outpic = string2frameno(okay, text);
   if (okay && !quick_picture_lookup.empty()) {
     // find the entry in the quick_picture_lookup table that corresponds to given output picture
     quick_picture_lookup_t::iterator it=
@@ -1470,6 +1558,65 @@
   //goinput2->clear();
 }
 
+void dvbcut::clickedframeseq()
+{
+  QString text = frameseqinput->currentText();
+  bool okay = false;
+  int dist = string2frameno(okay, text);
+  if (okay) {
+    frameseq_->distance(dist);
+    frameseq_->update(curpic);
+    updateframeseqbuttons();
+  }
+  //frameseqinput->clear();
+}
+
+void dvbcut::updateframeseqbuttons()
+{
+  int item = frameseqinput->currentItem();
+  if (item <= 0) {
+    frameseqprev->setEnabled(false);
+    frameseqprev->setText("Previous");
+  } else {
+    frameseqprev->setEnabled(true);
+    QString s = frameseqinput->text(item - 1);
+    frameseqprev->setText(s);
+  }
+
+  if (item >= frameseqinput->count() - 1) {
+    frameseqnext->setEnabled(false);
+    frameseqnext->setText("Next");
+  } else {
+    frameseqnext->setEnabled(true);
+    QString s = frameseqinput->text(item + 1);
+    frameseqnext->setText(s);
+  }
+}
+
+void dvbcut::clickedframeseqprev()
+{
+  int item = frameseqinput->currentItem();
+  if (item > 0) {
+    frameseqinput->setCurrentItem(item - 1);
+    clickedframeseq();
+  }
+}
+
+void dvbcut::clickedframeseqnext()
+{
+  int item = frameseqinput->currentItem();
+  if (item < frameseqinput->count() - 1) {
+    frameseqinput->setCurrentItem(item + 1);
+    clickedframeseq();
+  }
+}
+
+void dvbcut::clickedframeseqhome()
+{
+  frameseqinput->setCurrentText(settings().frameseq_home_distance);
+  clickedframeseq();
+}
+
 void dvbcut::mplayer_exited()
 {
   if (mplayer_process) {
@@ -1492,6 +1639,11 @@
   goinput->setEnabled(true);
   gobutton2->setEnabled(true);
   goinput2->setEnabled(true);
+  frameseqbutton->setEnabled(true);
+  frameseqinput->setEnabled(true);
+  frameseqprev->setEnabled(true);
+  frameseqnext->setEnabled(true);
+  frameseqhome->setEnabled(true);
 
 #ifdef HAVE_LIB_AO
 
@@ -1580,10 +1732,16 @@
   if (showimage) {
     if (!imgp)
       imgp=new imageprovider(*mpg,new dvbcutbusy(this),false,viewscalefactor);
+
     QPixmap px=imgp->getimage(curpic,fine);
     imagedisplay->setMinimumSize(px.size());
     imagedisplay->setPixmap(px);
     qApp->processEvents();
+
+    if (!frameseq_->imgp())
+      frameseq_->imgp(new imageprovider(*mpg, new dvbcutbusy(this), false, viewscalefactor * 7.));
+
+    frameseq_->update(curpic);
   }
 }
 
@@ -1672,6 +1830,8 @@
     delete imgp;
     imgp=0;
   }
+
+  frameseq_->imgp(0);
   eventlist->clear();
   imagedisplay->setBackgroundMode(Qt::PaletteBackground);
   imagedisplay->setMinimumSize(QSize(0,0));
@@ -1728,6 +1888,11 @@
   gobutton->setEnabled(false);
   goinput2->setEnabled(false);
   gobutton2->setEnabled(false);
+  frameseqbutton->setEnabled(false);
+  frameseqinput->setEnabled(false);
+  frameseqprev->setEnabled(false);
+  frameseqnext->setEnabled(false);
+  frameseqhome->setEnabled(false);
   linslider->setEnabled(false);
   jogslider->setEnabled(false);
 
@@ -1846,41 +2011,43 @@
     return;
   }
 
-  if (idxfilename.empty()) {
-    idxfilename = filename + ".idx";
-    if (!nogui) {
-	  /*
-	   * BEWARE! UGLY HACK BELOW!
-	   *
-	   * In order to circumvent the QFileDialog's stupid URL parsing,
-	   * we need to first change to the directory and then pass the
-	   * filename as a relative file: URL. Otherwise, filenames that
-	   * contain ":" will not be handled correctly. --mr
-	   */
-	  QUrl u;
-	  u.setProtocol(QString("file"));
-	  u.setPath(QString(idxfilename));
-	  if (chdir((const char*)u.dirPath()) == -1) chdir("/");
-	  QString relname = QString("file:") + u.fileName();
-	  QString s=QFileDialog::getSaveFileName(
-		  relname,
-		  settings().idxfilter,
-		  this,
-		  "Choose index file...",
-		  "Choose the name of the index file" );
-	  if (!s) {
-		delete mpg;
-		mpg=0;
-		fileOpenAction->setEnabled(true);
-		return;
-	  }
-	  idxfilename=(const char*)s;
-	  // it's now a relative name that will be canonicalized again soon
-	}
+  if (settings().create_index_file) {
+    if (idxfilename.empty()) {
+      idxfilename = filename + ".idx";
+      if (!nogui) {
+  	  /*
+  	   * BEWARE! UGLY HACK BELOW!
+  	   *
+  	   * In order to circumvent the QFileDialog's stupid URL parsing,
+  	   * we need to first change to the directory and then pass the
+  	   * filename as a relative file: URL. Otherwise, filenames that
+  	   * contain ":" will not be handled correctly. --mr
+  	   */
+  	  QUrl u;
+  	  u.setProtocol(QString("file"));
+  	  u.setPath(QString(idxfilename));
+  	  if (chdir((const char*)u.dirPath()) == -1) chdir("/");
+  	  QString relname = QString("file:") + u.fileName();
+  	  QString s=QFileDialog::getSaveFileName(
+  		  relname,
+  		  settings().idxfilter,
+  		  this,
+  		  "Choose index file...",
+  		  "Choose the name of the index file" );
+  	  if (!s) {
+  		delete mpg;
+  		mpg=0;
+  		fileOpenAction->setEnabled(true);
+  		return;
+  	  }
+  	  idxfilename=(const char*)s;
+  	  // it's now a relative name that will be canonicalized again soon
+  	}
+    }
+  
+    make_canonical(idxfilename);
   }
 
-  make_canonical(idxfilename);
-
   pictures=-1;
 
   if (!idxfilename.empty()) {
@@ -2019,14 +2186,8 @@
       else
         continue;
       bool okay=false;
-      int picnum;
       QString str=e.attribute("picture","-1");
-      if (str.contains(':') || str.contains('.')) {
-        okay=true;
-        picnum=string2pts(str)/getTimePerFrame();
-      }
-      else
-        picnum=str.toInt(&okay,0);
+      int picnum = string2frameno(okay, str);
       if (okay && picnum>=0 && picnum<pictures) {
         new EventListItem(eventlist,imgp->getimage(picnum),evt,picnum,(*mpg)[picnum].getpicturetype(),(*mpg)[picnum].getpts()-firstpts);
         qApp->processEvents();
@@ -2076,6 +2237,11 @@
   gobutton->setEnabled(true);
   goinput2->setEnabled(true);
   gobutton2->setEnabled(true);
+  frameseqbutton->setEnabled(true);
+  frameseqinput->setEnabled(true);
+  frameseqprev->setEnabled(true);
+  frameseqnext->setEnabled(true);
+  frameseqhome->setEnabled(true);
   linslider->setEnabled(true);
   jogslider->setEnabled(true);
 
@@ -2468,3 +2634,28 @@
       tr("Help file %1 not available").arg(helpFile));
   }
 }
+
+int dvbcut::string2frameno(const QString &s, int default_value)
+{
+	bool valid;
+	int frameno = string2frameno(valid, s);
+	return valid ? frameno : default_value;
+}
+
+int dvbcut::string2frameno(bool &valid, const QString &s)
+{
+  if (s.contains(':') || s.contains('.')) {
+    valid = true;
+    return string2pts(s.stripWhiteSpace()) / getTimePerFrame();
+  }
+
+  return s.toInt(&valid, 0);
+}
+
+void dvbcut::gotoFrame(int frameno)
+{
+  bool save = fine;
+  fine = true;
+  linslider->setValue(frameno);
+  fine = save;
+}
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision 179)
+++ src/Makefile.in	(working copy)
@@ -71,7 +71,8 @@
 	moc_mplayererrorbase.cpp \
 	moc_progressstatusbar.cpp \
 	moc_progresswindow.cpp \
-	moc_progresswindowbase.cpp
+	moc_progresswindowbase.cpp \
+	moc_framesequence.cpp
 
 UIC = \
 	uic_dvbcutbase.cpp \
@@ -85,7 +86,8 @@
 	imageprovider.cpp index.cpp lavfmuxer.cpp logoutput.cpp \
 	main.cpp mpegmuxer.cpp mpgfile.cpp playaudio.cpp \
 	progressstatusbar.cpp progresswindow.cpp psfile.cpp \
-	pts.cpp streamdata.cpp tsfile.cpp settings.cpp $(MOC) $(UIC) \
+	pts.cpp streamdata.cpp tsfile.cpp settings.cpp framesequence.cpp \
+	$(MOC) $(UIC) \
 	$(STDLIB)
 
 OBJS = $(SRCS:.cpp=.$(OBJEXT))
Index: src/settings.h
===================================================================
--- src/settings.h	(revision 179)
+++ src/settings.h	(working copy)
@@ -85,7 +85,12 @@
   int chapter_tolerance;
   double chapter_threshold;
   int chapter_minimum;
-
+  int frameseq_nframes;
+  QString frameseq_home_distance;
+  QString frameseq_distances;
+  int frameseq_button_minwidth;
+  bool create_index_file;
+  int search_dups_range;
 };
 
 // access function
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
DVBCUT-devel mailing list
DVBCUT-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dvbcut-devel

Reply via email to