Hi,

I attached my improved pipe version... 
Guess, someone has to open/learn QTdesigner now... ;)

Am Donnerstag, 29. November 2007 19:14 schrieb Michael Riepe:
> >>I'll also take a look into
> >>adding a checkbox (or similar) for choosing pipe output.
> >
> > I also played a little bit around with that and added an entry
> > to the muxerlist which uses a configurable command/label form the
> > settings-file (see the attached patch)...
>
> Nah... that's non-obvious. Besides that, you'll want to be able to use
> all muxers (except the TS muxer, maybe) for authoring.

More obvious than specifing the pipe in the file input field... ;)
One has to know that such a thing is possible, but when you see an entry in 
the combo box you know...

And normally for a given pipe command not all muxers make sense, so 
it is dangerous to let the user choose among all with a combo box (at least 
for the preset pipe commands). For instance dvdauthor only will work with DVD 
NAV-Pakets (muxer 0 and 2)...

Therefore I added now the appropriate muxer format to be used to the 
settings... additionally now an arbirtrary number of additional user 
configurable pipe commands is possible (beside the default dvdauthor call)!

>
> > OK,... with this approach I fixed the muxer type to the internal one
> > which is not very flexible (= 1. not so nice feature). If you know how to
> > add a checkbox "Use Output Pipe" one could also select the ffmpeg muxer
> > or even other output formats... that would be better!
> >
> > The specified command line in the settings understands the placeholders
> > %CHAPTER% and %OUTPUT%... the first one will be replaced by the comma
> > separated list of chapter time stamps and the later by the file or
> > directory name given in the dialog.
> >
> > Unfortunately this is a FileOpen dialog and so to get a directory for the
> > dvdauthor output one has to type it manually ( = 2. not so nice feature).
>
> Yep. I think it's better to use a custom dialog that also includes a
> checkbox and another text field for the postprocessing command (sans "|"
> in front of it).

That would be the best solution... a file menu entry "Export to pipe" (like 
"Export video"), which opens a dialog with a file/directory selection field, 
a combo box with the available pipe commands (editable/viewable in an 
additional text field) and an additonal checkbox&textfield for an optional  
post processing command. Actually I already had that idea, too... ;) 

Therefore there is now also an entry in the settings called /pipe/#-post... 
unfortunaely (without the checkbox/dialog) the post processing command will 
be executed (with some error checking) every time selecting the appropriate 
pipe command and so disabled multi-titleset DVDs (if you don't edit the 
config file in between). 

>
> > I also added a check for exists()&isExecutable() of the used command,
> > since your patch crashed when not finding the pipe script. Unfortunatley
> > this implies now, that one has to give the command/script with full
> > pathname (= 3. not so nice feature). Maybe some one knows a solution for
> > checking the $PATH for a command drom inside dvbcut (analog to the which
> > command)?
>
> It's better to add proper error checking and reporting to the pipe code.
> So far, the function just returns when it cannot fork or open the pipe,
> and the exit status of the child isn't checked either, so there is no
> indication at all if the export actually worked.

No idea how to do this... does execl return the child return code?

I use now system() (what exactly is the difference to exec()?) to check for 
the pipe command with 'which' and only proceed if the commmand is found!
Therefore one can now again give a pipe comand without specifying the full 
path (if it's in the systems $PATH).

>
> > PS: BTW,... I found a bug concerning the chapterlist, which is also fixed
> > in this patch! I also can send it separately Michael if you want to
> > include it before (just 3-4 lines in the end of dvbcut.cpp resp. in
> > quick_picture_lookup_table()... maybe a left over from the old mechanism,
> > showing up when START is on picture 0...?).
>
> You mean, this one?
>
> >          }
> >          break;
> >        case EventListItem::chapter:
> > -   if (startpic<=0)
> > -     chapterlist.push_back(outpts);
> > -   else
> > +   if (startpic>=0)
> >       chapterlist.push_back(eli.getpts()-startpts+outpts);
> >     break;
> >        default:

Yes,... exactly! Hope it works now under all cirumstances...

ciao
Ralph

PS: BTW,... with this patch the %CHAPTERS% tag can now also be used if the 
pipe command is given in the export file input field (anyhow,...  I guess this 
patch will just be preliminary until we have a proper pipe dialog). :)
diff -Naur svn/src/dvbcut.cpp r105-pipeoutput/src/dvbcut.cpp
--- svn/src/dvbcut.cpp	2007-11-28 16:12:51.000000000 +0100
+++ r105-pipeoutput/src/dvbcut.cpp	2007-11-30 12:41:34.000000000 +0100
@@ -510,6 +510,12 @@
   expd->muxercombo->insertItem("MPEG program stream (DVBCUT multiplexer)");
   expd->muxercombo->insertItem("MPEG program stream/DVD (libavformat)");
   expd->muxercombo->insertItem("MPEG transport stream (libavformat)");
+#ifndef __WIN32__
+  // add possible user configured pipe commands 
+  int pipe_items_start=expd->muxercombo->count();
+  for (unsigned int i = 0; i < settings().pipe_command.size(); ++i)
+    expd->muxercombo->insertItem(settings().pipe_label[i]);
+#endif
 
   if (settings().export_format < 0
       || settings().export_format >= expd->muxercombo->count())
@@ -534,12 +540,69 @@
     expd->hide();
   }
 
+  // create usable chapter lists 
+  std::string chapterstring, chaptercolumn;
+  if (!chapterlist.empty()) {
+    int nchar=0;
+    char chapter[16];
+    pts_t lastch=-1;
+    for(std::list<pts_t>::const_iterator it=chapterlist.begin();
+        it!=chapterlist.end();++it)
+      if (*it != lastch) {
+        lastch=*it;
+        // formatting the chapter string
+        if (nchar>0) {
+          nchar++; 
+          chapterstring+=",";
+          chaptercolumn+="\n";
+        }  
+        nchar+=sprintf(chapter,"%02d:%02d:%02d.%03d",
+                       int(lastch/(3600*90000)),
+                       int(lastch/(60*90000))%60,
+                       int(lastch/90000)%60,
+                       int(lastch/90)%1000	);
+        // append chapter marks to lists for plain text / dvdauthor xml-file         
+        chapterstring+=chapter;
+        chaptercolumn+=chapter;
+      }
+  }
+
   int child_pid = -1;
   int pipe_fds[2];
 
 #ifndef __WIN32__
   // check for piped output
-  if (expfilen[0] == '|') {
+  std::string expcmd;
+  size_t pos;
+  int ip=settings().export_format-pipe_items_start; 
+  if(ip>=0) {
+    if (settings().pipe_command[ip].find('|')==-1) 
+      expcmd = "|"+std::string(settings().pipe_command[ip].ascii());
+    else 
+      expcmd = std::string(settings().pipe_command[ip].ascii());
+       
+    if ((pos=expcmd.find("%OUTPUT%"))!=std::string::npos)
+      expcmd.replace(pos,8,expfilen);  
+  } else 
+    expcmd = expfilen;
+
+  // chapter tag can also be used with input field pipes!
+  if ((pos=expcmd.find("%CHAPTERS%"))!=std::string::npos)
+    expcmd.replace(pos,10,chapterstring);  
+
+  if ((pos=expcmd.find('|'))!=std::string::npos) {
+    pos++;   
+    size_t end=expcmd.find(' ',pos);  
+    //if (!QFileInfo(expcmd.substr(pos,end-pos)).exists() ||
+    //    !QFileInfo(expcmd.substr(pos,end-pos)).isExecutable()) {
+    // better test if command is found in $PATH, so one don't needs to give the full path name
+    std::string which="which "+expcmd.substr(pos,end-pos)+" >/dev/null";
+    int irc = system(which.c_str());
+    if(irc!=0) { 
+      critical("Command not found - dvbcut","Problems with piped output to:\n"+expcmd.substr(pos,end-pos));
+      return; 
+    }       
+
     if (::pipe(pipe_fds) < 0)
       return;
     child_pid = fork();
@@ -548,11 +611,11 @@
       if (pipe_fds[0] != STDIN_FILENO) {
 	dup2(pipe_fds[0], STDIN_FILENO);
       }
-      //fprintf(stderr, "Executing %s\n", expfilen.c_str()+1);
+      //fprintf(stderr, "Executing %s\n", expcmd.c_str()+pos);
       for (int fd=0; fd<256; ++fd)
 	if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
 	  ::close(fd);
-      execl("/bin/sh", "sh", "-c", expfilen.c_str()+1, (char *)0);
+      execl("/bin/sh", "sh", "-c", expcmd.c_str()+pos, (char *)0);
       _exit(127);
     }
     ::close(pipe_fds[0]);
@@ -562,7 +625,6 @@
     }
   } else
 #endif
-
   if (QFileInfo(expfilen).exists() && question(
       "File exists - dvbcut",
       expfilen+"\nalready exists. "
@@ -593,7 +655,15 @@
   std::string out_file = (child_pid < 0) ? expfilen :
     std::string("pipe:") + (const char*)QString::number(pipe_fds[1]);
 
-  switch(settings().export_format) {
+  int expfmt;
+#ifndef __WIN32__
+  if (ip>=0)
+    expfmt=settings().pipe_format[ip];
+  else  
+#endif
+    expfmt=settings().export_format;
+
+  switch(expfmt) {
     case 1:
       mux=std::auto_ptr<muxer>(new mpegmuxer(audiostreammask,*mpg,out_file.c_str(),false,0));
       break;
@@ -648,47 +718,55 @@
   }
 
   mux.reset();
+
+  log->printheading("Saved %d pictures (%02d:%02d:%02d.%03d)",savedpic,
+		    int(savedtime/(3600*90000)),
+		    int(savedtime/(60*90000))%60,
+		    int(savedtime/90000)%60,
+		    int(savedtime/90)%1000	);
+
 #ifndef __WIN32__
   if (child_pid > 0) {
     ::close(pipe_fds[1]);
     int wstatus;
     while (waitpid(child_pid, &wstatus, 0)==-1 && errno==EINTR);
   }
-#endif
 
-  log->printheading("Saved %d pictures (%02d:%02d:%02d.%03d)",savedpic,
-		    int(savedtime/(3600*90000)),
-		    int(savedtime/(60*90000))%60,
-		    int(savedtime/90000)%60,
-		    int(savedtime/90)%1000	);
+  // do some post processing if requested
+  if (ip>=0 && !settings().pipe_post[ip].isEmpty()) {
+    expcmd = std::string(settings().pipe_post[ip].ascii());
+       
+    if ((pos=expcmd.find("%OUTPUT%"))!=std::string::npos)
+      expcmd.replace(pos,8,expfilen);  
+
+    pos=expcmd.find(' ');  
+    std::string which="which "+expcmd.substr(0,pos)+" >/dev/null";
 
-  std::string chapterstring;
-  if (!chapterlist.empty()) {
-    int nchar=0;
-    char chapter[16];
     log->print("");
-    log->printheading("Chapter list");
-    pts_t lastch=-1;
-    for(std::list<pts_t>::const_iterator it=chapterlist.begin();
-        it!=chapterlist.end();++it)
-      if (*it != lastch) {
-        lastch=*it;
-        // formatting the chapter string
-        if (nchar>0) {
-          nchar++; 
-          chapterstring+=",";
-        }  
-        nchar+=sprintf(chapter,"%02d:%02d:%02d.%03d",
-                       int(lastch/(3600*90000)),
-                       int(lastch/(60*90000))%60,
-                       int(lastch/90000)%60,
-                       int(lastch/90)%1000	);
-        // normal output as before
-	log->print(chapter);
-        // append chapter marks to a comma separated list for dvdauthor xml-file         
-        chapterstring+=chapter;
-      }
-  }
+    log->printheading("Performing post processing");
+    int irc = system(which.c_str());
+
+    if(irc!=0) { 
+      critical("Command not found - dvbcut","Problems with post processing command:\n"+expcmd.substr(0,pos));
+      log->print("Command not found!");
+    } else {      
+      int irc = system(expcmd.c_str());
+      if(irc!=0) { 
+        critical("Post processing error - dvbcut","Post processing command:\n"+
+                 expcmd+"\n returned non-zero exit code: " +QString::number(irc));
+        log->print("Command reported some problems... please check!");
+      } 
+      //else      
+      //  log->print("Everything seems to be OK...");
+    }
+  }   
+#endif
+
+  // print plain list of chapter marks
+  log->print("");
+  log->printheading("Chapter list");
+  log->print(chaptercolumn.c_str());
+
   // simple dvdauthor xml file with chapter marks
   std::string filename,destname;
   if (expfilen.rfind("/")<expfilen.length()) 
@@ -2063,9 +2141,7 @@
         }
         break;
       case EventListItem::chapter:
-	if (startpic<=0)
-	  chapterlist.push_back(outpts);
-	else
+	if (startpic>=0)
 	  chapterlist.push_back(eli.getpts()-startpts+outpts);
 	break;
       default:
diff -Naur svn/src/settings.cpp r105-pipeoutput/src/settings.cpp
--- svn/src/settings.cpp	2007-11-28 16:12:51.000000000 +0100
+++ r105-pipeoutput/src/settings.cpp	2007-11-30 12:38:43.000000000 +0100
@@ -49,6 +49,22 @@
 #define DVBCUT_DEFAULT_BOOKMARK_LABEL \
 	"<font color=\"darkblue\">BOOKMARK</font>"
 
+#define DVBCUT_DEFAULT_PIPE_COMMAND \
+        "|dvdauthor -t -c '%CHAPTERS%' -v mpeg2 -o %OUTPUT% -"
+#define DVBCUT_DEFAULT_PIPE_POST \
+        "dvdauthor -o %OUTPUT% -T"
+#define DVBCUT_DEFAULT_PIPE_LABEL \
+        "DVD-Video titleset (dvdauthor)"
+#define DVBCUT_DEFAULT_PIPE_FORMAT (0)
+/* ok,... for time consuming conversions one does not save any time processing the piped output... but just as an example. ;-) 
+#define DVBCUT_DEFAULT_PIPE_COMMAND \
+        "|ffmpeg -f mpeg2video -i - -f avi -vcodec mpeg4 -b 1200k -g 250 -bf 2 -acodec libmp3lame -ab 128k -ar 44100 %OUTPUT%"
+#define DVBCUT_DEFAULT_PIPE_POST ""
+#define DVBCUT_DEFAULT_PIPE_LABEL \
+        "MPEG-4/ASP (ffmpeg)"
+#define DVBCUT_DEFAULT_PIPE_FORMAT (1)
+*/
+
 dvbcut_settings::dvbcut_settings() {
   setPath(DVBCUT_QSETTINGS_DOMAIN, DVBCUT_QSETTINGS_PRODUCT);
   beginGroup("/" DVBCUT_QSETTINGS_DOMAIN "/" DVBCUT_QSETTINGS_PRODUCT);
@@ -122,6 +138,29 @@
     snapshot_range = readNumEntry("/range", 0);
     snapshot_samples = readNumEntry("/samples", 1);
   endGroup();	// snapshots
+  beginGroup("/pipe");
+    pipe_command.clear();
+    pipe_post.clear();
+    pipe_label.clear();
+    pipe_format.clear();
+    QString command = readEntry("/0-command", DVBCUT_DEFAULT_PIPE_COMMAND);
+    QString post = readEntry("/0-post", DVBCUT_DEFAULT_PIPE_POST);
+    QString label = readEntry("/0-label", DVBCUT_DEFAULT_PIPE_LABEL);
+    int format = readNumEntry("/0-format", DVBCUT_DEFAULT_PIPE_FORMAT);
+    unsigned int i = 0;
+    while(!command.isEmpty() && !label.isEmpty()) {
+      if(format<0 || format>3) format = 0;
+      pipe_command.push_back(command);
+      pipe_post.push_back(post);
+      pipe_label.push_back(label);
+      pipe_format.push_back(format);
+      QString key = "/" + QString::number(++i);
+      command = readEntry(key + "-command");
+      post = readEntry(key + "-post");
+      label = readEntry(key + "-label");
+      format = readNumEntry(key + "-format", 0);
+    }
+  endGroup();	// pipe
 }
 
 void
@@ -176,6 +215,15 @@
     writeEntry("/range", snapshot_range);
     writeEntry("/samples", snapshot_samples);
   endGroup();	// snapshots
+  beginGroup("/pipe");
+    for (unsigned int i = 0; i < pipe_command.size(); ++i) {
+      QString key = "/" + QString::number(i);
+      writeEntry(key+"-command", pipe_command[i]);
+      writeEntry(key+"-post", pipe_post[i]);
+      writeEntry(key+"-label", pipe_label[i]);
+      writeEntry(key+"-format", pipe_format[i]);
+    }
+  endGroup();	// pipe
 }
 
 // private settings variable
diff -Naur svn/src/settings.h r105-pipeoutput/src/settings.h
--- svn/src/settings.h	2007-11-28 16:12:51.000000000 +0100
+++ r105-pipeoutput/src/settings.h	2007-11-30 12:04:48.000000000 +0100
@@ -75,6 +75,10 @@
   int snapshot_width;
   int snapshot_range;
   int snapshot_samples;
+  std::vector<QString> pipe_command;
+  std::vector<QString> pipe_post;
+  std::vector<QString> pipe_label;
+  std::vector<int> pipe_format;
 
 };
 
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
DVBCUT-user mailing list
DVBCUT-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dvbcut-user

Reply via email to