Example #1
0
func New(dev Device, since EventID, interval time.Duration, flags CreateFlags,
	paths ...string) *Stream {

	cpaths := C.fswatch_make_mutable_array()
	defer C.free(unsafe.Pointer(cpaths))
	for _, dir := range paths {
		path := C.CString(dir)
		defer C.free(unsafe.Pointer(path))
		str := C.CFStringCreateWithCString(nil, path, C.kCFStringEncodingUTF8)
		defer C.free(unsafe.Pointer(str))
		C.CFArrayAppendValue(cpaths, unsafe.Pointer(str))
	}

	csince := C.FSEventStreamEventId(since)
	cinterval := C.CFTimeInterval(interval / time.Second)
	cflags := C.FSEventStreamCreateFlags(flags &^ CF_USECFTYPES)

	s := new(Stream)
	s.Chan = make(chan []Event)

	ctx := C.FSEventStreamContext{info: unsafe.Pointer(&s.Chan)}

	var cstream C.FSEventStreamRef
	if dev == 0 {
		cstream = C.fswatch_create(&ctx, cpaths, csince, cinterval, cflags)
	} else {
		cdev := C.dev_t(dev)
		cstream = C.fswatch_create_relative_to_device(
			cdev, &ctx, cpaths, csince, cinterval, cflags)
	}
	s.cstream = cstream

	return s
}
Example #2
0
// Start listening to an event stream.
func (es *EventStream) Start() {
	cPaths := C.ArrayCreateMutable(C.int(len(es.Paths)))
	defer C.CFRelease(C.CFTypeRef(cPaths))

	for _, p := range es.Paths {
		p, _ = filepath.Abs(p)
		cpath := C.CString(p)
		defer C.free(unsafe.Pointer(cpath))

		str := C.CFStringCreateWithCString(nil, cpath, C.kCFStringEncodingUTF8)
		C.CFArrayAppendValue(cPaths, unsafe.Pointer(str))
	}

	since := C.FSEventStreamEventId(EventIDSinceNow)
	if es.Resume {
		since = C.FSEventStreamEventId(es.EventID)
	}

	if es.Events == nil {
		es.Events = make(chan []Event)
	}

	es.registryID = registry.Add(es)
	context := C.FSEventStreamContext{}
	info := C.uintptr_t(es.registryID)
	latency := C.CFTimeInterval(float64(es.Latency) / float64(time.Second))
	if es.Device != 0 {
		es.stream = C.EventStreamCreateRelativeToDevice(&context, info, C.dev_t(es.Device), cPaths, since, latency, C.FSEventStreamCreateFlags(es.Flags))
	} else {
		es.stream = C.EventStreamCreate(&context, info, cPaths, since, latency, C.FSEventStreamCreateFlags(es.Flags))
	}

	started := make(chan struct{})

	go func() {
		runtime.LockOSThread()
		es.rlref = C.CFRunLoopGetCurrent()
		C.FSEventStreamScheduleWithRunLoop(es.stream, es.rlref, C.kCFRunLoopDefaultMode)
		C.FSEventStreamStart(es.stream)
		close(started)
		C.CFRunLoopRun()
	}()

	if !es.hasFinalizer {
		runtime.SetFinalizer(es, finalizer)
		es.hasFinalizer = true
	}

	<-started
}
Example #3
0
import (
	"errors"
	"os"
	"sync"
	"sync/atomic"
	"time"
	"unsafe"
)

var nilstream C.FSEventStreamRef

// Default arguments for FSEventStreamCreate function.
var (
	latency C.CFTimeInterval
	flags   = C.FSEventStreamCreateFlags(C.kFSEventStreamCreateFlagFileEvents | C.kFSEventStreamCreateFlagNoDefer)
	since   = uint64(C.FSEventsGetCurrentEventId())
)

var runloop C.CFRunLoopRef // global runloop which all streams are registered with
var wg sync.WaitGroup      // used to wait until the runloop starts

// source is used for synchronization purposes - it signals when runloop has
// started and is ready via the wg. It also serves purpose of a dummy source,
// thanks to it the runloop does not return as it also has at least one source
// registered.
var source = C.CFRunLoopSourceCreate(nil, 0, &C.CFRunLoopSourceContext{
	perform: (C.CFRunLoopPerformCallBack)(C.gosource),
})

// Errors returned when FSEvents functions fail.
Example #4
0
	FSEventStreamCreateFlags);
static CFMutableArrayRef fswatch_make_mutable_array() {
  return CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
*/
import "C"

import (
	"math/rand"
	"sync"
	"time"
	"unsafe"
)

var (
	cflags   = C.FSEventStreamCreateFlags(0)
	chans    = make(map[string](chan string))
	interval = 700 * time.Millisecond
	now      = C.FSEventStreamEventId((1 << 64) - 1)

	lock sync.Mutex
)

func init() {
	rand.Seed(time.Now().UTC().UnixNano())
}

func startScanner(dir string) {
	lock.Lock()
	chans[dir] = make(chan string)
	lock.Unlock()