everything related to duct tape audio suite (dtas)
 help / color / mirror / Atom feed
4047a42a7a995b4d58d2f06913e940c52d4f2ef0 blob 4144 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
 
# Copyright (C) 2013-2019 all contributors <dtas-all@nongnu.org>
# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
# frozen_string_literal: true
require_relative '../dtas'
require_relative 'nonblock'

begin
require 'fiddle'

# used to restart DTAS::Source::SplitFX processing in dtas-player
# if the YAML file is edited
module DTAS::Watchable # :nodoc:
  class InotifyReadableIter # :nodoc:

    Inotify_init = Fiddle::Function.new(DTAS.libc['inotify_init1'],
      [ Fiddle::TYPE_INT ],
      Fiddle::TYPE_INT)

    Inotify_add_watch = Fiddle::Function.new(DTAS.libc['inotify_add_watch'],
      [ Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT ],
      Fiddle::TYPE_INT)

    # IO.select compatibility
    attr_reader :to_io  #:nodoc:

    def initialize # :nodoc:
      fd = Inotify_init.call(02000000 | 04000) # CLOEXEC | NONBLOCK
      raise "inotify_init failed: #{Fiddle.last_error}" if fd < 0
      @to_io = DTAS::Nonblock.for_fd(fd)
      @buf = ''.b
      @q = []
    end

    # struct inotify_event {
    #     int      wd;       /* Watch descriptor */
    #     uint32_t mask;     /* Mask describing event */
    #     uint32_t cookie;   /* Unique cookie associating related
    #                           events (for rename(2)) */
    #     uint32_t len;      /* Size of name field */
    #     char     name[];   /* Optional null-terminated name */
    InotifyEvent = Struct.new(:wd, :mask, :cookie, :len, :name) # :nodoc:

    def take # :nodoc:
      event = @q.pop and return event
      case rv = @to_io.read_nonblock(16384, @buf, exception: false)
      when :wait_readable, nil
        return
      else
        until rv.empty?
          hdr = rv.slice!(0,16)
          name = nil
          wd, mask, cookie, len = res = hdr.unpack('iIII')
          wd && mask && cookie && len or
            raise "bogus inotify_event #{res.inspect} hdr=#{hdr.inspect}"
          if len > 0
            name = rv.slice!(0, len)
            name.size == len or raise "short name #{name.inspect} != #{len}"
            name.sub!(/\0+\z/, '') or
              raise "missing: `\\0', inotify_event.name=#{name.inspect}"
            name = DTAS.dedupe_str(name)
          end
          ie = InotifyEvent.new(wd, mask, cookie, len, name)
          if event
            @q << ie
          else
            event = ie
          end
        end # /until rv.empty?
        return event
      end while true
    end

    FLAGS = 8 | 128 # CLOSE_WRITE | MOVED_TO

    def readable_iter
      or_call = false
      while event = take # drain the buffer
        w = @watches[event.wd] or next
        if (event.mask & FLAGS) != 0 && w[event.name]
          or_call = true
        end
      end
      if or_call
        @on_readable.call
        :delete
      else
        :wait_readable
      end
    end

    def add_watch(watchdir)
      wd = Inotify_add_watch.call(@to_io.fileno, watchdir, FLAGS)
      raise "inotify_add_watch failed: #{Fiddle.last_error}" if wd < 0
      wd
    end

    def close
      @to_io = @to_io.close if @to_io
    end

    # we must watch the directory, since
    def watch_files(paths, blk)
      @watches = {} # wd -> { basename -> true }
      @on_readable = blk
      @dir2wd = {}
      Array(paths).each do |path|
        watchdir, watchbase = File.split(File.expand_path(path))
        begin
          wd = @dir2wd[watchdir] ||= add_watch(watchdir)
          m = @watches[wd] ||= {}
          m[watchbase] = true
        rescue SystemCallError => e
          warn "#{watchdir.dump}: #{e.message} (#{e.class})"
        end
      end
    end
  end

  def watch_begin(blk)
    @ino = InotifyReadableIter.new
    @ino.watch_files(@watch_extra << @infile, blk)
    @ino
  end

  def watch_extra(paths)
    @ino.watch_extra(paths)
  end

  # Closing the inotify descriptor (instead of using inotify_rm_watch)
  # is cleaner because it avoids EINVAL on race conditions in case
  # a directory is deleted: https://lkml.org/lkml/2007/7/9/3
  def watch_end(srv)
    srv.wait_ctl(@ino, :delete)
    @ino = @ino.close
  end
end

rescue LoadError, Fiddle::DLError => e
  warn "#{e.message} (#{e.class})"
end
debug log:

solving 4047a42 ...
found 4047a42 in https://80x24.org/dtas-all/20191201012653.21967-5-e@80x24.org/
found d0f37af in https://80x24.org/dtas.git
preparing index
index prepared:
100644 d0f37af8289c6c9f40f8892d826d4a1e24596600	lib/dtas/watchable.rb

applying [1/1] https://80x24.org/dtas-all/20191201012653.21967-5-e@80x24.org/
diff --git a/lib/dtas/watchable.rb b/lib/dtas/watchable.rb
index d0f37af..4047a42 100644

Checking patch lib/dtas/watchable.rb...
Applied patch lib/dtas/watchable.rb cleanly.

index at:
100644 4047a42a7a995b4d58d2f06913e940c52d4f2ef0	lib/dtas/watchable.rb

everything related to duct tape audio suite (dtas)

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://80x24.org/dtas-all
	git clone --mirror http://ou63pmih66umazou.onion/dtas-all

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V1 dtas-all dtas-all/ https://80x24.org/dtas-all \
		dtas-all@nongnu.org
	public-inbox-index dtas-all

Example config snippet for mirrors.
Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.audio.dtas
	nntp://ou63pmih66umazou.onion/inbox.comp.audio.dtas
 note: .onion URLs require Tor: https://www.torproject.org/

code repositories for the project(s) associated with this inbox:

	dtas.git

AGPL code for this site: git clone https://public-inbox.org/public-inbox.git