<commit_before>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tar

import (
	"bytes"
	"io/ioutil"
	"os"
	"reflect"
	"testing"
	"time"
)

func TestFileInfoHeader(t *testing.T) {
	fi, err := os.Stat("testdata/small.txt")
	if err != nil {
		t.Fatal(err)
	}
	h, err := FileInfoHeader(fi, "")
	if err != nil {
		t.Fatalf("FileInfoHeader: %v", err)
	}
	if g, e := h.Name, "small.txt"; g != e {
		t.Errorf("Name = %q; want %q", g, e)
	}
	if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e {
		t.Errorf("Mode = %#o; want %#o", g, e)
	}
	if g, e := h.Size, int64(5); g != e {
		t.Errorf("Size = %v; want %v", g, e)
	}
	if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
		t.Errorf("ModTime = %v; want %v", g, e)
	}
}

func TestFileInfoHeaderDir(t *testing.T) {
	fi, err := os.Stat("testdata")
	if err != nil {
		t.Fatal(err)
	}
	h, err := FileInfoHeader(fi, "")
	if err != nil {
		t.Fatalf("FileInfoHeader: %v", err)
	}
	if g, e := h.Name, "testdata/"; g != e {
		t.Errorf("Name = %q; want %q", g, e)
	}
	if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISDIR; g != e {
		t.Errorf("Mode = %#o; want %#o", g, e)
	}
	if g, e := h.Size, int64(0); g != e {
		t.Errorf("Size = %v; want %v", g, e)
	}
	if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
		t.Errorf("ModTime = %v; want %v", g, e)
	}
}

func TestFileInfoHeaderSymlink(t *testing.T) {
	h, err := FileInfoHeader(symlink{}, "some-target")
	if err != nil {
		t.Fatal(err)
	}
	if g, e := h.Name, "some-symlink"; g != e {
		t.Errorf("Name = %q; want %q", g, e)
	}
	if g, e := h.Linkname, "some-target"; g != e {
		t.Errorf("Linkname = %q; want %q", g, e)
	}
}

type symlink struct{}

func (symlink) Name() string       { return "some-symlink" }
func (symlink) Size() int64        { return 0 }
func (symlink) Mode() os.FileMode  { return os.ModeSymlink }
func (symlink) ModTime() time.Time { return time.Time{} }
func (symlink) IsDir() bool        { return false }
func (symlink) Sys() interface{}   { return nil }

func TestRoundTrip(t *testing.T) {
	data := []byte("some file contents")

	var b bytes.Buffer
	tw := NewWriter(&b)
	hdr := &Header{
		Name:    "file.txt",
		Uid:     1 << 21, // too big for 8 octal digits
		Size:    int64(len(data)),
		ModTime: time.Now(),
	}
	// tar only supports second precision.
	hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond)
	if err := tw.WriteHeader(hdr); err != nil {
		t.Fatalf("tw.WriteHeader: %v", err)
	}
	if _, err := tw.Write(data); err != nil {
		t.Fatalf("tw.Write: %v", err)
	}
	if err := tw.Close(); err != nil {
		t.Fatalf("tw.Close: %v", err)
	}

	// Read it back.
	tr := NewReader(&b)
	rHdr, err := tr.Next()
	if err != nil {
		t.Fatalf("tr.Next: %v", err)
	}
	if !reflect.DeepEqual(rHdr, hdr) {
		t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
	}
	rData, err := ioutil.ReadAll(tr)
	if err != nil {
		t.Fatalf("Read: %v", err)
	}
	if !bytes.Equal(rData, data) {
		t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data)
	}
}

type headerRoundTripTest struct {
	h  *Header
	fm os.FileMode
}

func TestHeaderRoundTrip(t *testing.T) {
	golden := []headerRoundTripTest{
		// regular file.
		{
			h: &Header{
				Name:     "test.txt",
				Mode:     0644 | c_ISREG,
				Size:     12,
				ModTime:  time.Unix(1360600916, 0),
				Typeflag: TypeReg,
			},
			fm: 0644,
		},
		// hard link.
		{
			h: &Header{
				Name:     "hard.txt",
				Mode:     0644 | c_ISLNK,
				Size:     0,
				ModTime:  time.Unix(1360600916, 0),
				Typeflag: TypeLink,
			},
			fm: 0644 | os.ModeSymlink,
		},
		// symbolic link.
		{
			h: &Header{
				Name:     "link.txt",
				Mode:     0777 | c_ISLNK,
				Size:     0,
				ModTime:  time.Unix(1360600852, 0),
				Typeflag: TypeSymlink,
			},
			fm: 0777 | os.ModeSymlink,
		},
		// character device node.
		{
			h: &Header{
				Name:     "dev/null",
				Mode:     0666 | c_ISCHR,
				Size:     0,
				ModTime:  time.Unix(1360578951, 0),
				Typeflag: TypeChar,
			},
			fm: 0666 | os.ModeDevice | os.ModeCharDevice,
		},
		// block device node.
		{
			h: &Header{
				Name:     "dev/sda",
				Mode:     0660 | c_ISBLK,
				Size:     0,
				ModTime:  time.Unix(1360578954, 0),
				Typeflag: TypeBlock,
			},
			fm: 0660 | os.ModeDevice,
		},
		// directory.
		{
			h: &Header{
				Name:     "dir/",
				Mode:     0755 | c_ISDIR,
				Size:     0,
				ModTime:  time.Unix(1360601116, 0),
				Typeflag: TypeDir,
			},
			fm: 0755 | os.ModeDir,
		},
		// fifo node.
		{
			h: &Header{
				Name:     "dev/initctl",
				Mode:     0600 | c_ISFIFO,
				Size:     0,
				ModTime:  time.Unix(1360578949, 0),
				Typeflag: TypeFifo,
			},
			fm: 0600 | os.ModeNamedPipe,
		},
		// setuid.
		{
			h: &Header{
				Name:     "bin/su",
				Mode:     0755 | c_ISREG | c_ISUID,
				Size:     23232,
				ModTime:  time.Unix(1355405093, 0),
				Typeflag: TypeReg,
			},
			fm: 0755 | os.ModeSetuid,
		},
		// setguid.
		{
			h: &Header{
				Name:     "group.txt",
				Mode:     0750 | c_ISREG | c_ISGID,
				Size:     0,
				ModTime:  time.Unix(1360602346, 0),
				Typeflag: TypeReg,
			},
			fm: 0750 | os.ModeSetgid,
		},
		// sticky.
		{
			h: &Header{
				Name:     "sticky.txt",
				Mode:     0600 | c_ISREG | c_ISVTX,
				Size:     7,
				ModTime:  time.Unix(1360602540, 0),
				Typeflag: TypeReg,
			},
			fm: 0600 | os.ModeSticky,
		},
	}

	for i, g := range golden {
		fi := g.h.FileInfo()
		h2, err := FileInfoHeader(fi, "")
		if err != nil {
			t.Error(err)
			continue
		}
		if got, want := h2.Name, g.h.Name; got != want {
			t.Errorf("i=%d: Name: got %v, want %v", i, got, want)
		}
		if got, want := h2.Size, g.h.Size; got != want {
			t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
		}
		if got, want := h2.Mode, g.h.Mode; got != want {
			t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
		}
		if got, want := fi.Mode(), g.fm; got != want {
			t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
		}
		if got, want := h2.ModTime, g.h.ModTime; got != want {
			t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
		}
		if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h {
			t.Errorf("i=%d: Sys didn't return original *Header", i)
		}
	}
}
<commit_msg>archive/tar: make test pass on setgid dirs<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tar

import (
	"bytes"
	"io/ioutil"
	"os"
	"reflect"
	"testing"
	"time"
)

func TestFileInfoHeader(t *testing.T) {
	fi, err := os.Stat("testdata/small.txt")
	if err != nil {
		t.Fatal(err)
	}
	h, err := FileInfoHeader(fi, "")
	if err != nil {
		t.Fatalf("FileInfoHeader: %v", err)
	}
	if g, e := h.Name, "small.txt"; g != e {
		t.Errorf("Name = %q; want %q", g, e)
	}
	if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e {
		t.Errorf("Mode = %#o; want %#o", g, e)
	}
	if g, e := h.Size, int64(5); g != e {
		t.Errorf("Size = %v; want %v", g, e)
	}
	if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
		t.Errorf("ModTime = %v; want %v", g, e)
	}
}

func TestFileInfoHeaderDir(t *testing.T) {
	fi, err := os.Stat("testdata")
	if err != nil {
		t.Fatal(err)
	}
	h, err := FileInfoHeader(fi, "")
	if err != nil {
		t.Fatalf("FileInfoHeader: %v", err)
	}
	if g, e := h.Name, "testdata/"; g != e {
		t.Errorf("Name = %q; want %q", g, e)
	}
	const setsid = 02000 // see golang.org/issue/4867
	if g, e := h.Mode&^setsid, int64(fi.Mode().Perm())|c_ISDIR; g != e {
		t.Errorf("Mode = %#o; want %#o", g, e)
	}
	if g, e := h.Size, int64(0); g != e {
		t.Errorf("Size = %v; want %v", g, e)
	}
	if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
		t.Errorf("ModTime = %v; want %v", g, e)
	}
}

func TestFileInfoHeaderSymlink(t *testing.T) {
	h, err := FileInfoHeader(symlink{}, "some-target")
	if err != nil {
		t.Fatal(err)
	}
	if g, e := h.Name, "some-symlink"; g != e {
		t.Errorf("Name = %q; want %q", g, e)
	}
	if g, e := h.Linkname, "some-target"; g != e {
		t.Errorf("Linkname = %q; want %q", g, e)
	}
}

type symlink struct{}

func (symlink) Name() string       { return "some-symlink" }
func (symlink) Size() int64        { return 0 }
func (symlink) Mode() os.FileMode  { return os.ModeSymlink }
func (symlink) ModTime() time.Time { return time.Time{} }
func (symlink) IsDir() bool        { return false }
func (symlink) Sys() interface{}   { return nil }

func TestRoundTrip(t *testing.T) {
	data := []byte("some file contents")

	var b bytes.Buffer
	tw := NewWriter(&b)
	hdr := &Header{
		Name:    "file.txt",
		Uid:     1 << 21, // too big for 8 octal digits
		Size:    int64(len(data)),
		ModTime: time.Now(),
	}
	// tar only supports second precision.
	hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond)
	if err := tw.WriteHeader(hdr); err != nil {
		t.Fatalf("tw.WriteHeader: %v", err)
	}
	if _, err := tw.Write(data); err != nil {
		t.Fatalf("tw.Write: %v", err)
	}
	if err := tw.Close(); err != nil {
		t.Fatalf("tw.Close: %v", err)
	}

	// Read it back.
	tr := NewReader(&b)
	rHdr, err := tr.Next()
	if err != nil {
		t.Fatalf("tr.Next: %v", err)
	}
	if !reflect.DeepEqual(rHdr, hdr) {
		t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
	}
	rData, err := ioutil.ReadAll(tr)
	if err != nil {
		t.Fatalf("Read: %v", err)
	}
	if !bytes.Equal(rData, data) {
		t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data)
	}
}

type headerRoundTripTest struct {
	h  *Header
	fm os.FileMode
}

func TestHeaderRoundTrip(t *testing.T) {
	golden := []headerRoundTripTest{
		// regular file.
		{
			h: &Header{
				Name:     "test.txt",
				Mode:     0644 | c_ISREG,
				Size:     12,
				ModTime:  time.Unix(1360600916, 0),
				Typeflag: TypeReg,
			},
			fm: 0644,
		},
		// hard link.
		{
			h: &Header{
				Name:     "hard.txt",
				Mode:     0644 | c_ISLNK,
				Size:     0,
				ModTime:  time.Unix(1360600916, 0),
				Typeflag: TypeLink,
			},
			fm: 0644 | os.ModeSymlink,
		},
		// symbolic link.
		{
			h: &Header{
				Name:     "link.txt",
				Mode:     0777 | c_ISLNK,
				Size:     0,
				ModTime:  time.Unix(1360600852, 0),
				Typeflag: TypeSymlink,
			},
			fm: 0777 | os.ModeSymlink,
		},
		// character device node.
		{
			h: &Header{
				Name:     "dev/null",
				Mode:     0666 | c_ISCHR,
				Size:     0,
				ModTime:  time.Unix(1360578951, 0),
				Typeflag: TypeChar,
			},
			fm: 0666 | os.ModeDevice | os.ModeCharDevice,
		},
		// block device node.
		{
			h: &Header{
				Name:     "dev/sda",
				Mode:     0660 | c_ISBLK,
				Size:     0,
				ModTime:  time.Unix(1360578954, 0),
				Typeflag: TypeBlock,
			},
			fm: 0660 | os.ModeDevice,
		},
		// directory.
		{
			h: &Header{
				Name:     "dir/",
				Mode:     0755 | c_ISDIR,
				Size:     0,
				ModTime:  time.Unix(1360601116, 0),
				Typeflag: TypeDir,
			},
			fm: 0755 | os.ModeDir,
		},
		// fifo node.
		{
			h: &Header{
				Name:     "dev/initctl",
				Mode:     0600 | c_ISFIFO,
				Size:     0,
				ModTime:  time.Unix(1360578949, 0),
				Typeflag: TypeFifo,
			},
			fm: 0600 | os.ModeNamedPipe,
		},
		// setuid.
		{
			h: &Header{
				Name:     "bin/su",
				Mode:     0755 | c_ISREG | c_ISUID,
				Size:     23232,
				ModTime:  time.Unix(1355405093, 0),
				Typeflag: TypeReg,
			},
			fm: 0755 | os.ModeSetuid,
		},
		// setguid.
		{
			h: &Header{
				Name:     "group.txt",
				Mode:     0750 | c_ISREG | c_ISGID,
				Size:     0,
				ModTime:  time.Unix(1360602346, 0),
				Typeflag: TypeReg,
			},
			fm: 0750 | os.ModeSetgid,
		},
		// sticky.
		{
			h: &Header{
				Name:     "sticky.txt",
				Mode:     0600 | c_ISREG | c_ISVTX,
				Size:     7,
				ModTime:  time.Unix(1360602540, 0),
				Typeflag: TypeReg,
			},
			fm: 0600 | os.ModeSticky,
		},
	}

	for i, g := range golden {
		fi := g.h.FileInfo()
		h2, err := FileInfoHeader(fi, "")
		if err != nil {
			t.Error(err)
			continue
		}
		if got, want := h2.Name, g.h.Name; got != want {
			t.Errorf("i=%d: Name: got %v, want %v", i, got, want)
		}
		if got, want := h2.Size, g.h.Size; got != want {
			t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
		}
		if got, want := h2.Mode, g.h.Mode; got != want {
			t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
		}
		if got, want := fi.Mode(), g.fm; got != want {
			t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
		}
		if got, want := h2.ModTime, g.h.ModTime; got != want {
			t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
		}
		if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h {
			t.Errorf("i=%d: Sys didn't return original *Header", i)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gob

import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"reflect"
	"sync"
)

// A Decoder manages the receipt of type and data information read from the
// remote side of a connection.
type Decoder struct {
	mutex        sync.Mutex                              // each item must be received atomically
	r            io.Reader                               // source of the data
	buf          bytes.Buffer                            // buffer for more efficient i/o from r
	wireType     map[typeId]*wireType                    // map from remote ID to local description
	decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines
	ignorerCache map[typeId]**decEngine                  // ditto for ignored objects
	freeList     *decoderState                           // list of free decoderStates; avoids reallocation
	countBuf     []byte                                  // used for decoding integers while parsing messages
	tmp          []byte                                  // temporary storage for i/o; saves reallocating
	err          error
}

// NewDecoder returns a new decoder that reads from the io.Reader.
// If r does not also implement io.ByteReader, it will be wrapped in a
// bufio.Reader.
func NewDecoder(r io.Reader) *Decoder {
	dec := new(Decoder)
	// We use the ability to read bytes as a plausible surrogate for buffering.
	if _, ok := r.(io.ByteReader); !ok {
		r = bufio.NewReader(r)
	}
	dec.r = r
	dec.wireType = make(map[typeId]*wireType)
	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
	dec.ignorerCache = make(map[typeId]**decEngine)
	dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes

	return dec
}

// recvType loads the definition of a type.
func (dec *Decoder) recvType(id typeId) {
	// Have we already seen this type?  That's an error
	if id < firstUserId || dec.wireType[id] != nil {
		dec.err = errors.New("gob: duplicate type received")
		return
	}

	// Type:
	wire := new(wireType)
	dec.decodeValue(tWireType, reflect.ValueOf(wire))
	if dec.err != nil {
		return
	}
	// Remember we've seen this type.
	dec.wireType[id] = wire
}

var errBadCount = errors.New("invalid message length")

// recvMessage reads the next count-delimited item from the input. It is the converse
// of Encoder.writeMessage. It returns false on EOF or other error reading the message.
func (dec *Decoder) recvMessage() bool {
	// Read a count.
	nbytes, _, err := decodeUintReader(dec.r, dec.countBuf)
	if err != nil {
		dec.err = err
		return false
	}
	// Upper limit of 1GB, allowing room to grow a little without overflow.
	// TODO: We might want more control over this limit.
	if nbytes >= 1<<30 {
		dec.err = errBadCount
		return false
	}
	dec.readMessage(int(nbytes))
	return dec.err == nil
}

// readMessage reads the next nbytes bytes from the input.
func (dec *Decoder) readMessage(nbytes int) {
	// Allocate the buffer.
	if cap(dec.tmp) < nbytes {
		dec.tmp = make([]byte, nbytes+100) // room to grow
	}
	dec.tmp = dec.tmp[:nbytes]

	// Read the data
	_, dec.err = io.ReadFull(dec.r, dec.tmp)
	if dec.err != nil {
		if dec.err == io.EOF {
			dec.err = io.ErrUnexpectedEOF
		}
		return
	}
	dec.buf.Write(dec.tmp)
}

// toInt turns an encoded uint64 into an int, according to the marshaling rules.
func toInt(x uint64) int64 {
	i := int64(x >> 1)
	if x&1 != 0 {
		i = ^i
	}
	return i
}

func (dec *Decoder) nextInt() int64 {
	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
	if err != nil {
		dec.err = err
	}
	return toInt(n)
}

func (dec *Decoder) nextUint() uint64 {
	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
	if err != nil {
		dec.err = err
	}
	return n
}

// decodeTypeSequence parses:
// TypeSequence
//	(TypeDefinition DelimitedTypeDefinition*)?
// and returns the type id of the next value.  It returns -1 at
// EOF.  Upon return, the remainder of dec.buf is the value to be
// decoded.  If this is an interface value, it can be ignored by
// resetting that buffer.
func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
	for dec.err == nil {
		if dec.buf.Len() == 0 {
			if !dec.recvMessage() {
				break
			}
		}
		// Receive a type id.
		id := typeId(dec.nextInt())
		if id >= 0 {
			// Value follows.
			return id
		}
		// Type definition for (-id) follows.
		dec.recvType(-id)
		// When decoding an interface, after a type there may be a
		// DelimitedValue still in the buffer.  Skip its count.
		// (Alternatively, the buffer is empty and the byte count
		// will be absorbed by recvMessage.)
		if dec.buf.Len() > 0 {
			if !isInterface {
				dec.err = errors.New("extra data in buffer")
				break
			}
			dec.nextUint()
		}
	}
	return -1
}

// Decode reads the next value from the connection and stores
// it in the data represented by the empty interface value.
// If e is nil, the value will be discarded. Otherwise,
// the value underlying e must be a pointer to the
// correct type for the next data item received.
func (dec *Decoder) Decode(e interface{}) error {
	if e == nil {
		return dec.DecodeValue(reflect.Value{})
	}
	value := reflect.ValueOf(e)
	// If e represents a value as opposed to a pointer, the answer won't
	// get back to the caller.  Make sure it's a pointer.
	if value.Type().Kind() != reflect.Ptr {
		dec.err = errors.New("gob: attempt to decode into a non-pointer")
		return dec.err
	}
	return dec.DecodeValue(value)
}

// DecodeValue reads the next value from the connection.
// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
// Otherwise, it stores the value into v.  In that case, v must represent
// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
func (dec *Decoder) DecodeValue(v reflect.Value) error {
	if v.IsValid() {
		if v.Kind() == reflect.Ptr && !v.IsNil() {
			// That's okay, we'll store through the pointer.
		} else if !v.CanSet() {
			return errors.New("gob: DecodeValue of unassignable value")
		}
	}
	// Make sure we're single-threaded through here.
	dec.mutex.Lock()
	defer dec.mutex.Unlock()

	dec.buf.Reset() // In case data lingers from previous invocation.
	dec.err = nil
	id := dec.decodeTypeSequence(false)
	if dec.err == nil {
		dec.decodeValue(id, v)
	}
	return dec.err
}

// If debug.go is compiled into the program , debugFunc prints a human-readable
// representation of the gob data read from r by calling that file's Debug function.
// Otherwise it is nil.
var debugFunc func(io.Reader)
<commit_msg>encoding/gob: reduce decoder memory Gob decoding reads a whole message into memory and then copies it into a bytes.Buffer. For large messages this wastes an entire copy of the message. In this CL, we use a staging buffer to avoid the large temporary.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gob

import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"reflect"
	"sync"
)

// A Decoder manages the receipt of type and data information read from the
// remote side of a connection.
type Decoder struct {
	mutex        sync.Mutex                              // each item must be received atomically
	r            io.Reader                               // source of the data
	buf          bytes.Buffer                            // buffer for more efficient i/o from r
	wireType     map[typeId]*wireType                    // map from remote ID to local description
	decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines
	ignorerCache map[typeId]**decEngine                  // ditto for ignored objects
	freeList     *decoderState                           // list of free decoderStates; avoids reallocation
	countBuf     []byte                                  // used for decoding integers while parsing messages
	tmp          []byte                                  // temporary storage for i/o; saves reallocating
	err          error
}

// NewDecoder returns a new decoder that reads from the io.Reader.
// If r does not also implement io.ByteReader, it will be wrapped in a
// bufio.Reader.
func NewDecoder(r io.Reader) *Decoder {
	dec := new(Decoder)
	// We use the ability to read bytes as a plausible surrogate for buffering.
	if _, ok := r.(io.ByteReader); !ok {
		r = bufio.NewReader(r)
	}
	dec.r = r
	dec.wireType = make(map[typeId]*wireType)
	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
	dec.ignorerCache = make(map[typeId]**decEngine)
	dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes

	return dec
}

// recvType loads the definition of a type.
func (dec *Decoder) recvType(id typeId) {
	// Have we already seen this type?  That's an error
	if id < firstUserId || dec.wireType[id] != nil {
		dec.err = errors.New("gob: duplicate type received")
		return
	}

	// Type:
	wire := new(wireType)
	dec.decodeValue(tWireType, reflect.ValueOf(wire))
	if dec.err != nil {
		return
	}
	// Remember we've seen this type.
	dec.wireType[id] = wire
}

var errBadCount = errors.New("invalid message length")

// recvMessage reads the next count-delimited item from the input. It is the converse
// of Encoder.writeMessage. It returns false on EOF or other error reading the message.
func (dec *Decoder) recvMessage() bool {
	// Read a count.
	nbytes, _, err := decodeUintReader(dec.r, dec.countBuf)
	if err != nil {
		dec.err = err
		return false
	}
	// Upper limit of 1GB, allowing room to grow a little without overflow.
	// TODO: We might want more control over this limit.
	if nbytes >= 1<<30 {
		dec.err = errBadCount
		return false
	}
	dec.readMessage(int(nbytes))
	return dec.err == nil
}

// readMessage reads the next nbytes bytes from the input.
func (dec *Decoder) readMessage(nbytes int) {
	// Allocate the dec.tmp buffer, up to 10KB.
	const maxBuf = 10 * 1024
	nTmp := nbytes
	if nTmp > maxBuf {
		nTmp = maxBuf
	}
	if cap(dec.tmp) < nTmp {
		nAlloc := nTmp + 100 // A little extra for growth.
		if nAlloc > maxBuf {
			nAlloc = maxBuf
		}
		dec.tmp = make([]byte, nAlloc)
	}
	dec.tmp = dec.tmp[:nTmp]

	// Read the data
	dec.buf.Grow(nbytes)
	for nbytes > 0 {
		if nbytes < nTmp {
			dec.tmp = dec.tmp[:nbytes]
		}
		var nRead int
		nRead, dec.err = io.ReadFull(dec.r, dec.tmp)
		if dec.err != nil {
			if dec.err == io.EOF {
				dec.err = io.ErrUnexpectedEOF
			}
			return
		}
		dec.buf.Write(dec.tmp)
		nbytes -= nRead
	}
}

// toInt turns an encoded uint64 into an int, according to the marshaling rules.
func toInt(x uint64) int64 {
	i := int64(x >> 1)
	if x&1 != 0 {
		i = ^i
	}
	return i
}

func (dec *Decoder) nextInt() int64 {
	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
	if err != nil {
		dec.err = err
	}
	return toInt(n)
}

func (dec *Decoder) nextUint() uint64 {
	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
	if err != nil {
		dec.err = err
	}
	return n
}

// decodeTypeSequence parses:
// TypeSequence
//	(TypeDefinition DelimitedTypeDefinition*)?
// and returns the type id of the next value.  It returns -1 at
// EOF.  Upon return, the remainder of dec.buf is the value to be
// decoded.  If this is an interface value, it can be ignored by
// resetting that buffer.
func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
	for dec.err == nil {
		if dec.buf.Len() == 0 {
			if !dec.recvMessage() {
				break
			}
		}
		// Receive a type id.
		id := typeId(dec.nextInt())
		if id >= 0 {
			// Value follows.
			return id
		}
		// Type definition for (-id) follows.
		dec.recvType(-id)
		// When decoding an interface, after a type there may be a
		// DelimitedValue still in the buffer.  Skip its count.
		// (Alternatively, the buffer is empty and the byte count
		// will be absorbed by recvMessage.)
		if dec.buf.Len() > 0 {
			if !isInterface {
				dec.err = errors.New("extra data in buffer")
				break
			}
			dec.nextUint()
		}
	}
	return -1
}

// Decode reads the next value from the connection and stores
// it in the data represented by the empty interface value.
// If e is nil, the value will be discarded. Otherwise,
// the value underlying e must be a pointer to the
// correct type for the next data item received.
func (dec *Decoder) Decode(e interface{}) error {
	if e == nil {
		return dec.DecodeValue(reflect.Value{})
	}
	value := reflect.ValueOf(e)
	// If e represents a value as opposed to a pointer, the answer won't
	// get back to the caller.  Make sure it's a pointer.
	if value.Type().Kind() != reflect.Ptr {
		dec.err = errors.New("gob: attempt to decode into a non-pointer")
		return dec.err
	}
	return dec.DecodeValue(value)
}

// DecodeValue reads the next value from the connection.
// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
// Otherwise, it stores the value into v.  In that case, v must represent
// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
func (dec *Decoder) DecodeValue(v reflect.Value) error {
	if v.IsValid() {
		if v.Kind() == reflect.Ptr && !v.IsNil() {
			// That's okay, we'll store through the pointer.
		} else if !v.CanSet() {
			return errors.New("gob: DecodeValue of unassignable value")
		}
	}
	// Make sure we're single-threaded through here.
	dec.mutex.Lock()
	defer dec.mutex.Unlock()

	dec.buf.Reset() // In case data lingers from previous invocation.
	dec.err = nil
	id := dec.decodeTypeSequence(false)
	if dec.err == nil {
		dec.decodeValue(id, v)
	}
	return dec.err
}

// If debug.go is compiled into the program , debugFunc prints a human-readable
// representation of the gob data read from r by calling that file's Debug function.
// Otherwise it is nil.
var debugFunc func(io.Reader)
<|endoftext|>


<commit_before>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build netbsd

package net

func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
	panic("unimplemented")
}

func setIPv4MulticastLoopback(fd *netFD, v bool) error {
	panic("unimplemented")
}
<commit_msg>net: no panic on placeholders for netbsd<commit_after>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// IP-level socket options for NetBSD

package net

import "syscall"

func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
	// TODO: Implement this
	return nil, syscall.EAFNOSUPPORT
}

func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
	// TODO: Implement this
	return syscall.EAFNOSUPPORT
}

func ipv4MulticastLoopback(fd *netFD) (bool, error) {
	// TODO: Implement this
	return false, syscall.EAFNOSUPPORT
}

func setIPv4MulticastLoopback(fd *netFD, v bool) error {
	// TODO: Implement this
	return syscall.EAFNOSUPPORT
}

func ipv4ReceiveInterface(fd *netFD) (bool, error) {
	// TODO: Implement this
	return false, syscall.EAFNOSUPPORT
}

func setIPv4ReceiveInterface(fd *netFD, v bool) error {
	// TODO: Implement this
	return syscall.EAFNOSUPPORT
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build nocgo

package user

import (
	"fmt"
	"runtime"
)

func Lookup(username string) (*User, error) {
	return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}

func LookupId(int) (*User, error) {
	return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
<commit_msg>os/user: not on windows<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build nocgo windows

package user

import (
	"fmt"
	"runtime"
)

func Lookup(username string) (*User, error) {
	return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}

func LookupId(int) (*User, error) {
	return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
<|endoftext|>


<commit_before>/*
 *
 * pig is a very simple game involving dice rolls.
 *
 */
package pig

import (
	"github.com/jkomoros/boardgame"
)

//go:generate autoreader

type gameDelegate struct {
	boardgame.DefaultGameDelegate
}

func (g *gameDelegate) Name() string {
	return "pig"
}

func (g *gameDelegate) DisplayName() string {
	return "Pig"
}

func (g *gameDelegate) LegalNumPlayers(numPlayers int) bool {
	return numPlayers > 0 && numPlayers < 6
}

func (g *gameDelegate) DefaultNumPlayers() int {
	return 2
}

func (g *gameDelegate) EmptyGameState() boardgame.MutableSubState {
	dice := g.Manager().Chest().Deck(diceDeckName)

	if dice == nil {
		return nil
	}

	return &gameState{
		CurrentPlayer: 0,
		Die:           boardgame.NewSizedStack(dice, 1),
	}
}

func (g *gameDelegate) EmptyPlayerState(index boardgame.PlayerIndex) boardgame.MutablePlayerState {
	return &playerState{
		playerIndex: index,
		TotalScore:  0,
		RoundScore:  0,
	}
}

func (g *gameDelegate) EmptyDynamicComponentValues(deck *boardgame.Deck) boardgame.MutableSubState {
	if deck.Name() == diceDeckName {
		return &dieDynamicValue{
			Value: 1,
		}
	}
	return nil
}

func NewManager(storage boardgame.StorageManager) *boardgame.GameManager {
	chest := boardgame.NewComponentChest()

	dice := boardgame.NewDeck()

	dice.AddComponent(DefaultDie())

	chest.AddDeck(diceDeckName, dice)

	manager := boardgame.NewGameManager(&gameDelegate{}, chest, storage)

	if manager == nil {
		panic("No manager returned")
	}

	manager.AddPlayerMoveFactory(MoveRollDiceFactory)
	manager.AddPlayerMoveFactory(MoveDoneTurnFactory)

	manager.AddFixUpMoveFactory(MoveCountDieFactory)
	manager.AddFixUpMoveFactory(MoveAdvanceNextPlayerFactory)

	manager.SetUp()

	return manager
}
<commit_msg>Make sure that the player states start off initialized correctly. Part of #372.<commit_after>/*
 *
 * pig is a very simple game involving dice rolls.
 *
 */
package pig

import (
	"github.com/jkomoros/boardgame"
)

//go:generate autoreader

type gameDelegate struct {
	boardgame.DefaultGameDelegate
}

func (g *gameDelegate) Name() string {
	return "pig"
}

func (g *gameDelegate) DisplayName() string {
	return "Pig"
}

func (g *gameDelegate) LegalNumPlayers(numPlayers int) bool {
	return numPlayers > 0 && numPlayers < 6
}

func (g *gameDelegate) DefaultNumPlayers() int {
	return 2
}

func (g *gameDelegate) EmptyGameState() boardgame.MutableSubState {
	dice := g.Manager().Chest().Deck(diceDeckName)

	if dice == nil {
		return nil
	}

	return &gameState{
		CurrentPlayer: 0,
		Die:           boardgame.NewSizedStack(dice, 1),
	}
}

func (g *gameDelegate) EmptyPlayerState(index boardgame.PlayerIndex) boardgame.MutablePlayerState {
	return &playerState{
		playerIndex: index,
		TotalScore:  0,
		RoundScore:  0,
		DieCounted:  true,
		Done:        false,
		Busted:      false,
	}
}

func (g *gameDelegate) EmptyDynamicComponentValues(deck *boardgame.Deck) boardgame.MutableSubState {
	if deck.Name() == diceDeckName {
		return &dieDynamicValue{
			Value: 1,
		}
	}
	return nil
}

func NewManager(storage boardgame.StorageManager) *boardgame.GameManager {
	chest := boardgame.NewComponentChest()

	dice := boardgame.NewDeck()

	dice.AddComponent(DefaultDie())

	chest.AddDeck(diceDeckName, dice)

	manager := boardgame.NewGameManager(&gameDelegate{}, chest, storage)

	if manager == nil {
		panic("No manager returned")
	}

	manager.AddPlayerMoveFactory(MoveRollDiceFactory)
	manager.AddPlayerMoveFactory(MoveDoneTurnFactory)

	manager.AddFixUpMoveFactory(MoveCountDieFactory)
	manager.AddFixUpMoveFactory(MoveAdvanceNextPlayerFactory)

	manager.SetUp()

	return manager
}
<|endoftext|>


<commit_before>package main

import "github.com/aklyachkin/go-newt"

import "fmt"

func main() {
    newt.Init()
    newt.Cls()

    r := newt.NewResultStr()

    b1 := newt.Checkbox(-1, -1, "A pretty long checkbox for testing", " ", "", r)
    b2 := newt.Button(-1, -1, "Another button")
    b3 := newt.Button(-1, -1, "But, but")
    b4 := newt.Button(-1, -1, "But what?")

    f := newt.Form(nil, "", 0)

    grid := newt.CreateGrid(2, 2)
    newt.GridSetField(grid, 0, 0, newt.GRID_COMPONENT, b1, 0, 0, 0, 0, newt.ANCHOR_RIGHT, 0)
    newt.GridSetField(grid, 0, 1, newt.GRID_COMPONENT, b2, 0, 0, 0, 0, 0, 0)
    newt.GridSetField(grid, 1, 0, newt.GRID_COMPONENT, b3, 0, 0, 0, 0, 0, 0)
    newt.GridSetField(grid, 1, 1, newt.GRID_COMPONENT, b4, 0, 0, 0, 0, 0, 0)

    newt.FormAddComponents(f, b1, b2, b3, b4)
    newt.GridWrappedWindow(grid, "first window")
    newt.GridFree(grid, 1)

    newt.RunForm(f)
    newt.FormDestroy(f)

    newt.PopWindow()

    flowedText, textWidth, textHeight := newt.ReflowText(
        "This is quite a bit of text. It is 40 " +
        "columns long, so some wrapping should be " +
        "done. Did you know that the quick, brown " +
        "fox jumped over the lazy dog?\n\n" +
        "In other news, it's pretty important that we " +
        "can properly force a line break.",
        40, 5, 5)
    t := newt.Textbox(-1, -1, textWidth, textHeight, newt.FLAG_WRAP)
    newt.TextboxSetText(t, flowedText)

    b1 = newt.Button(-1, -1, "Okay")
    b2 = newt.Button(-1, -1, "Cancel")

    grid = newt.CreateGrid(1, 2)
    subgrid := newt.CreateGrid(2, 1)

    newt.GridSetField(subgrid, 0, 0, newt.GRID_COMPONENT, b1, 0, 0, 0, 0, 0, 0)
    newt.GridSetField(subgrid, 1, 0, newt.GRID_COMPONENT, b2, 0, 0, 0, 0, 0, 0)

    newt.GridSetField(grid, 0, 0, newt.GRID_COMPONENT, t, 0, 0, 0, 1, 0, 0)
    newt.GridSetField(grid, 0, 1, newt.GRID_SUBGRID, subgrid, 0, 0, 0, 0, 0, newt.GRID_FLAG_GROWX)
    newt.GridWrappedWindow(grid, "another example")
    newt.GridDestroy(grid, 1)

    f = newt.Form(nil, "", 0)
    newt.FormAddComponents(f, b1, t, b2)
    newt.RunForm(f)

    newt.PopWindow()
    newt.FormDestroy(f)

    newt.WinMessage("Simple", "Ok", "This is a simple message window")
    newt.WinChoice("Simple", "Ok", "Cancel", "This is a simple choice window")

    textWidth = 0
    menuContents := []string{"One", "Two", "Three", "Four", "Five"}
    rc, textWidth := newt.WinMenu("Test Menu", "This is a simple involvation of the " +
        "newtWinMenu() call. It may or may not have a scrollbar, " +
        "depending on the need for one.", 50, 5, 5, 3, menuContents, "Ok", "Cancel")

    autoEntries := make([]newt.WinEntry, 4)
    autoEntries[0] = newt.NewWinEntry("An entry", 0)
    autoEntries[1] = newt.NewWinEntry("Another entry", 0)
    autoEntries[2] = newt.NewWinEntry("Third entry", 0)
    autoEntries[3] = newt.NewWinEntry("Forth entry", 0)

    rc1 := newt.WinEntries("Test newtWinEntries()", "This is a simple invovation of " +
        "newtWinEntries() call. It lets you get a lot of input " +
        "quite easily.", 50, 5, 5, 20, &autoEntries, "Ok", "Cancel")

    newt.Finished()
    fmt.Println("WinMenu():",rc, textWidth)
    fmt.Println("WinEntries():",rc1)

    for i, v := range autoEntries {
        fmt.Printf("%d) Value: %s\n", i, v.Value())
        v.Destroy()
    }
}
<commit_msg>pointer error<commit_after>package main

import "github.com/aklyachkin/go-newt"

import "fmt"

func main() {
    newt.Init()
    newt.Cls()

    r := newt.NewResultStr()

    b1 := newt.Checkbox(-1, -1, "A pretty long checkbox for testing", " ", "", &r)
    b2 := newt.Button(-1, -1, "Another button")
    b3 := newt.Button(-1, -1, "But, but")
    b4 := newt.Button(-1, -1, "But what?")

    f := newt.Form(nil, "", 0)

    grid := newt.CreateGrid(2, 2)
    newt.GridSetField(grid, 0, 0, newt.GRID_COMPONENT, b1, 0, 0, 0, 0, newt.ANCHOR_RIGHT, 0)
    newt.GridSetField(grid, 0, 1, newt.GRID_COMPONENT, b2, 0, 0, 0, 0, 0, 0)
    newt.GridSetField(grid, 1, 0, newt.GRID_COMPONENT, b3, 0, 0, 0, 0, 0, 0)
    newt.GridSetField(grid, 1, 1, newt.GRID_COMPONENT, b4, 0, 0, 0, 0, 0, 0)

    newt.FormAddComponents(f, b1, b2, b3, b4)
    newt.GridWrappedWindow(grid, "first window")
    newt.GridFree(grid, 1)

    newt.RunForm(f)
    newt.FormDestroy(f)

    newt.PopWindow()

    flowedText, textWidth, textHeight := newt.ReflowText(
        "This is quite a bit of text. It is 40 " +
        "columns long, so some wrapping should be " +
        "done. Did you know that the quick, brown " +
        "fox jumped over the lazy dog?\n\n" +
        "In other news, it's pretty important that we " +
        "can properly force a line break.",
        40, 5, 5)
    t := newt.Textbox(-1, -1, textWidth, textHeight, newt.FLAG_WRAP)
    newt.TextboxSetText(t, flowedText)

    b1 = newt.Button(-1, -1, "Okay")
    b2 = newt.Button(-1, -1, "Cancel")

    grid = newt.CreateGrid(1, 2)
    subgrid := newt.CreateGrid(2, 1)

    newt.GridSetField(subgrid, 0, 0, newt.GRID_COMPONENT, b1, 0, 0, 0, 0, 0, 0)
    newt.GridSetField(subgrid, 1, 0, newt.GRID_COMPONENT, b2, 0, 0, 0, 0, 0, 0)

    newt.GridSetField(grid, 0, 0, newt.GRID_COMPONENT, t, 0, 0, 0, 1, 0, 0)
    newt.GridSetField(grid, 0, 1, newt.GRID_SUBGRID, subgrid, 0, 0, 0, 0, 0, newt.GRID_FLAG_GROWX)
    newt.GridWrappedWindow(grid, "another example")
    newt.GridDestroy(grid, 1)

    f = newt.Form(nil, "", 0)
    newt.FormAddComponents(f, b1, t, b2)
    newt.RunForm(f)

    newt.PopWindow()
    newt.FormDestroy(f)

    newt.WinMessage("Simple", "Ok", "This is a simple message window")
    newt.WinChoice("Simple", "Ok", "Cancel", "This is a simple choice window")

    textWidth = 0
    menuContents := []string{"One", "Two", "Three", "Four", "Five"}
    rc, textWidth := newt.WinMenu("Test Menu", "This is a simple involvation of the " +
        "newtWinMenu() call. It may or may not have a scrollbar, " +
        "depending on the need for one.", 50, 5, 5, 3, menuContents, "Ok", "Cancel")

    autoEntries := make([]newt.WinEntry, 4)
    autoEntries[0] = newt.NewWinEntry("An entry", 0)
    autoEntries[1] = newt.NewWinEntry("Another entry", 0)
    autoEntries[2] = newt.NewWinEntry("Third entry", 0)
    autoEntries[3] = newt.NewWinEntry("Forth entry", 0)

    rc1 := newt.WinEntries("Test newtWinEntries()", "This is a simple invovation of " +
        "newtWinEntries() call. It lets you get a lot of input " +
        "quite easily.", 50, 5, 5, 20, &autoEntries, "Ok", "Cancel")

    newt.Finished()
    fmt.Println("WinMenu():",rc, textWidth)
    fmt.Println("WinEntries():",rc1)

    for i, v := range autoEntries {
        fmt.Printf("%d) Value: %s\n", i, v.Value())
        v.Destroy()
    }
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/ebml-go/common"
	"code.google.com/p/ebml-go/webm"
	"code.google.com/p/ffvorbis-go/ffvorbis"
	"code.google.com/p/ffvp8-go/ffvp8"
	"code.google.com/p/portaudio-go/portaudio"
	"flag"
	gl "github.com/chsc/gogl/gl21"
	"github.com/jteeuwen/glfw"
	"math"
	"runtime"
	"time"
)

var (
	unsync     = flag.Bool("u", false, "Unsynchronized display")
	notc       = flag.Bool("t", false, "Ignore timecodes")
	blend      = flag.Bool("b", false, "Blend between images")
	fullscreen = flag.Bool("f", false, "Fullscreen mode")
	justaudio  = flag.Bool("a", false, "Just audio")
	justvideo  = flag.Bool("v", false, "Just video")
)

var ntex int

const vss = `
void main() {
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = ftransform();
}
`

const ycbcr2rgb = `
const mat3 ycbcr2rgb = mat3(
                          1.164, 0, 1.596,
                          1.164, -0.392, -0.813,
                          1.164, 2.017, 0.0
                          );
const float ysub = 0.0625;
vec3 ycbcr2rgb(vec3 c) {
   vec3 ycbcr = vec3(c.x - ysub, c.y - 0.5, c.z - 0.5);
   return ycbcr * ycbcr2rgb;
}
`

const fss = ycbcr2rgb + `
uniform sampler2D yt1;
uniform sampler2D cbt1;
uniform sampler2D crt1;

void main() {
   vec3 c = vec3(texture2D(yt1, gl_TexCoord[0].st).r,
                 texture2D(cbt1, gl_TexCoord[0].st).r,
                 texture2D(crt1, gl_TexCoord[0].st).r);
   gl_FragColor = vec4(ycbcr2rgb(c), 1.0);
}
`
const bfss = ycbcr2rgb + `
uniform sampler2D yt1;
uniform sampler2D cbt1;
uniform sampler2D crt1;
uniform sampler2D yt0;
uniform sampler2D cbt0;
uniform sampler2D crt0;
uniform float factor;

void main() {
   vec3 c0 = vec3(texture2D(yt0, gl_TexCoord[0].st).r,
                  texture2D(cbt0, gl_TexCoord[0].st).r,
                  texture2D(crt0, gl_TexCoord[0].st).r);
   vec3 c1 = vec3(texture2D(yt1, gl_TexCoord[0].st).r,
                  texture2D(cbt1, gl_TexCoord[0].st).r,
                  texture2D(crt1, gl_TexCoord[0].st).r);
   gl_FragColor = vec4(ycbcr2rgb(mix(c0, c1, factor)), 1);
}
`

func texinit(id int) {
	gl.BindTexture(gl.TEXTURE_2D, gl.Uint(id))
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
}

func shinit() gl.Int {
	vs := loadShader(gl.VERTEX_SHADER, vss)
	var sfs string
	if *blend {
		sfs = bfss
	} else {
		sfs = fss
	}
	fs := loadShader(gl.FRAGMENT_SHADER, sfs)
	prg := gl.CreateProgram()
	gl.AttachShader(prg, vs)
	gl.AttachShader(prg, fs)
	gl.LinkProgram(prg)
	var l int
	if *blend {
		l = 6
	} else {
		l = 3
	}
	gl.UseProgram(prg)
	names := []string{"yt1", "cbt1", "crt1", "yt0", "cbt0", "crt0"}
	for i := 0; i < l; i++ {
		loc := gl.GetUniformLocation(prg, gl.GLString(names[i]))
		gl.Uniform1i(loc, gl.Int(i))
	}
	return gl.GetUniformLocation(prg, gl.GLString("factor"))
}

func upload(id gl.Uint, data []byte, stride int, w int, h int) {
	gl.BindTexture(gl.TEXTURE_2D, id)
	gl.PixelStorei(gl.UNPACK_ROW_LENGTH, gl.Int(stride))
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.Sizei(w), gl.Sizei(h), 0,
		gl.LUMINANCE, gl.UNSIGNED_BYTE, gl.Pointer(&data[0]))
}

func initquad() {
	ver := []gl.Float{-1, 1, 1, 1, -1, -1, 1, -1}
	gl.BindBuffer(gl.ARRAY_BUFFER, 1)
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(ver)),
		gl.Pointer(&ver[0]), gl.STATIC_DRAW)
	gl.VertexPointer(2, gl.FLOAT, 0, nil)
	tex := []gl.Float{0, 0, 1, 0, 0, 1, 1, 1}
	gl.BindBuffer(gl.ARRAY_BUFFER, 2)
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(tex)),
		gl.Pointer(&tex[0]), gl.STATIC_DRAW)
	gl.TexCoordPointer(2, gl.FLOAT, 0, nil)
	gl.EnableClientState(gl.VERTEX_ARRAY)
	gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
}

func loadShader(shtype gl.Enum, src string) gl.Uint {
	sh := gl.CreateShader(shtype)
	gsrc := gl.GLString(src)
	gl.ShaderSource(sh, 1, &gsrc, nil)
	gl.CompileShader(sh)
	return sh
}

func factor(t time.Time, tc0 time.Time, tc1 time.Time) gl.Float {
	num := t.Sub(tc0)
	den := tc1.Sub(tc0)
	res := num.Seconds() / den.Seconds()
	res = math.Max(res, 0)
	res = math.Min(res, 1)
	return gl.Float(res)
}

func vpresent(wchan <-chan *ffvp8.Frame) {
	if *blend {
		ntex = 6
	} else {
		ntex = 3
	}
	img := <-wchan
	w := img.Rect.Dx()
	h := img.Rect.Dy()
	gl.Init()
	glfw.Init()
	defer glfw.Terminate()
	mode := glfw.Windowed
	ww := w
	wh := h
	if *fullscreen {
		mode = glfw.Fullscreen
		ww = 1440
		wh = 900
	}
	glfw.OpenWindow(ww, wh, 0, 0, 0, 0, 0, 0, mode)
	defer glfw.CloseWindow()
	glfw.SetWindowSizeCallback(func(ww, wh int) {
		oaspect := float64(w) / float64(h)
		haspect := float64(ww) / float64(wh)
		vaspect := float64(wh) / float64(ww)
		var scx, scy float64
		if oaspect > haspect {
			scx = 1
			scy = haspect / oaspect
		} else {
			scx = vaspect * oaspect
			scy = 1
		}
		gl.Viewport(0, 0, gl.Sizei(ww), gl.Sizei(wh))
		gl.LoadIdentity()
		gl.Scaled(gl.Double(scx), gl.Double(scy), 1)
	})
	if !*unsync {
		glfw.SetSwapInterval(1)
	}
	glfw.SetWindowTitle(*common.In)
	for i := 0; i < ntex; i++ {
		texinit(i + 1)
	}
	factorloc := shinit()
	initquad()
	gl.Enable(gl.TEXTURE_2D)
	tbase := time.Now()
	pimg := img
	for glfw.WindowParam(glfw.Opened) == 1 {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
		t := time.Now()
		if *notc || t.After(tbase.Add(img.Timecode)) {
			var ok bool
			//			if pimg != img {
			//				pimg.Release()
			//			}
			pimg = img
			img = nil
			for img == nil {
				img, ok = <-wchan
				if !ok {
					return
				}
			}
		}
		gl.ActiveTexture(gl.TEXTURE0)
		upload(1, img.Y, img.YStride, w, h)
		gl.ActiveTexture(gl.TEXTURE1)
		upload(2, img.Cb, img.CStride, w/2, h/2)
		gl.ActiveTexture(gl.TEXTURE2)
		upload(3, img.Cr, img.CStride, w/2, h/2)
		if *blend {
			gl.Uniform1f(factorloc, factor(t,
				tbase.Add(pimg.Timecode),
				tbase.Add(img.Timecode)))
			gl.ActiveTexture(gl.TEXTURE3)
			upload(4, pimg.Y, pimg.YStride, w, h)
			gl.ActiveTexture(gl.TEXTURE4)
			upload(5, pimg.Cb, pimg.CStride, w/2, h/2)
			gl.ActiveTexture(gl.TEXTURE5)
			upload(6, pimg.Cr, pimg.CStride, w/2, h/2)
		}
		gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
		runtime.GC()
		glfw.SwapBuffers()
	}
}

type AudioWriter struct {
	ch       <-chan *ffvorbis.Samples
	active   bool
	curr     *ffvorbis.Samples
	channels int
	sofar    int
}

func (aw *AudioWriter) ProcessAudio(in, out []float32) {
	for sent, lo := 0, len(out); sent < lo; {
		if aw.curr == nil || aw.sofar == len(aw.curr.Data) {
			aw.curr, aw.active = <-aw.ch
			if aw.curr == nil {
				return
			}
			aw.sofar = 0
		}
		s := copy(out[sent:], aw.curr.Data[aw.sofar:])
		sent += s
		aw.sofar += s
	}
}

func apresent(wchan <-chan *ffvorbis.Samples, audio *webm.Audio) {
	chk := func(err error) {
		if err != nil {
			panic(err)
		}
	}
	channels := int(audio.Channels)
	aw := AudioWriter{wchan, true, nil, channels, 0}
	stream, err := portaudio.OpenDefaultStream(0, channels,
		audio.SamplingFrequency, 0, &aw)
	defer stream.Close()
	chk(err)
	chk(stream.Start())
	defer stream.Stop()
	for aw.active {
		time.Sleep(time.Second)
	}
}

func main() {
	flag.Parse()
	vp := vpresent
	ap := apresent
	if *justaudio {
		vp = nil
	}
	if *justvideo {
		ap = nil
	}
	common.Main(vp, ap)
}
<commit_msg>Removed commented out code<commit_after>package main

import (
	"code.google.com/p/ebml-go/common"
	"code.google.com/p/ebml-go/webm"
	"code.google.com/p/ffvorbis-go/ffvorbis"
	"code.google.com/p/ffvp8-go/ffvp8"
	"code.google.com/p/portaudio-go/portaudio"
	"flag"
	gl "github.com/chsc/gogl/gl21"
	"github.com/jteeuwen/glfw"
	"math"
	"runtime"
	"time"
)

var (
	unsync     = flag.Bool("u", false, "Unsynchronized display")
	notc       = flag.Bool("t", false, "Ignore timecodes")
	blend      = flag.Bool("b", false, "Blend between images")
	fullscreen = flag.Bool("f", false, "Fullscreen mode")
	justaudio  = flag.Bool("a", false, "Just audio")
	justvideo  = flag.Bool("v", false, "Just video")
)

var ntex int

const vss = `
void main() {
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = ftransform();
}
`

const ycbcr2rgb = `
const mat3 ycbcr2rgb = mat3(
                          1.164, 0, 1.596,
                          1.164, -0.392, -0.813,
                          1.164, 2.017, 0.0
                          );
const float ysub = 0.0625;
vec3 ycbcr2rgb(vec3 c) {
   vec3 ycbcr = vec3(c.x - ysub, c.y - 0.5, c.z - 0.5);
   return ycbcr * ycbcr2rgb;
}
`

const fss = ycbcr2rgb + `
uniform sampler2D yt1;
uniform sampler2D cbt1;
uniform sampler2D crt1;

void main() {
   vec3 c = vec3(texture2D(yt1, gl_TexCoord[0].st).r,
                 texture2D(cbt1, gl_TexCoord[0].st).r,
                 texture2D(crt1, gl_TexCoord[0].st).r);
   gl_FragColor = vec4(ycbcr2rgb(c), 1.0);
}
`
const bfss = ycbcr2rgb + `
uniform sampler2D yt1;
uniform sampler2D cbt1;
uniform sampler2D crt1;
uniform sampler2D yt0;
uniform sampler2D cbt0;
uniform sampler2D crt0;
uniform float factor;

void main() {
   vec3 c0 = vec3(texture2D(yt0, gl_TexCoord[0].st).r,
                  texture2D(cbt0, gl_TexCoord[0].st).r,
                  texture2D(crt0, gl_TexCoord[0].st).r);
   vec3 c1 = vec3(texture2D(yt1, gl_TexCoord[0].st).r,
                  texture2D(cbt1, gl_TexCoord[0].st).r,
                  texture2D(crt1, gl_TexCoord[0].st).r);
   gl_FragColor = vec4(ycbcr2rgb(mix(c0, c1, factor)), 1);
}
`

func texinit(id int) {
	gl.BindTexture(gl.TEXTURE_2D, gl.Uint(id))
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
}

func shinit() gl.Int {
	vs := loadShader(gl.VERTEX_SHADER, vss)
	var sfs string
	if *blend {
		sfs = bfss
	} else {
		sfs = fss
	}
	fs := loadShader(gl.FRAGMENT_SHADER, sfs)
	prg := gl.CreateProgram()
	gl.AttachShader(prg, vs)
	gl.AttachShader(prg, fs)
	gl.LinkProgram(prg)
	var l int
	if *blend {
		l = 6
	} else {
		l = 3
	}
	gl.UseProgram(prg)
	names := []string{"yt1", "cbt1", "crt1", "yt0", "cbt0", "crt0"}
	for i := 0; i < l; i++ {
		loc := gl.GetUniformLocation(prg, gl.GLString(names[i]))
		gl.Uniform1i(loc, gl.Int(i))
	}
	return gl.GetUniformLocation(prg, gl.GLString("factor"))
}

func upload(id gl.Uint, data []byte, stride int, w int, h int) {
	gl.BindTexture(gl.TEXTURE_2D, id)
	gl.PixelStorei(gl.UNPACK_ROW_LENGTH, gl.Int(stride))
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.Sizei(w), gl.Sizei(h), 0,
		gl.LUMINANCE, gl.UNSIGNED_BYTE, gl.Pointer(&data[0]))
}

func initquad() {
	ver := []gl.Float{-1, 1, 1, 1, -1, -1, 1, -1}
	gl.BindBuffer(gl.ARRAY_BUFFER, 1)
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(ver)),
		gl.Pointer(&ver[0]), gl.STATIC_DRAW)
	gl.VertexPointer(2, gl.FLOAT, 0, nil)
	tex := []gl.Float{0, 0, 1, 0, 0, 1, 1, 1}
	gl.BindBuffer(gl.ARRAY_BUFFER, 2)
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(tex)),
		gl.Pointer(&tex[0]), gl.STATIC_DRAW)
	gl.TexCoordPointer(2, gl.FLOAT, 0, nil)
	gl.EnableClientState(gl.VERTEX_ARRAY)
	gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
}

func loadShader(shtype gl.Enum, src string) gl.Uint {
	sh := gl.CreateShader(shtype)
	gsrc := gl.GLString(src)
	gl.ShaderSource(sh, 1, &gsrc, nil)
	gl.CompileShader(sh)
	return sh
}

func factor(t time.Time, tc0 time.Time, tc1 time.Time) gl.Float {
	num := t.Sub(tc0)
	den := tc1.Sub(tc0)
	res := num.Seconds() / den.Seconds()
	res = math.Max(res, 0)
	res = math.Min(res, 1)
	return gl.Float(res)
}

func vpresent(wchan <-chan *ffvp8.Frame) {
	if *blend {
		ntex = 6
	} else {
		ntex = 3
	}
	img := <-wchan
	w := img.Rect.Dx()
	h := img.Rect.Dy()
	gl.Init()
	glfw.Init()
	defer glfw.Terminate()
	mode := glfw.Windowed
	ww := w
	wh := h
	if *fullscreen {
		mode = glfw.Fullscreen
		ww = 1440
		wh = 900
	}
	glfw.OpenWindow(ww, wh, 0, 0, 0, 0, 0, 0, mode)
	defer glfw.CloseWindow()
	glfw.SetWindowSizeCallback(func(ww, wh int) {
		oaspect := float64(w) / float64(h)
		haspect := float64(ww) / float64(wh)
		vaspect := float64(wh) / float64(ww)
		var scx, scy float64
		if oaspect > haspect {
			scx = 1
			scy = haspect / oaspect
		} else {
			scx = vaspect * oaspect
			scy = 1
		}
		gl.Viewport(0, 0, gl.Sizei(ww), gl.Sizei(wh))
		gl.LoadIdentity()
		gl.Scaled(gl.Double(scx), gl.Double(scy), 1)
	})
	if !*unsync {
		glfw.SetSwapInterval(1)
	}
	glfw.SetWindowTitle(*common.In)
	for i := 0; i < ntex; i++ {
		texinit(i + 1)
	}
	factorloc := shinit()
	initquad()
	gl.Enable(gl.TEXTURE_2D)
	tbase := time.Now()
	pimg := img
	for glfw.WindowParam(glfw.Opened) == 1 {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
		t := time.Now()
		if *notc || t.After(tbase.Add(img.Timecode)) {
			var ok bool
			pimg = img
			img = nil
			for img == nil {
				img, ok = <-wchan
				if !ok {
					return
				}
			}
		}
		gl.ActiveTexture(gl.TEXTURE0)
		upload(1, img.Y, img.YStride, w, h)
		gl.ActiveTexture(gl.TEXTURE1)
		upload(2, img.Cb, img.CStride, w/2, h/2)
		gl.ActiveTexture(gl.TEXTURE2)
		upload(3, img.Cr, img.CStride, w/2, h/2)
		if *blend {
			gl.Uniform1f(factorloc, factor(t,
				tbase.Add(pimg.Timecode),
				tbase.Add(img.Timecode)))
			gl.ActiveTexture(gl.TEXTURE3)
			upload(4, pimg.Y, pimg.YStride, w, h)
			gl.ActiveTexture(gl.TEXTURE4)
			upload(5, pimg.Cb, pimg.CStride, w/2, h/2)
			gl.ActiveTexture(gl.TEXTURE5)
			upload(6, pimg.Cr, pimg.CStride, w/2, h/2)
		}
		gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
		runtime.GC()
		glfw.SwapBuffers()
	}
}

type AudioWriter struct {
	ch       <-chan *ffvorbis.Samples
	active   bool
	curr     *ffvorbis.Samples
	channels int
	sofar    int
}

func (aw *AudioWriter) ProcessAudio(in, out []float32) {
	for sent, lo := 0, len(out); sent < lo; {
		if aw.curr == nil || aw.sofar == len(aw.curr.Data) {
			aw.curr, aw.active = <-aw.ch
			if aw.curr == nil {
				return
			}
			aw.sofar = 0
		}
		s := copy(out[sent:], aw.curr.Data[aw.sofar:])
		sent += s
		aw.sofar += s
	}
}

func apresent(wchan <-chan *ffvorbis.Samples, audio *webm.Audio) {
	chk := func(err error) {
		if err != nil {
			panic(err)
		}
	}
	channels := int(audio.Channels)
	aw := AudioWriter{wchan, true, nil, channels, 0}
	stream, err := portaudio.OpenDefaultStream(0, channels,
		audio.SamplingFrequency, 0, &aw)
	defer stream.Close()
	chk(err)
	chk(stream.Start())
	defer stream.Stop()
	for aw.active {
		time.Sleep(time.Second)
	}
}

func main() {
	flag.Parse()
	vp := vpresent
	ap := apresent
	if *justaudio {
		vp = nil
	}
	if *justvideo {
		ap = nil
	}
	common.Main(vp, ap)
}
<|endoftext|>


<commit_before>package web

import (
	"net/http"

	"github.com/anthonynsimon/parrot/render"
)

func newDocument(w http.ResponseWriter, r *http.Request) error {
	render.Template(w, "documents/new", nil)
	return nil
}

func createDocument(w http.ResponseWriter, r *http.Request) error {
	render.Template(w, "documents/show", nil)
	return nil
}

func showDocument(w http.ResponseWriter, r *http.Request) error {
	render.Template(w, "documents/show", nil)
	return nil
}

func findDocuments(w http.ResponseWriter, r *http.Request) error {
	render.Template(w, "documents/find", nil)
	return nil
}
<commit_msg>Add payload to new doc template<commit_after>package web

import (
	"net/http"

	"github.com/anthonynsimon/parrot/model"
	"github.com/anthonynsimon/parrot/render"
)

func newDocument(w http.ResponseWriter, r *http.Request) error {
	payload := map[string]interface{}{
		"locales": model.Locales,
	}
	render.Template(w, "documents/new", payload)
	return nil
}

func createDocument(w http.ResponseWriter, r *http.Request) error {
	render.Template(w, "documents/show", nil)
	return nil
}

func showDocument(w http.ResponseWriter, r *http.Request) error {
	render.Template(w, "documents/show", nil)
	return nil
}

func findDocuments(w http.ResponseWriter, r *http.Request) error {
	render.Template(w, "documents/find", nil)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/ebml-go/webm"
	"code.google.com/p/portaudio-go/portaudio"
	"flag"
	gl "github.com/chsc/gogl/gl21"
	"github.com/jteeuwen/glfw"
	"log"
	"math"
	"os"
	"runtime"
	"time"
)

var (
	in         = flag.String("i", "", "Input file")
	unsync     = flag.Bool("u", false, "Unsynchronized display")
	notc       = flag.Bool("t", false, "Ignore timecodes")
	blend      = flag.Bool("b", false, "Blend between images")
	fullscreen = flag.Bool("f", false, "Fullscreen mode")
	justaudio  = flag.Bool("a", false, "Just audio")
	justvideo  = flag.Bool("v", false, "Just video")
)

var ntex int

const vss = `
void main() {
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = ftransform();
}
`

const ycbcr2rgb = `
const mat3 ycbcr2rgb = mat3(
                          1.164, 0, 1.596,
                          1.164, -0.392, -0.813,
                          1.164, 2.017, 0.0
                          );
const float ysub = 0.0625;
vec3 ycbcr2rgb(vec3 c) {
   vec3 ycbcr = vec3(c.x - ysub, c.y - 0.5, c.z - 0.5);
   return ycbcr * ycbcr2rgb;
}
`

const fss = ycbcr2rgb + `
uniform sampler2D yt1;
uniform sampler2D cbt1;
uniform sampler2D crt1;

void main() {
   vec3 c = vec3(texture2D(yt1, gl_TexCoord[0].st).r,
                 texture2D(cbt1, gl_TexCoord[0].st).r,
                 texture2D(crt1, gl_TexCoord[0].st).r);
   gl_FragColor = vec4(ycbcr2rgb(c), 1.0);
}
`
const bfss = ycbcr2rgb + `
uniform sampler2D yt1;
uniform sampler2D cbt1;
uniform sampler2D crt1;
uniform sampler2D yt0;
uniform sampler2D cbt0;
uniform sampler2D crt0;
uniform float factor;

void main() {
   vec3 c0 = vec3(texture2D(yt0, gl_TexCoord[0].st).r,
                  texture2D(cbt0, gl_TexCoord[0].st).r,
                  texture2D(crt0, gl_TexCoord[0].st).r);
   vec3 c1 = vec3(texture2D(yt1, gl_TexCoord[0].st).r,
                  texture2D(cbt1, gl_TexCoord[0].st).r,
                  texture2D(crt1, gl_TexCoord[0].st).r);
   gl_FragColor = vec4(ycbcr2rgb(mix(c0, c1, factor)), 1);
}
`

func texinit(id int) {
	gl.BindTexture(gl.TEXTURE_2D, gl.Uint(id))
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
}

func shinit() gl.Int {
	vs := loadShader(gl.VERTEX_SHADER, vss)
	var sfs string
	if *blend {
		sfs = bfss
	} else {
		sfs = fss
	}
	fs := loadShader(gl.FRAGMENT_SHADER, sfs)
	prg := gl.CreateProgram()
	gl.AttachShader(prg, vs)
	gl.AttachShader(prg, fs)
	gl.LinkProgram(prg)
	var l int
	if *blend {
		l = 6
	} else {
		l = 3
	}
	gl.UseProgram(prg)
	names := []string{"yt1", "cbt1", "crt1", "yt0", "cbt0", "crt0"}
	for i := 0; i < l; i++ {
		loc := gl.GetUniformLocation(prg, gl.GLString(names[i]))
		gl.Uniform1i(loc, gl.Int(i))
	}
	return gl.GetUniformLocation(prg, gl.GLString("factor"))
}

func upload(id gl.Uint, data []byte, stride int, w int, h int) {
	gl.BindTexture(gl.TEXTURE_2D, id)
	gl.PixelStorei(gl.UNPACK_ROW_LENGTH, gl.Int(stride))
	gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.Sizei(w), gl.Sizei(h), 0,
		gl.LUMINANCE, gl.UNSIGNED_BYTE, gl.Pointer(&data[0]))
}

func initquad() {
	ver := []gl.Float{-1, 1, 1, 1, -1, -1, 1, -1}
	gl.BindBuffer(gl.ARRAY_BUFFER, 1)
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(ver)),
		gl.Pointer(&ver[0]), gl.STATIC_DRAW)
	gl.VertexPointer(2, gl.FLOAT, 0, nil)
	tex := []gl.Float{0, 0, 1, 0, 0, 1, 1, 1}
	gl.BindBuffer(gl.ARRAY_BUFFER, 2)
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(tex)),
		gl.Pointer(&tex[0]), gl.STATIC_DRAW)
	gl.TexCoordPointer(2, gl.FLOAT, 0, nil)
	gl.EnableClientState(gl.VERTEX_ARRAY)
	gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
}

func loadShader(shtype gl.Enum, src string) gl.Uint {
	sh := gl.CreateShader(shtype)
	gsrc := gl.GLString(src)
	gl.ShaderSource(sh, 1, &gsrc, nil)
	gl.CompileShader(sh)
	return sh
}

func factor(t time.Time, tc0 time.Time, tc1 time.Time) gl.Float {
	num := t.Sub(tc0)
	den := tc1.Sub(tc0)
	res := num.Seconds() / den.Seconds()
	res = math.Max(res, 0)
	res = math.Min(res, 1)
	return gl.Float(res)
}

var steps = uint(0xffffffff)
var seek = time.Duration(-1)
var duration = time.Duration(-1)

func xseek(x int) {
	w, _ := glfw.WindowSize()
	factor := float64(x) / float64(w)
	seek = time.Duration(float64(duration) * factor)
}

func mphandler(x, y int) {
	if glfw.KeyPress == glfw.MouseButton(glfw.MouseLeft) {
		xseek(x)
	}
}

func mbhandler(button, state int) {
	if state == glfw.KeyRelease {
		x, _ := glfw.MousePos()
		xseek(x)
	}
}

func khandler(key, state int) {
	if state == glfw.KeyRelease {
		switch key {
		case 'P':
			steps = 0
		case 'R':
			steps = 0xffffffff
		case 'S':
			steps = 1
		}
	}
}

func vpresent(wchan <-chan webm.Frame, reader *webm.Reader) {
	if *blend {
		ntex = 6
	} else {
		ntex = 3
	}
	img := <-wchan
	w := img.Rect.Dx()
	h := img.Rect.Dy()
	gl.Init()
	glfw.Init()
	defer glfw.Terminate()
	mode := glfw.Windowed
	ww := w
	wh := h
	if *fullscreen {
		mode = glfw.Fullscreen
		ww = 1440
		wh = 900
	}
	glfw.OpenWindow(ww, wh, 0, 0, 0, 0, 0, 0, mode)
	glfw.SetKeyCallback(khandler)
	glfw.SetMouseButtonCallback(mbhandler)
	glfw.SetMousePosCallback(mphandler)
	defer glfw.CloseWindow()
	glfw.SetWindowSizeCallback(func(ww, wh int) {
		oaspect := float64(w) / float64(h)
		haspect := float64(ww) / float64(wh)
		vaspect := float64(wh) / float64(ww)
		var scx, scy float64
		if oaspect > haspect {
			scx = 1
			scy = haspect / oaspect
		} else {
			scx = vaspect * oaspect
			scy = 1
		}
		gl.Viewport(0, 0, gl.Sizei(ww), gl.Sizei(wh))
		gl.LoadIdentity()
		gl.Scaled(gl.Double(scx), gl.Double(scy), 1)
	})
	if !*unsync {
		glfw.SetSwapInterval(1)
	}
	glfw.SetWindowTitle(*in)
	for i := 0; i < ntex; i++ {
		texinit(i + 1)
	}
	factorloc := shinit()
	initquad()
	gl.Enable(gl.TEXTURE_2D)
	tbase := time.Now()
	pimg := img
	for glfw.WindowParam(glfw.Opened) == 1 {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
		t := time.Now()
		if steps > 0 && (*notc || t.After(tbase.Add(img.Timecode))) {
			pimg = img
			var ok bool
			img, ok = <-wchan
			if !ok {
				return
			}
			if img.Timecode == pimg.Timecode {
				log.Println("same timecode", img.Timecode)
			}
			if img.Rebase {
				tbase = time.Now().Add(-img.Timecode)
			}
			steps--
		}
		gl.ActiveTexture(gl.TEXTURE0)
		upload(1, img.Y, img.YStride, w, h)
		gl.ActiveTexture(gl.TEXTURE1)
		upload(2, img.Cb, img.CStride, w/2, h/2)
		gl.ActiveTexture(gl.TEXTURE2)
		upload(3, img.Cr, img.CStride, w/2, h/2)
		if *blend {
			gl.Uniform1f(factorloc, factor(t,
				tbase.Add(pimg.Timecode),
				tbase.Add(img.Timecode)))
			gl.ActiveTexture(gl.TEXTURE3)
			upload(4, pimg.Y, pimg.YStride, w, h)
			gl.ActiveTexture(gl.TEXTURE4)
			upload(5, pimg.Cb, pimg.CStride, w/2, h/2)
			gl.ActiveTexture(gl.TEXTURE5)
			upload(6, pimg.Cr, pimg.CStride, w/2, h/2)
		}
		gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
		runtime.GC()
		if seek >= 0 {
			reader.Seek(seek)
			seek = time.Duration(-1)
		}
		glfw.SwapBuffers()
	}
}

type AudioWriter struct {
	ch       <-chan webm.Samples
	channels int
	active   bool
	sofar    int
	curr     webm.Samples
}

func (aw *AudioWriter) ProcessAudio(in, out []float32) {
	for sent, lo := 0, len(out); sent < lo; {
		if aw.sofar == len(aw.curr.Data) {
			aw.curr, aw.active = <-aw.ch
			aw.sofar = 0
			//log.Println("timecode", aw.curr.Timecode)
		}
		s := copy(out[sent:], aw.curr.Data[aw.sofar:])
		sent += s
		aw.sofar += s
	}
}

func apresent(wchan <-chan webm.Samples, audio *webm.Audio) {
	chk := func(err error) {
		if err != nil {
			panic(err)
		}
	}
	channels := int(audio.Channels)
	aw := AudioWriter{ch: wchan, channels: channels, active: true}
	stream, err := portaudio.OpenDefaultStream(0, channels,
		audio.SamplingFrequency, 0, &aw)
	defer stream.Close()
	chk(err)
	chk(stream.Start())
	defer stream.Stop()
	for aw.active {
		time.Sleep(time.Second)
	}
}

func main() {
	flag.Parse()

	var err error
	var wm webm.WebM
	r, err := os.Open(*in)
	defer r.Close()
	if err != nil {
		log.Panic("Unable to open file " + *in)
	}
	reader, err := webm.Parse(r, &wm)
	if err != nil {
		log.Panic("Unable to parse file:", err)
	}
	duration = time.Duration(wm.GetDuration()) * time.Second

	splitter := webm.NewSplitter(reader.Chan)

	var vtrack *webm.TrackEntry
	var vstream *webm.Stream
	if !*justaudio {
		vtrack = wm.FindFirstVideoTrack()
	}
	if vtrack != nil {
		vstream = webm.NewStream(vtrack)
	}
	var astream *webm.Stream
	var atrack *webm.TrackEntry
	if !*justvideo {
		atrack = wm.FindFirstAudioTrack()
	}
	if atrack != nil {
		astream = webm.NewStream(atrack)
	}
	splitter.Split(astream, vstream)
	switch {
	case astream != nil && vstream != nil:
		go apresent(astream.AudioChannel(), &atrack.Audio)
		fallthrough
	case vstream != nil:
		vpresent(vstream.VideoChannel(), reader)
	case astream != nil:
		apresent(astream.AudioChannel(), &atrack.Audio)
	}
}
<commit_msg>More responsive seeking<commit_after>package main

import (
	"code.google.com/p/ebml-go/webm"
	"code.google.com/p/portaudio-go/portaudio"
	"flag"
	gl "github.com/chsc/gogl/gl21"
	"github.com/jteeuwen/glfw"
	"log"
	"math"
	"os"
	"runtime"
	"time"
)

var (
	in         = flag.String("i", "", "Input file")
	unsync     = flag.Bool("u", false, "Unsynchronized display")
	notc       = flag.Bool("t", false, "Ignore timecodes")
	blend      = flag.Bool("b", false, "Blend between images")
	fullscreen = flag.Bool("f", false, "Fullscreen mode")
	justaudio  = flag.Bool("a", false, "Just audio")
	justvideo  = flag.Bool("v", false, "Just video")
)

var ntex int

const vss = `
void main() {
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = ftransform();
}
`

const ycbcr2rgb = `
const mat3 ycbcr2rgb = mat3(
                          1.164, 0, 1.596,
                          1.164, -0.392, -0.813,
                          1.164, 2.017, 0.0
                          );
const float ysub = 0.0625;
vec3 ycbcr2rgb(vec3 c) {
   vec3 ycbcr = vec3(c.x - ysub, c.y - 0.5, c.z - 0.5);
   return ycbcr * ycbcr2rgb;
}
`

const fss = ycbcr2rgb + `
uniform sampler2D yt1;
uniform sampler2D cbt1;
uniform sampler2D crt1;

void main() {
   vec3 c = vec3(texture2D(yt1, gl_TexCoord[0].st).r,
                 texture2D(cbt1, gl_TexCoord[0].st).r,
                 texture2D(crt1, gl_TexCoord[0].st).r);
   gl_FragColor = vec4(ycbcr2rgb(c), 1.0);
}
`
const bfss = ycbcr2rgb + `
uniform sampler2D yt1;
uniform sampler2D cbt1;
uniform sampler2D crt1;
uniform sampler2D yt0;
uniform sampler2D cbt0;
uniform sampler2D crt0;
uniform float factor;

void main() {
   vec3 c0 = vec3(texture2D(yt0, gl_TexCoord[0].st).r,
                  texture2D(cbt0, gl_TexCoord[0].st).r,
                  texture2D(crt0, gl_TexCoord[0].st).r);
   vec3 c1 = vec3(texture2D(yt1, gl_TexCoord[0].st).r,
                  texture2D(cbt1, gl_TexCoord[0].st).r,
                  texture2D(crt1, gl_TexCoord[0].st).r);
   gl_FragColor = vec4(ycbcr2rgb(mix(c0, c1, factor)), 1);
}
`

func texinit(id int) {
	gl.BindTexture(gl.TEXTURE_2D, gl.Uint(id))
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
}

func shinit() gl.Int {
	vs := loadShader(gl.VERTEX_SHADER, vss)
	var sfs string
	if *blend {
		sfs = bfss
	} else {
		sfs = fss
	}
	fs := loadShader(gl.FRAGMENT_SHADER, sfs)
	prg := gl.CreateProgram()
	gl.AttachShader(prg, vs)
	gl.AttachShader(prg, fs)
	gl.LinkProgram(prg)
	var l int
	if *blend {
		l = 6
	} else {
		l = 3
	}
	gl.UseProgram(prg)
	names := []string{"yt1", "cbt1", "crt1", "yt0", "cbt0", "crt0"}
	for i := 0; i < l; i++ {
		loc := gl.GetUniformLocation(prg, gl.GLString(names[i]))
		gl.Uniform1i(loc, gl.Int(i))
	}
	return gl.GetUniformLocation(prg, gl.GLString("factor"))
}

func upload(id gl.Uint, data []byte, stride int, w int, h int) {
	gl.BindTexture(gl.TEXTURE_2D, id)
	gl.PixelStorei(gl.UNPACK_ROW_LENGTH, gl.Int(stride))
	gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.Sizei(w), gl.Sizei(h), 0,
		gl.LUMINANCE, gl.UNSIGNED_BYTE, gl.Pointer(&data[0]))
}

func initquad() {
	ver := []gl.Float{-1, 1, 1, 1, -1, -1, 1, -1}
	gl.BindBuffer(gl.ARRAY_BUFFER, 1)
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(ver)),
		gl.Pointer(&ver[0]), gl.STATIC_DRAW)
	gl.VertexPointer(2, gl.FLOAT, 0, nil)
	tex := []gl.Float{0, 0, 1, 0, 0, 1, 1, 1}
	gl.BindBuffer(gl.ARRAY_BUFFER, 2)
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(tex)),
		gl.Pointer(&tex[0]), gl.STATIC_DRAW)
	gl.TexCoordPointer(2, gl.FLOAT, 0, nil)
	gl.EnableClientState(gl.VERTEX_ARRAY)
	gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
}

func loadShader(shtype gl.Enum, src string) gl.Uint {
	sh := gl.CreateShader(shtype)
	gsrc := gl.GLString(src)
	gl.ShaderSource(sh, 1, &gsrc, nil)
	gl.CompileShader(sh)
	return sh
}

func factor(t time.Time, tc0 time.Time, tc1 time.Time) gl.Float {
	num := t.Sub(tc0)
	den := tc1.Sub(tc0)
	res := num.Seconds() / den.Seconds()
	res = math.Max(res, 0)
	res = math.Min(res, 1)
	return gl.Float(res)
}

var steps = uint(0xffffffff)
var seek = time.Duration(-1)
var duration = time.Duration(-1)

func xseek(x int) {
	w, _ := glfw.WindowSize()
	factor := float64(x) / float64(w)
	seek = time.Duration(float64(duration) * factor)
}

func mphandler(x, y int) {
	if glfw.KeyPress == glfw.MouseButton(glfw.MouseLeft) {
		xseek(x)
	}
}

func mbhandler(button, state int) {
	if state == glfw.KeyPress {
		x, _ := glfw.MousePos()
		xseek(x)
	}
}

func khandler(key, state int) {
	if state == glfw.KeyRelease {
		switch key {
		case 'P':
			steps = 0
		case 'R':
			steps = 0xffffffff
		case 'S':
			steps = 1
		}
	}
}

func vpresent(wchan <-chan webm.Frame, reader *webm.Reader) {
	if *blend {
		ntex = 6
	} else {
		ntex = 3
	}
	img := <-wchan
	w := img.Rect.Dx()
	h := img.Rect.Dy()
	gl.Init()
	glfw.Init()
	defer glfw.Terminate()
	mode := glfw.Windowed
	ww := w
	wh := h
	if *fullscreen {
		mode = glfw.Fullscreen
		ww = 1440
		wh = 900
	}
	glfw.OpenWindow(ww, wh, 0, 0, 0, 0, 0, 0, mode)
	glfw.SetKeyCallback(khandler)
	glfw.SetMouseButtonCallback(mbhandler)
	glfw.SetMousePosCallback(mphandler)
	defer glfw.CloseWindow()
	glfw.SetWindowSizeCallback(func(ww, wh int) {
		oaspect := float64(w) / float64(h)
		haspect := float64(ww) / float64(wh)
		vaspect := float64(wh) / float64(ww)
		var scx, scy float64
		if oaspect > haspect {
			scx = 1
			scy = haspect / oaspect
		} else {
			scx = vaspect * oaspect
			scy = 1
		}
		gl.Viewport(0, 0, gl.Sizei(ww), gl.Sizei(wh))
		gl.LoadIdentity()
		gl.Scaled(gl.Double(scx), gl.Double(scy), 1)
	})
	if !*unsync {
		glfw.SetSwapInterval(1)
	}
	glfw.SetWindowTitle(*in)
	for i := 0; i < ntex; i++ {
		texinit(i + 1)
	}
	factorloc := shinit()
	initquad()
	gl.Enable(gl.TEXTURE_2D)
	tbase := time.Now()
	pimg := img
	for glfw.WindowParam(glfw.Opened) == 1 {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
		t := time.Now()
		if steps > 0 && (*notc || t.After(tbase.Add(img.Timecode))) {
			pimg = img
			var ok bool
			img, ok = <-wchan
			if !ok {
				return
			}
			if img.Timecode == pimg.Timecode {
				log.Println("same timecode", img.Timecode)
			}
			if img.Rebase {
				tbase = time.Now().Add(-img.Timecode)
			}
			steps--
		}
		gl.ActiveTexture(gl.TEXTURE0)
		upload(1, img.Y, img.YStride, w, h)
		gl.ActiveTexture(gl.TEXTURE1)
		upload(2, img.Cb, img.CStride, w/2, h/2)
		gl.ActiveTexture(gl.TEXTURE2)
		upload(3, img.Cr, img.CStride, w/2, h/2)
		if *blend {
			gl.Uniform1f(factorloc, factor(t,
				tbase.Add(pimg.Timecode),
				tbase.Add(img.Timecode)))
			gl.ActiveTexture(gl.TEXTURE3)
			upload(4, pimg.Y, pimg.YStride, w, h)
			gl.ActiveTexture(gl.TEXTURE4)
			upload(5, pimg.Cb, pimg.CStride, w/2, h/2)
			gl.ActiveTexture(gl.TEXTURE5)
			upload(6, pimg.Cr, pimg.CStride, w/2, h/2)
		}
		gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
		runtime.GC()
		if seek >= 0 {
			reader.Seek(seek)
			seek = time.Duration(-1)
		}
		glfw.SwapBuffers()
	}
}

type AudioWriter struct {
	ch       <-chan webm.Samples
	channels int
	active   bool
	sofar    int
	curr     webm.Samples
}

func (aw *AudioWriter) ProcessAudio(in, out []float32) {
	for sent, lo := 0, len(out); sent < lo; {
		if aw.sofar == len(aw.curr.Data) {
			aw.curr, aw.active = <-aw.ch
			aw.sofar = 0
			//log.Println("timecode", aw.curr.Timecode)
		}
		s := copy(out[sent:], aw.curr.Data[aw.sofar:])
		sent += s
		aw.sofar += s
	}
}

func apresent(wchan <-chan webm.Samples, audio *webm.Audio) {
	chk := func(err error) {
		if err != nil {
			panic(err)
		}
	}
	channels := int(audio.Channels)
	aw := AudioWriter{ch: wchan, channels: channels, active: true}
	stream, err := portaudio.OpenDefaultStream(0, channels,
		audio.SamplingFrequency, 0, &aw)
	defer stream.Close()
	chk(err)
	chk(stream.Start())
	defer stream.Stop()
	for aw.active {
		time.Sleep(time.Second)
	}
}

func main() {
	flag.Parse()

	var err error
	var wm webm.WebM
	r, err := os.Open(*in)
	defer r.Close()
	if err != nil {
		log.Panic("Unable to open file " + *in)
	}
	reader, err := webm.Parse(r, &wm)
	if err != nil {
		log.Panic("Unable to parse file:", err)
	}
	duration = time.Duration(wm.GetDuration()) * time.Second

	splitter := webm.NewSplitter(reader.Chan)

	var vtrack *webm.TrackEntry
	var vstream *webm.Stream
	if !*justaudio {
		vtrack = wm.FindFirstVideoTrack()
	}
	if vtrack != nil {
		vstream = webm.NewStream(vtrack)
	}
	var astream *webm.Stream
	var atrack *webm.TrackEntry
	if !*justvideo {
		atrack = wm.FindFirstAudioTrack()
	}
	if atrack != nil {
		astream = webm.NewStream(atrack)
	}
	splitter.Split(astream, vstream)
	switch {
	case astream != nil && vstream != nil:
		go apresent(astream.AudioChannel(), &atrack.Audio)
		fallthrough
	case vstream != nil:
		vpresent(vstream.VideoChannel(), reader)
	case astream != nil:
		apresent(astream.AudioChannel(), &atrack.Audio)
	}
}
<|endoftext|>


<commit_before>package jobserver

import (
	"fmt"
	"time"

	"github.com/pachyderm/pachyderm/src/pkg/uuid"
	"github.com/pachyderm/pachyderm/src/pps"
	"github.com/pachyderm/pachyderm/src/pps/jobserver/run"
	"github.com/pachyderm/pachyderm/src/pps/persist"
	"go.pedge.io/google-protobuf"
	"go.pedge.io/proto/rpclog"
	"go.pedge.io/proto/time"
	"golang.org/x/net/context"
	kube "k8s.io/kubernetes/pkg/client/unversioned"
)

type apiServer struct {
	protorpclog.Logger
	persistAPIClient persist.APIClient
	client           *kube.Client
}

func newAPIServer(
	persistAPIClient persist.APIClient,
	client *kube.Client,
) *apiServer {
	return &apiServer{
		protorpclog.NewLogger("pachyderm.pps.JobAPI"),
		persistAPIClient,
		client,
	}
}

func (a *apiServer) CreateJob(ctx context.Context, request *pps.CreateJobRequest) (response *pps.Job, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistJobInfo := &persist.JobInfo{
		Input:        request.Input,
		OutputParent: request.OutputParent,
	}
	if request.GetTransform() != nil {
		persistJobInfo.Spec = &persist.JobInfo_Transform{
			Transform: request.GetTransform(),
		}
	} else if request.GetPipeline() != nil {
		persistJobInfo.Spec = &persist.JobInfo_PipelineName{
			PipelineName: request.GetPipeline().Name,
		}
	} else {
		return nil, fmt.Errorf("pachyderm.pps.jobserver: both transform and pipeline are not set on %v", request)
	}
	persistJobInfo.JobId = uuid.NewWithoutDashes()
	persistJobInfo.CreatedAt = prototime.TimeToTimestamp(time.Now())
	if err := jobserverrun.StartJob(a.client, persistJobInfo); err != nil {
		return nil, err
	}
	_, err = a.persistAPIClient.CreateJobInfo(ctx, persistJobInfo)
	if err != nil {
		return nil, err
	}
	return &pps.Job{
		Id: persistJobInfo.JobId,
	}, nil
}

func (a *apiServer) InspectJob(ctx context.Context, request *pps.InspectJobRequest) (response *pps.JobInfo, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistJobInfo, err := a.persistAPIClient.GetJobInfo(ctx, request.Job)
	if err != nil {
		return nil, err
	}
	return a.persistJobInfoToJobInfo(ctx, persistJobInfo)
}

func (a *apiServer) ListJob(ctx context.Context, request *pps.ListJobRequest) (response *pps.JobInfos, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	var persistJobInfos *persist.JobInfos
	persistJobInfos, err = a.persistAPIClient.ListJobInfos(ctx, request)
	if err != nil {
		return nil, err
	}
	jobInfos := make([]*pps.JobInfo, len(persistJobInfos.JobInfo))
	for i, persistJobInfo := range persistJobInfos.JobInfo {
		jobInfo, err := a.persistJobInfoToJobInfo(ctx, persistJobInfo)
		if err != nil {
			return nil, err
		}
		jobInfos[i] = jobInfo
	}
	return &pps.JobInfos{
		JobInfo: jobInfos,
	}, nil
}

func (a *apiServer) GetJobLogs(request *pps.GetJobLogsRequest, responseServer pps.JobAPI_GetJobLogsServer) (err error) {
	// TODO: filter by output stream
	persistJobLogs, err := a.persistAPIClient.GetJobLogs(context.Background(), request.Job)
	if err != nil {
		return err
	}
	for _, persistJobLog := range persistJobLogs.JobLog {
		if request.OutputStream == pps.OutputStream_OUTPUT_STREAM_ALL || persistJobLog.OutputStream == request.OutputStream {
			if err := responseServer.Send(&google_protobuf.BytesValue{Value: persistJobLog.Value}); err != nil {
				return err
			}
		}
	}
	return nil
}

// TODO: bulk get
func (a *apiServer) persistJobInfoToJobInfo(ctx context.Context, persistJobInfo *persist.JobInfo) (*pps.JobInfo, error) {
	job := &pps.Job{Id: persistJobInfo.JobId}
	persistJobStatuses, err := a.persistAPIClient.GetJobStatuses(ctx, job)
	if err != nil {
		return nil, err
	}
	persistJobOutput, err := a.persistAPIClient.GetJobOutput(ctx, job)
	if err != nil {
		return nil, err
	}
	jobInfo := &pps.JobInfo{
		Job:   job,
		Input: persistJobInfo.Input,
	}
	if persistJobInfo.GetTransform() != nil {
		jobInfo.Spec = &pps.JobInfo_Transform{
			Transform: persistJobInfo.GetTransform(),
		}
	}
	if persistJobInfo.GetPipelineName() != "" {
		jobInfo.Spec = &pps.JobInfo_Pipeline{
			Pipeline: &pps.Pipeline{
				Name: persistJobInfo.GetPipelineName(),
			},
		}
	}
	jobInfo.JobStatus = make([]*pps.JobStatus, len(persistJobStatuses.JobStatus))
	for i, persistJobStatus := range persistJobStatuses.JobStatus {
		jobInfo.JobStatus[i] = &pps.JobStatus{
			Type:      persistJobStatus.Type,
			Timestamp: persistJobStatus.Timestamp,
			Message:   persistJobStatus.Message,
		}
	}
	if persistJobOutput != nil {
		jobInfo.Output = persistJobOutput.Output
	}
	return jobInfo, nil
}
<commit_msg>Move run code into api_server.<commit_after>package jobserver

import (
	"fmt"
	"time"

	"go.pedge.io/google-protobuf"
	"go.pedge.io/proto/rpclog"
	"go.pedge.io/proto/time"
	"golang.org/x/net/context"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/apis/extensions"
	kube "k8s.io/kubernetes/pkg/client/unversioned"

	"github.com/pachyderm/pachyderm/src/pkg/uuid"
	"github.com/pachyderm/pachyderm/src/pps"
	"github.com/pachyderm/pachyderm/src/pps/persist"
)

type apiServer struct {
	protorpclog.Logger
	persistAPIClient persist.APIClient
	kubeClient       *kube.Client
}

func newAPIServer(
	persistAPIClient persist.APIClient,
	kubeClient *kube.Client,
) *apiServer {
	return &apiServer{
		protorpclog.NewLogger("pachyderm.pps.JobAPI"),
		persistAPIClient,
		kubeClient,
	}
}

func (a *apiServer) CreateJob(ctx context.Context, request *pps.CreateJobRequest) (response *pps.Job, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistJobInfo := &persist.JobInfo{
		Input:        request.Input,
		OutputParent: request.OutputParent,
	}
	if request.GetTransform() != nil {
		persistJobInfo.Spec = &persist.JobInfo_Transform{
			Transform: request.GetTransform(),
		}
	} else if request.GetPipeline() != nil {
		persistJobInfo.Spec = &persist.JobInfo_PipelineName{
			PipelineName: request.GetPipeline().Name,
		}
	} else {
		return nil, fmt.Errorf("pachyderm.pps.jobserver: both transform and pipeline are not set on %v", request)
	}
	persistJobInfo.JobId = uuid.NewWithoutDashes()
	persistJobInfo.CreatedAt = prototime.TimeToTimestamp(time.Now())
	if _, err := a.kubeClient.Jobs(api.NamespaceDefault).Create(job(persistJobInfo)); err != nil {
		return nil, err
	}
	_, err = a.persistAPIClient.CreateJobInfo(ctx, persistJobInfo)
	if err != nil {
		return nil, err
	}
	return &pps.Job{
		Id: persistJobInfo.JobId,
	}, nil
}

func (a *apiServer) InspectJob(ctx context.Context, request *pps.InspectJobRequest) (response *pps.JobInfo, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistJobInfo, err := a.persistAPIClient.GetJobInfo(ctx, request.Job)
	if err != nil {
		return nil, err
	}
	return a.persistJobInfoToJobInfo(ctx, persistJobInfo)
}

func (a *apiServer) ListJob(ctx context.Context, request *pps.ListJobRequest) (response *pps.JobInfos, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	var persistJobInfos *persist.JobInfos
	persistJobInfos, err = a.persistAPIClient.ListJobInfos(ctx, request)
	if err != nil {
		return nil, err
	}
	jobInfos := make([]*pps.JobInfo, len(persistJobInfos.JobInfo))
	for i, persistJobInfo := range persistJobInfos.JobInfo {
		jobInfo, err := a.persistJobInfoToJobInfo(ctx, persistJobInfo)
		if err != nil {
			return nil, err
		}
		jobInfos[i] = jobInfo
	}
	return &pps.JobInfos{
		JobInfo: jobInfos,
	}, nil
}

func (a *apiServer) GetJobLogs(request *pps.GetJobLogsRequest, responseServer pps.JobAPI_GetJobLogsServer) (err error) {
	// TODO: filter by output stream
	persistJobLogs, err := a.persistAPIClient.GetJobLogs(context.Background(), request.Job)
	if err != nil {
		return err
	}
	for _, persistJobLog := range persistJobLogs.JobLog {
		if request.OutputStream == pps.OutputStream_OUTPUT_STREAM_ALL || persistJobLog.OutputStream == request.OutputStream {
			if err := responseServer.Send(&google_protobuf.BytesValue{Value: persistJobLog.Value}); err != nil {
				return err
			}
		}
	}
	return nil
}

// TODO: bulk get
func (a *apiServer) persistJobInfoToJobInfo(ctx context.Context, persistJobInfo *persist.JobInfo) (*pps.JobInfo, error) {
	job := &pps.Job{Id: persistJobInfo.JobId}
	persistJobStatuses, err := a.persistAPIClient.GetJobStatuses(ctx, job)
	if err != nil {
		return nil, err
	}
	persistJobOutput, err := a.persistAPIClient.GetJobOutput(ctx, job)
	if err != nil {
		return nil, err
	}
	jobInfo := &pps.JobInfo{
		Job:   job,
		Input: persistJobInfo.Input,
	}
	if persistJobInfo.GetTransform() != nil {
		jobInfo.Spec = &pps.JobInfo_Transform{
			Transform: persistJobInfo.GetTransform(),
		}
	}
	if persistJobInfo.GetPipelineName() != "" {
		jobInfo.Spec = &pps.JobInfo_Pipeline{
			Pipeline: &pps.Pipeline{
				Name: persistJobInfo.GetPipelineName(),
			},
		}
	}
	jobInfo.JobStatus = make([]*pps.JobStatus, len(persistJobStatuses.JobStatus))
	for i, persistJobStatus := range persistJobStatuses.JobStatus {
		jobInfo.JobStatus[i] = &pps.JobStatus{
			Type:      persistJobStatus.Type,
			Timestamp: persistJobStatus.Timestamp,
			Message:   persistJobStatus.Message,
		}
	}
	if persistJobOutput != nil {
		jobInfo.Output = persistJobOutput.Output
	}
	return jobInfo, nil
}

func job(jobInfo *persist.JobInfo) *extensions.Job {
	app := jobInfo.JobId
	return &extensions.Job{
		TypeMeta: unversioned.TypeMeta{
			Kind:       "Job",
			APIVersion: "v1",
		},
		ObjectMeta: api.ObjectMeta{
			Name: jobInfo.JobId,
			Labels: map[string]string{
				"app": app,
			},
		},
		Spec: extensions.JobSpec{
			Selector: &extensions.PodSelector{
				MatchLabels: map[string]string{
					"app": app,
				},
			},
			Template: api.PodTemplateSpec{
				ObjectMeta: api.ObjectMeta{
					Name: jobInfo.JobId,
					Labels: map[string]string{
						"app": app,
					},
				},
				Spec: api.PodSpec{
					Containers: []api.Container{
						{
							Name:    "user",
							Image:   jobInfo.GetTransform().Image,
							Command: jobInfo.GetTransform().Cmd,
						},
					},
				},
			},
		},
	}
}
<|endoftext|>


<commit_before>package record

import (
	"context"
	"time"

	"github.com/CyCoreSystems/ari"
	"github.com/CyCoreSystems/ari/ext/record"
	"github.com/pkg/errors"
	uuid "github.com/satori/go.uuid"
)

// RecordingStartTimeout is the amount of time to wait for a recording to start
// before declaring the recording to have failed.
var RecordingStartTimeout = 1 * time.Second

// Options describes a set of recording options for a recording Session
type Options struct {
	// name is the name for the live recording
	name string
}

// Apply applies a set of options for the recording Session
func (o *Options) Apply(opts ...OptionFunc) (err error) {
	for _, f := range opts {
		err = f(o)
		if err != nil {
			return errors.Wrap(err, "failed to apply option")
		}
	}
	return nil
}

// OptionFunc is a function which applies changes to an Options set
type OptionFunc func(*Options)

// Session desribes the interface to a generic recording session
type Session interface {
	// Done returns a channel which is closed when the session is complete
	Done() <-chan struct{}

	// Err waits for the session to complete, then returns any error encountered during its execution
	Err() error

	// Result waits for the session to complete, then returns the Result
	Result() (*Result, error)

	// Scrap terminates the recording session and throws away the recording.
	Scrap()

	// Stop stops the recording session
	Stop() *Result
}

// Result represents the result of a recording Session.  It provides an interface to disposition the recording.
type Result struct {
	h *ari.LiveRecordingHandle

	// DTMF holds any DTMF digits which are received during the recording session
	DTMF string

	// Duration indicates the duration of the recording
	Duration time.Duration

	// Error holds any error encountered during the recording session
	Error error

	// Status indicates the status of the recording
	Status Status
}

// Delete discards the recording
func (r *Result) Delete() {
	panic("not implemented")
}

// Save stores the recording to a Stored Recording, returning a handle to that stored recording.
func (r *Result) Save(name string) (*ari.StoredRecordingHandle, error) {
	panic("not implemented")
}

// Record starts a new recording Session
func Record(ctx context.Context, r Recorder, opts ...OptionFunc) Session {
	s, err := New(opts...)
	if err != nil {
		return errorSession(err)
	}

	ctx, cancel := context.WithCancel(ctx)
	s.cancel = cancel

	return s.Record(ctx, p)
}

// New creates a new recording Session
func New(opts ...OptionFunc) Session {
	o := &Options{
		name: uuid.NewV1().String(),
	}

	o.Apply(opts...)

	return &recordingSession{
		cancel:  cancel,
		options: o,
		doneCh:  make(chan struct{}),
		status:  InProgress,
	}
}

type nilSession struct {
	status Status
}

func (n *nilSession) Done() <-chan struct{} {
	ch := make(chan struct{})
	close(ch)

	return ch
}

func (n *nilSession) Err() error {
	panic("not implemented")
}

func (n *nilSession) Result() (*record.Result, error) {
	panic("not implemented")
}

func (n *nilSession) Scrap() {
	panic("not implemented")
}

func (n *nilSession) Stop() *record.Result {
	panic("not implemented")
}

type recordingSession struct {
	cancel context.CancelFunc

	doneCh chan struct{}

	options *Options

	status Status

	// TODO
}

func (r *recordingSession) Done() <-chan struct{} {
	panic("not implemented")
}

func (r *recordingSession) Err() error {
	panic("not implemented")
}

func (r *recordingSession) Result() (*record.Result, error) {
	panic("not implemented")
}

func (r *recordingSession) Scrap() {
	panic("not implemented")
}

func (r *recordingSession) Stop() *record.Result {
	panic("not implemented")
}

/*
	Logger.Debug("Starting record", "name", name, "opts", opts)

	// Create recording handle
	h, err := r.StageRecord(name, opts)
	if err != nil {
		rec.err = err
		rec.status = Failed
		close(rec.doneCh)
		return
	}
	rec.handle = h

	go func() {
		defer close(rec.doneCh)

		Logger.Debug("Grabbing subscriptions", "name", name, "opts", opts)

		hangupSub := r.Subscribe(ari.Events.ChannelDestroyed, ari.Events.ChannelHangupRequest)
		defer hangupSub.Cancel()

		// Listen for start, stop, and failed events
		startSub := h.Subscribe(ari.Events.RecordingStarted)
		defer startSub.Cancel()

		failedSub := h.Subscribe(ari.Events.RecordingFailed)
		defer failedSub.Cancel()

		finishedSub := h.Subscribe(ari.Events.RecordingFinished)
		defer finishedSub.Cancel()

		Logger.Debug("Starting recording", "name", name, "opts", opts)
		err := h.Exec()
		if err != nil {
			rec.status = Failed
			rec.err = errors.Wrap(err, "failed to start recording")
			return
		}

		// Wait for the recording to start
		Logger.Debug("Starting record event loop", "name", name, "opts", opts)
		startTimer := time.NewTimer(RecordingStartTimeout)
		for {
			select {
			case <-ctx.Done():
				rec.status = Canceled
				return
			case <-startTimer.C:
				rec.status = Failed
				rec.err = timeoutErr{"Timeout waiting for recording to start"}
				return
			case e := <-startSub.Events():
				r := e.(*ari.RecordingStarted).Recording
				if r.Name == name {
					Logger.Debug("Recording started.")
					startTimer.Stop()
				}
			case e := <-failedSub.Events():
				r := e.(*ari.RecordingFailed).Recording
				if r.Name == name {
					rec.status = Failed
					rec.err = fmt.Errorf("Recording failed: %s", r.Cause)
					return
				}
			case e := <-finishedSub.Events():
				r := e.(*ari.RecordingFinished).Recording
				if r.Name == name {
					Logger.Debug("Recording stopped")
					rec.status = Finished
					rec.data = &r
					return
				}
			}
		}
	}()

	return
}

type timeoutErr struct {
	msg string
}

func (err timeoutErr) Error() string {
	return err.msg
}

func (err timeoutErr) Timeout() bool {
	return true
}

*/
<commit_msg>ext/record: compile fixes<commit_after>package record

import (
	"context"
	"time"

	"github.com/CyCoreSystems/ari"
	uuid "github.com/satori/go.uuid"
)

// RecordingStartTimeout is the amount of time to wait for a recording to start
// before declaring the recording to have failed.
var RecordingStartTimeout = 1 * time.Second

// Options describes a set of recording options for a recording Session
type Options struct {
	// name is the name for the live recording
	name string
}

// Apply applies a set of options for the recording Session
func (o *Options) Apply(opts ...OptionFunc) {
	for _, f := range opts {
		f(o)
	}
}

// OptionFunc is a function which applies changes to an Options set
type OptionFunc func(*Options)

// Session desribes the interface to a generic recording session
type Session interface {
	// Done returns a channel which is closed when the session is complete
	Done() <-chan struct{}

	// Err waits for the session to complete, then returns any error encountered during its execution
	Err() error

	// Result waits for the session to complete, then returns the Result
	Result() (*Result, error)

	// Scrap terminates the recording session and throws away the recording.
	Scrap()

	// Stop stops the recording session
	Stop() *Result
}

// Result represents the result of a recording Session.  It provides an interface to disposition the recording.
type Result struct {
	h *ari.LiveRecordingHandle

	// DTMF holds any DTMF digits which are received during the recording session
	DTMF string

	// Duration indicates the duration of the recording
	Duration time.Duration

	// Error holds any error encountered during the recording session
	Error error

	// Status indicates the status of the recording
	Status Status
}

// Delete discards the recording
func (r *Result) Delete() {
	panic("not implemented")
}

// Save stores the recording to a Stored Recording, returning a handle to that stored recording.
func (r *Result) Save(name string) (*ari.StoredRecordingHandle, error) {
	panic("not implemented")
}

// Record starts a new recording Session
func Record(ctx context.Context, r ari.Recorder, opts ...OptionFunc) Session {
	s := newRecordingSession(opts...)

	ctx, cancel := context.WithCancel(ctx)
	s.cancel = cancel

	go s.record(ctx, r)

	return s
}

// New creates a new recording Session
func newRecordingSession(opts ...OptionFunc) *recordingSession {
	o := &Options{
		name: uuid.NewV1().String(),
	}

	o.Apply(opts...)

	return &recordingSession{
		options: o,
		doneCh:  make(chan struct{}),
		status:  InProgress,
	}
}

type nilSession struct {
	status Status
}

func (s *nilSession) Done() <-chan struct{} {
	ch := make(chan struct{})
	close(ch)

	return ch
}

func (s *nilSession) Err() error {
	panic("not implemented")
}

func (s *nilSession) Result() (*Result, error) {
	panic("not implemented")
}

func (s *nilSession) Scrap() {
	panic("not implemented")
}

func (s *nilSession) Stop() *Result {
	panic("not implemented")
}

type recordingSession struct {
	cancel context.CancelFunc

	doneCh chan struct{}

	options *Options

	status Status

	// TODO
}

func (s *recordingSession) Done() <-chan struct{} {
	panic("not implemented")
}

func (s *recordingSession) Err() error {
	panic("not implemented")
}

func (s *recordingSession) Result() (*Result, error) {
	panic("not implemented")
}

func (s *recordingSession) Scrap() {
	panic("not implemented")
}

func (s *recordingSession) Stop() *Result {
	panic("not implemented")
}

func (s *recordingSession) record(ctx context.Context, r ari.Recorder) {
	panic("not implemented")
}

/*
	Logger.Debug("Starting record", "name", name, "opts", opts)

	// Create recording handle
	h, err := r.StageRecord(name, opts)
	if err != nil {
		rec.err = err
		rec.status = Failed
		close(rec.doneCh)
		return
	}
	rec.handle = h

	go func() {
		defer close(rec.doneCh)

		Logger.Debug("Grabbing subscriptions", "name", name, "opts", opts)

		hangupSub := r.Subscribe(ari.Events.ChannelDestroyed, ari.Events.ChannelHangupRequest)
		defer hangupSub.Cancel()

		// Listen for start, stop, and failed events
		startSub := h.Subscribe(ari.Events.RecordingStarted)
		defer startSub.Cancel()

		failedSub := h.Subscribe(ari.Events.RecordingFailed)
		defer failedSub.Cancel()

		finishedSub := h.Subscribe(ari.Events.RecordingFinished)
		defer finishedSub.Cancel()

		Logger.Debug("Starting recording", "name", name, "opts", opts)
		err := h.Exec()
		if err != nil {
			rec.status = Failed
			rec.err = errors.Wrap(err, "failed to start recording")
			return
		}

		// Wait for the recording to start
		Logger.Debug("Starting record event loop", "name", name, "opts", opts)
		startTimer := time.NewTimer(RecordingStartTimeout)
		for {
			select {
			case <-ctx.Done():
				rec.status = Canceled
				return
			case <-startTimer.C:
				rec.status = Failed
				rec.err = timeoutErr{"Timeout waiting for recording to start"}
				return
			case e := <-startSub.Events():
				r := e.(*ari.RecordingStarted).Recording
				if r.Name == name {
					Logger.Debug("Recording started.")
					startTimer.Stop()
				}
			case e := <-failedSub.Events():
				r := e.(*ari.RecordingFailed).Recording
				if r.Name == name {
					rec.status = Failed
					rec.err = fmt.Errorf("Recording failed: %s", r.Cause)
					return
				}
			case e := <-finishedSub.Events():
				r := e.(*ari.RecordingFinished).Recording
				if r.Name == name {
					Logger.Debug("Recording stopped")
					rec.status = Finished
					rec.data = &r
					return
				}
			}
		}
	}()

	return
}

type timeoutErr struct {
	msg string
}

func (err timeoutErr) Error() string {
	return err.msg
}

func (err timeoutErr) Timeout() bool {
	return true
}

*/
<|endoftext|>


<commit_before>package testing

import (
	"code.google.com/p/go.tools/godoc/vfs"
	"github.com/sourcegraph/go-vcs/vcs"
)

type MockRepository struct {
	ResolveRevision_ func(spec string) (vcs.CommitID, error)
	ResolveTag_      func(name string) (vcs.CommitID, error)
	ResolveBranch_   func(name string) (vcs.CommitID, error)

	Branches_ func() ([]*vcs.Branch, error)
	Tags_     func() ([]*vcs.Tag, error)

	GetCommit_ func(vcs.CommitID) (*vcs.Commit, error)
	Commits_   func(vcs.CommitsOptions) ([]*vcs.Commit, uint, error)

	FileSystem_ func(at vcs.CommitID) (vfs.FileSystem, error)
}

var _ vcs.Repository = MockRepository{}

func (r MockRepository) ResolveRevision(spec string) (vcs.CommitID, error) {
	if r.ResolveRevision_ == nil {
		return "", nil
	}
	return r.ResolveRevision_(spec)
}

func (r MockRepository) ResolveTag(name string) (vcs.CommitID, error) {
	if r.ResolveTag_ == nil {
		return "", nil
	}
	return r.ResolveTag_(name)
}

func (r MockRepository) ResolveBranch(name string) (vcs.CommitID, error) {
	if r.ResolveBranch_ == nil {
		return "", nil
	}
	return r.ResolveBranch_(name)
}

func (r MockRepository) Branches() ([]*vcs.Branch, error) {
	if r.Branches_ == nil {
		return nil, nil
	}
	return r.Branches_()
}

func (r MockRepository) Tags() ([]*vcs.Tag, error) {
	if r.Tags_ == nil {
		return nil, nil
	}
	return r.Tags_()
}

func (r MockRepository) GetCommit(id vcs.CommitID) (*vcs.Commit, error) {
	if r.GetCommit_ == nil {
		return nil, nil
	}
	return r.GetCommit_(id)
}

func (r MockRepository) Commits(opt vcs.CommitsOptions) ([]*vcs.Commit, uint, error) {
	if r.Commits_ == nil {
		return nil, 0, nil
	}
	return r.Commits_(opt)
}

func (r MockRepository) FileSystem(at vcs.CommitID) (vfs.FileSystem, error) {
	if r.FileSystem_ == nil {
		return nil, nil
	}
	return r.FileSystem_(at)
}
<commit_msg>don't provide default return impls in MockRepository (makes it easy to accidentally rely on them in a test)<commit_after>package testing

import (
	"code.google.com/p/go.tools/godoc/vfs"
	"github.com/sourcegraph/go-vcs/vcs"
)

type MockRepository struct {
	ResolveRevision_ func(spec string) (vcs.CommitID, error)
	ResolveTag_      func(name string) (vcs.CommitID, error)
	ResolveBranch_   func(name string) (vcs.CommitID, error)

	Branches_ func() ([]*vcs.Branch, error)
	Tags_     func() ([]*vcs.Tag, error)

	GetCommit_ func(vcs.CommitID) (*vcs.Commit, error)
	Commits_   func(vcs.CommitsOptions) ([]*vcs.Commit, uint, error)

	FileSystem_ func(at vcs.CommitID) (vfs.FileSystem, error)
}

var _ vcs.Repository = MockRepository{}

func (r MockRepository) ResolveRevision(spec string) (vcs.CommitID, error) {
	return r.ResolveRevision_(spec)
}

func (r MockRepository) ResolveTag(name string) (vcs.CommitID, error) {
	return r.ResolveTag_(name)
}

func (r MockRepository) ResolveBranch(name string) (vcs.CommitID, error) {
	return r.ResolveBranch_(name)
}

func (r MockRepository) Branches() ([]*vcs.Branch, error) {
	return r.Branches_()
}

func (r MockRepository) Tags() ([]*vcs.Tag, error) {
	return r.Tags_()
}

func (r MockRepository) GetCommit(id vcs.CommitID) (*vcs.Commit, error) {
	return r.GetCommit_(id)
}

func (r MockRepository) Commits(opt vcs.CommitsOptions) ([]*vcs.Commit, uint, error) {
	return r.Commits_(opt)
}

func (r MockRepository) FileSystem(at vcs.CommitID) (vfs.FileSystem, error) {
	return r.FileSystem_(at)
}
<|endoftext|>