Beispiel #1
0
// Schedules the Stream on a new thread
// and starts delivering events on the channel.
//
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/Reference/reference.html#jumpTo_20
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/Reference/reference.html#jumpTo_17
func (s *Stream) Start() bool {
	type watchSuccessData struct {
		runloop C.CFRunLoopRef
		stream  Stream
	}

	successChan := make(chan C.CFRunLoopRef)

	go func() {
		C.FSEventStreamScheduleWithRunLoop(s.cstream,
			C.CFRunLoopGetCurrent(), C.kCFRunLoopCommonModes)
		ok := C.FSEventStreamStart(s.cstream) != C.FALSE
		if ok {
			successChan <- C.CFRunLoopGetCurrent()
			C.CFRunLoopRun()
		} else {
			successChan <- nil
		}
	}()

	runloop := <-successChan

	if runloop == nil {
		return false
	}
	s.runloop = runloop
	return true
}
Beispiel #2
0
func startScanner(dir string) {
	lock.Lock()
	chans[dir] = make(chan string)
	lock.Unlock()

	cpaths := C.fswatch_make_mutable_array()
	defer C.free(unsafe.Pointer(cpaths))

	path := C.CString(dir)
	str := C.CFStringCreateWithCString(nil, path, C.kCFStringEncodingUTF8)
	defer C.free(unsafe.Pointer(path))
	defer C.free(unsafe.Pointer(str))

	C.CFArrayAppendValue(cpaths, unsafe.Pointer(str))

	ctx := C.FSEventStreamContext{info: unsafe.Pointer(C.CString(dir))}

	stream := C.fswatch_create(&ctx, cpaths, now, C.CFTimeInterval(interval/time.Second), cflags)

	go func() {
		C.FSEventStreamScheduleWithRunLoop(stream, C.CFRunLoopGetCurrent(), C.kCFRunLoopCommonModes)
		C.FSEventStreamStart(stream)
		C.CFRunLoopRun()
	}()
}
Beispiel #3
0
// initializes the global runloop and ensures any created stream awaits its
// readiness.
func init() {
	wg.Add(1)
	go func() {
		runloop = C.CFRunLoopGetCurrent()
		C.CFRunLoopAddSource(runloop, source, C.kCFRunLoopDefaultMode)
		C.CFRunLoopRun()
		panic("runloop has just unexpectedly stopped")
	}()
	C.CFRunLoopSourceSignal(source)
}
Beispiel #4
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
}
Beispiel #5
0
func NewWatcher() (*Watcher, error) {
	w := &Watcher{
		watches:       make(map[string]C.FSEventStreamRef),
		fsnFlags:      make(map[string]uint32),
		enFlags:       make(map[string]uint32),
		paths:         make(map[int]string),
		finfo:         make(map[int]os.FileInfo),
		fileExists:    make(map[string]bool),
		internalEvent: make(chan *FileEvent),
		Event:         make(chan *FileEvent),
		Error:         make(chan error),
		done:          make(chan bool, 1),
	}

	w.rlref = C.CFRunLoopGetCurrent() // XXX: accessing the 'current' runloop. This will cause problems with multiple watchers in one process

	// Start the runloop. This exists for the duration of the watcher
	go func() {
		C.CFRunLoopRun()
	}()

	return w, nil
}