giffer

Create .gif images from sites like youtube.com
Log | Files | Refs | LICENSE

pipe.go (1227B)


      1 package giffer
      2 
      3 import (
      4 	"bytes"
      5 	"io"
      6 	"log"
      7 	"os/exec"
      8 
      9 	"github.com/pkg/errors"
     10 )
     11 
     12 // CmdPipe executes a stack of commands, piping in order.
     13 type CmdPipe struct {
     14 	In    io.Reader
     15 	Out   io.Writer
     16 	Stack []*exec.Cmd
     17 
     18 	Debug bool
     19 }
     20 
     21 // Run the commands.
     22 func (p CmdPipe) Run() (err error) {
     23 	var errBuf bytes.Buffer
     24 	defer func() {
     25 		if p.Debug {
     26 			log.Printf("%s", errBuf.String())
     27 		}
     28 	}()
     29 	pipes := make([]*io.PipeWriter, len(p.Stack)-1)
     30 	ii := 0
     31 	for ; ii < len(p.Stack)-1; ii++ {
     32 		if ii == 0 {
     33 			p.Stack[ii].Stdin = p.In
     34 		}
     35 		stdin, stdout := io.Pipe()
     36 		p.Stack[ii].Stdout = stdout
     37 		p.Stack[ii].Stderr = &errBuf
     38 		p.Stack[ii+1].Stdin = stdin
     39 		pipes[ii] = stdout
     40 	}
     41 	p.Stack[ii].Stdout = p.Out
     42 	p.Stack[ii].Stderr = &errBuf
     43 	if err := call(p.Stack, pipes); err != nil {
     44 		return errors.Wrap(err, string(errBuf.Bytes()))
     45 	}
     46 	return err
     47 }
     48 
     49 func call(stack []*exec.Cmd, pipes []*io.PipeWriter) (err error) {
     50 	if stack[0].Process == nil {
     51 		if err = stack[0].Start(); err != nil {
     52 			return err
     53 		}
     54 	}
     55 	if len(stack) > 1 {
     56 		if err = stack[1].Start(); err != nil {
     57 			return err
     58 		}
     59 		defer func() {
     60 			if err == nil {
     61 				pipes[0].Close()
     62 				err = call(stack[1:], pipes[1:])
     63 			}
     64 		}()
     65 	}
     66 	return stack[0].Wait()
     67 }