puredata 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e5019cc763303059953a987b3987e9841bf6e3ad
4
+ data.tar.gz: 12158322048cc28ae8b83425b9a75c40915b01b8
5
+ SHA512:
6
+ metadata.gz: 2909322b6f9c15dac7f1f49c09680bbc96166ae78931ae4a6a271a3a00c7a3ce42aff1ebdcba5c3f9a3cbc8402fbf766bd4ae3d5f329d165edd10845120600e4
7
+ data.tar.gz: 61935a92985785f15c9c5ee1afb6da5460eb2db389082a261489bebc02f6b8c1e401faf1c6d4d06d9a1eae3d92cbd270d357933f185ab1e0130366fac1fbab2b
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /vendor/bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in puredata.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Tomoyuki Chikanaga
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,33 @@
1
+ = Ruby/PureData
2
+ Ruby library to manipulate PureData (Pd-extended) via socket.
3
+
4
+ == Requirements
5
+ Mac OS X
6
+ Pd-extended
7
+
8
+ == Synopsis
9
+
10
+ require "puredata"
11
+
12
+ Pd.start do |pd|
13
+ canvas = pd.canvas("sample")
14
+
15
+ osc = canvas.obj("osc~", 440)
16
+ mul = canvas.obj("*~", 0.1)
17
+ dac = canvas.obj("dac~")
18
+ osc >> mul
19
+ dac.left << mul
20
+ dac.right << mul
21
+
22
+ pd.dsp = true
23
+ sleep 5
24
+ pd.dsp = false
25
+ end
26
+
27
+ == Description
28
+
29
+ == Installation
30
+
31
+ == License
32
+
33
+ This software is released under the MIT License, see LICENSE.txt.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ require "puredata"
2
+
3
+ Pd.start do |pd|
4
+ # create abstraction "osc440.pd"
5
+ sample = pd.abstraction("osc440") do |abst|
6
+ abst.add_outlet(true)
7
+ osc = abst.obj("osc~", 440)
8
+ mul = abst.obj("*~", 0.3)
9
+ osc >> mul
10
+ abst.outlet(0) << mul
11
+ end
12
+
13
+ canvas = pd.canvas("sample")
14
+ osc440 = canvas.obj("osc440")
15
+ dac = canvas.obj("dac~")
16
+ osc440 >> dac.left
17
+ osc440 >> dac.right
18
+ canvas.save
19
+
20
+ pd.dsp = true
21
+ sleep 3
22
+ pd.dsp = false
23
+ end
@@ -0,0 +1,2 @@
1
+ #N canvas 0 22 450 300 10;
2
+ #X obj 40 40 netreceive 10002 0 old;
@@ -0,0 +1,39 @@
1
+ require "puredata"
2
+
3
+ PureData.start(:port => 10002) do |pd|
4
+ # create canvas "sample.pd"
5
+ canvas = pd.canvas("sample")
6
+
7
+ # osc~ => *~ 0.1 => dac~
8
+ osc = canvas.obj("osc~", 440)
9
+ mul = canvas.obj("*~", 0.3)
10
+ dac = canvas.obj("dac~")
11
+ canvas.connect(osc.outlet, mul.inlet(0))
12
+ canvas.connect(mul.outlet, dac.left)
13
+ canvas.connect(mul.outlet, dac.right)
14
+
15
+ pd.dsp = true
16
+ sleep 3
17
+ pd.dsp = false
18
+
19
+ # add receive object for modify frequency of osc~
20
+ freq = canvas.obj("r", "freq")
21
+ line = canvas.obj("line")
22
+ canvas.connect(freq.outlet, line.inlet)
23
+ canvas.connect(line.outlet, osc.freq)
24
+
25
+ pd.dsp = true
26
+ pd.msg(:freq, 500, 4000)
27
+ puts "freq 500 4000"
28
+ sleep 3
29
+ pd.msg(:freq, 220, 5000)
30
+ puts "freq 220 5000"
31
+ sleep 5
32
+ pd.msg(:freq, 1000, 1000)
33
+ puts "freq 1000 1000"
34
+ sleep 1
35
+ pd.msg(:freq, 100, 50)
36
+ puts "freq 100 50"
37
+ sleep 1
38
+ pd.dsp = false
39
+ end
@@ -0,0 +1,21 @@
1
+ require "puredata"
2
+
3
+ Pd.start do |pd|
4
+ # create canvas "sample.pd"
5
+ canvas = pd.canvas("sample")
6
+
7
+ # osc~ => *~ 0.1 => dac~
8
+ osc = canvas.obj("osc~", 440)
9
+ mul = canvas.obj("*~", 0.3)
10
+ dac = canvas.obj("dac~")
11
+ canvas.connect(osc.outlet, mul.inlet(0))
12
+ canvas.connect(mul.outlet, dac.left)
13
+ canvas.connect(mul.outlet, dac.right)
14
+
15
+ # save canvas
16
+ canvas.save
17
+
18
+ # Canvas#save only messaging to Pd and there's no reply.
19
+ # So we can't confirm Pd save patch to file.
20
+ sleep 1
21
+ end
@@ -0,0 +1,8 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # Ruby/PureData early scrach version.
4
+
5
+ require "puredata/pd"
6
+ require "puredata/canvas"
7
+ require "puredata/connection"
8
+ require "puredata/pdobject"
@@ -0,0 +1,98 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # Ruby/PureData Canvas, Abstraction class
4
+
5
+ class PureData
6
+ class Canvas
7
+ def initialize(pd, name, opt={})
8
+ @pd = pd
9
+ @name = name.dup
10
+ unless /\.pd\Z/ =~ @name
11
+ @name += ".pd"
12
+ end
13
+ @dir = File.expand_path(opt[:dir] || Dir.pwd)
14
+ @pdobjid = 0
15
+ pos = opt[:position] || [100, 100]
16
+ size = opt[:size] || [300, 300]
17
+ font = opt[:font] || 10
18
+ pd.msg("pd", "filename", @name, @dir)
19
+ pd.msg("#N", "canvas #{pos.join(" ")} #{size.join(" ")} #{font}")
20
+ pd.msg("#X", "pop", "1")
21
+ end
22
+
23
+ def msg(*args)
24
+ @pd.msg("pd-#{@name}", *args)
25
+ end
26
+
27
+ def obj(klass, *args)
28
+ self.msg("obj", 10, 10, klass, *args)
29
+ id = @pdobjid
30
+ @pdobjid += 1
31
+ cls = PureData.dispatch_object_class(klass, *args)
32
+ cls.new(@pd, self, id, klass, *args)
33
+ end
34
+
35
+ def connect(outlet, inlet)
36
+ obj1, outletid = outlet.outlet_tuple
37
+ obj2, inletid = inlet.inlet_tuple
38
+ oid1 = obj1.pdobjid
39
+ oid2 = obj2.pdobjid
40
+ self.msg("connect", oid1, outletid, oid2, inletid)
41
+ end
42
+
43
+ def save(path=nil)
44
+ if path
45
+ name = File.basename(path)
46
+ unless /\.pd\Z/ =~ name
47
+ name += ".pd"
48
+ end
49
+ dir = File.expand_path(File.dirname(path))
50
+ else
51
+ name = @name
52
+ dir = @dir
53
+ end
54
+ self.msg("savetofile", name, dir)
55
+ @name = name
56
+ @dir = dir
57
+ nil
58
+ end
59
+ end
60
+
61
+ class Abstraction < Canvas
62
+ def initialize(pd, name, opt={})
63
+ super(pd, name, opt)
64
+ @inlets = []
65
+ @outlets = []
66
+ end
67
+
68
+ def inlet(idx=0)
69
+ @inlets[idx].outlet(0)
70
+ end
71
+
72
+ def outlet(idx=0)
73
+ @outlets[idx].inlet(0)
74
+ end
75
+
76
+ def add_inlet(audio=false)
77
+ if audio
78
+ @inlets << self.obj("inlet~")
79
+ else
80
+ @inlets << self.obj("inlet")
81
+ end
82
+ end
83
+
84
+ def add_outlet(audio=false)
85
+ if audio
86
+ @outlets << self.obj("outlet~")
87
+ else
88
+ @outlets << self.obj("outlet")
89
+ end
90
+ end
91
+
92
+ def self.create(pd, name, opt={})
93
+ abstract = self.new(pd, name, opt)
94
+ yield(abstract)
95
+ abstract.save
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,67 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # PureData connection (inlet/outlet) control
4
+
5
+ class PureData
6
+ class IOlet
7
+ def initialize(obj, idx=0)
8
+ @obj = obj
9
+ @idx = idx
10
+ end
11
+
12
+ attr_reader :idx
13
+
14
+ def canvas
15
+ @obj.canvas
16
+ end
17
+
18
+ def pdobjid
19
+ @obj.pdobjid
20
+ end
21
+
22
+ def name
23
+ @obj.name
24
+ end
25
+
26
+ def check_canvas(other)
27
+ unless @obj.canvas == other.canvas
28
+ raise "#{@obj.name} and #{other.name} must be in same canvas"
29
+ end
30
+ end
31
+
32
+ def pair
33
+ [@obj, @idx]
34
+ end
35
+ end
36
+
37
+ class Inlet < IOlet
38
+ def inlet_tuple
39
+ [@obj, @idx]
40
+ end
41
+
42
+ def <<(other)
43
+ if other.is_a?(PdObject)
44
+ other = other.outlet
45
+ end
46
+ check_canvas(other)
47
+ @obj.canvas.connect(other, self)
48
+ other
49
+ end
50
+ end
51
+
52
+ class Outlet < IOlet
53
+ def outlet_tuple
54
+ [@obj, @idx]
55
+ end
56
+
57
+ def >>(other)
58
+ if other.is_a?(PdObject)
59
+ other = other.inlet
60
+ end
61
+ check_canvas(other)
62
+ @obj.canvas.connect(self, other)
63
+ other
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,132 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # Ruby/PureData early scrach version.
4
+
5
+ require "socket"
6
+
7
+ require "puredata/canvas"
8
+
9
+ class PureData
10
+ case RUBY_PLATFORM
11
+ when /darwin/
12
+ @@pd_app_path = "/Applications/Pd-extended.app/Contents/Resources/bin/pd"
13
+ else
14
+ @@pd_app_path = nil
15
+ end
16
+
17
+ def self.start(opt={}, &blk)
18
+ pd = self.new(opt)
19
+ pd.fork_pd(opt)
20
+ pd.start(opt, &blk)
21
+ end
22
+
23
+ def self.attach(opt={}, &blk)
24
+ pd = self.new(opt)
25
+ pd.start(opt, &blk)
26
+ end
27
+
28
+ def initialize(opt={})
29
+ @portno = (opt[:port] || 10002).to_i
30
+ end
31
+
32
+ def fork_pd(opt={})
33
+ path = opt[:pd_app_path] || @@pd_app_path
34
+ pd_params = opt[:pd_params] || []
35
+ if path.nil? or not File.executable?(path)
36
+ raise "option :pd_app_path (Pd-extended executable) must be specified."
37
+ end
38
+ cmd = [
39
+ path,
40
+ pd_params,
41
+ "-nogui",
42
+ "-send", "pd filename ruby-pd.pd ./;",
43
+ "-send", "#N canvas 10 10 200 200 10;",
44
+ "-send", "#X pop 1;",
45
+ "-send", "pd-ruby-pd.pd obj 50 50 netreceive #{@portno} 0 old;",
46
+ ].flatten
47
+ @pid = fork do
48
+ Process.setsid
49
+ exec(*cmd)
50
+ end
51
+ end
52
+
53
+ def bind(opt={})
54
+ err = nil
55
+ 200.times do
56
+ sleep 0.1
57
+ begin
58
+ @sock = TCPSocket.new("localhost", @portno)
59
+ break
60
+ rescue
61
+ err = $!
62
+ end
63
+ end
64
+ unless @sock
65
+ $stderr.puts("connect to localhost:#{@portno} failed")
66
+ raise err
67
+ end
68
+ end
69
+
70
+ def start(opt={}, &blk)
71
+ begin
72
+ bind(opt)
73
+ if blk
74
+ blk.call(self)
75
+ end
76
+ ensure
77
+ if blk
78
+ stop
79
+ end
80
+ end
81
+ end
82
+
83
+ def stop
84
+ if @sock
85
+ @sock.close unless @sock.closed?
86
+ @sock = nil
87
+ end
88
+
89
+ return if @pid.nil?
90
+
91
+ begin
92
+ Process.kill(:TERM, -@pid)
93
+ rescue Errno::ESRCH
94
+ rescue Errno::EPERM
95
+ raise "fail to kill process(#{@pid}): #{$!}"
96
+ end
97
+ Process.waitpid(@pid)
98
+ ensure
99
+ @sock = nil
100
+ @pid = nil
101
+ end
102
+
103
+ def msg(*args)
104
+ @sock.puts(args.map{|l| l.to_s}.join(" ") + ";")
105
+ end
106
+
107
+ def canvas(name, opt={})
108
+ Canvas.new(self, name, opt)
109
+ end
110
+
111
+ def abstraction(name, opt={}, &blk)
112
+ if blk
113
+ Abstraction.create(self, name, opt, &blk)
114
+ else
115
+ Abstraction.new(self, name, opt)
116
+ end
117
+ end
118
+
119
+ def dsp=(flag)
120
+ if flag
121
+ self.msg("pd", "dsp", 1)
122
+ else
123
+ self.msg("pd", "dsp", 0)
124
+ end
125
+ end
126
+
127
+ def quit
128
+ self.msg("pd", "quit")
129
+ end
130
+ end
131
+
132
+ Pd = PureData
@@ -0,0 +1,9 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # Ruby/PureData Pd object wrapper classes
4
+
5
+ require "puredata/pdobject/pdobject"
6
+ require "puredata/pdobject/osc"
7
+ require "puredata/pdobject/dac"
8
+ require "puredata/pdobject/receive"
9
+
@@ -0,0 +1,16 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # dac~ object class
4
+
5
+ class PureData
6
+ class Dac < PdObject
7
+ def left
8
+ inlet(0)
9
+ end
10
+ def right
11
+ inlet(1)
12
+ end
13
+ end
14
+ end
15
+
16
+ PureData.register_pdobject(PureData::Dac, "dac~")
@@ -0,0 +1,12 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # osc~ object class
4
+
5
+ class PureData
6
+ class Osc < PdObject
7
+ def freq
8
+ inlet(0)
9
+ end
10
+ end
11
+ end
12
+ PureData.register_pdobject(PureData::Osc, "osc~")
@@ -0,0 +1,55 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # Ruby/PureData ojbect wrapper base class
4
+
5
+ class PureData
6
+
7
+ @@pdclass = {}
8
+
9
+ def self.register_pdobject(klass, *names)
10
+ names.each do |n|
11
+ @@pdclass[n] = klass
12
+ end
13
+ end
14
+
15
+ def self.dispatch_object_class(klass, *args)
16
+ cls = @@pdclass[klass.to_s]
17
+ cls ||= PdObject
18
+ cls
19
+ end
20
+
21
+ class PdObject
22
+ def initialize(pd, canvas, pdobjid, name, *args)
23
+ @pd = pd
24
+ @canvas = canvas
25
+ @pdobjid = pdobjid
26
+ @name = name
27
+ @args = args
28
+ end
29
+ attr_reader :canvas, :pdobjid, :name
30
+
31
+ def inlet(idx=0)
32
+ Inlet.new(self, idx)
33
+ end
34
+
35
+ def inlet_pair
36
+ [self, 0]
37
+ end
38
+
39
+ def outlet(idx=0)
40
+ Outlet.new(self, idx)
41
+ end
42
+
43
+ def outlet_pair
44
+ [self, 0]
45
+ end
46
+
47
+ def <<(other)
48
+ self.inlet << other
49
+ end
50
+
51
+ def >>(other)
52
+ self.outlet >> other
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,13 @@
1
+ # vim:encoding=utf-8
2
+ #
3
+ # receive object class
4
+
5
+ class PureData
6
+ class Receive < PdObject
7
+ def msg(*args)
8
+ @pd.msg(@args[0], *args)
9
+ end
10
+ end
11
+ end
12
+
13
+ PureData.register_pdobject(PureData::Receive, "receive", "r")
@@ -0,0 +1,3 @@
1
+ module Puredata
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'puredata/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "puredata"
8
+ spec.version = Puredata::VERSION
9
+ spec.authors = ["CHIKANAGA Tomoyuki"]
10
+ spec.email = ["nagachika00@gmail.com"]
11
+
12
+ spec.summary = "Ruby library to manipulate PureData (Pd-extended) via socket."
13
+ spec.description = "Ruby library to manipulate PureData (Pd-extended) via socket."
14
+ spec.homepage = "https://github.com/nagachika/ruby-puredata"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.12"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: puredata
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - CHIKANAGA Tomoyuki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Ruby library to manipulate PureData (Pd-extended) via socket.
42
+ email:
43
+ - nagachika00@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.rdoc
52
+ - Rakefile
53
+ - example/abstraction.rb
54
+ - example/example.pd
55
+ - example/example.rb
56
+ - example/save.rb
57
+ - lib/puredata.rb
58
+ - lib/puredata/canvas.rb
59
+ - lib/puredata/connection.rb
60
+ - lib/puredata/pd.rb
61
+ - lib/puredata/pdobject.rb
62
+ - lib/puredata/pdobject/dac.rb
63
+ - lib/puredata/pdobject/osc.rb
64
+ - lib/puredata/pdobject/pdobject.rb
65
+ - lib/puredata/pdobject/receive.rb
66
+ - lib/puredata/version.rb
67
+ - puredata.gemspec
68
+ homepage: https://github.com/nagachika/ruby-puredata
69
+ licenses: []
70
+ metadata: {}
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 2.5.1
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: Ruby library to manipulate PureData (Pd-extended) via socket.
91
+ test_files: []