wiretap 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +32 -0
- data/README +93 -0
- data/ext/Makefile +146 -0
- data/ext/audio_format.cpp +224 -0
- data/ext/bmp.cpp +65 -0
- data/ext/extconf.rb +85 -0
- data/ext/format.cpp +347 -0
- data/ext/image.h +27 -0
- data/ext/image_format.cpp +194 -0
- data/ext/node.cpp +401 -0
- data/ext/nodechildren.cpp +67 -0
- data/ext/nodeframes.cpp +233 -0
- data/ext/nodemetadata.cpp +90 -0
- data/ext/ppm.cpp +132 -0
- data/ext/server.cpp +202 -0
- data/ext/serverlist.cpp +183 -0
- data/ext/sgi.cpp +69 -0
- data/ext/testserver/Makefile +5 -0
- data/ext/testserver/cfg/wiretap_path_translation_db.xml +44 -0
- data/ext/testserver/cfg/wiretapd.cfg +74 -0
- data/ext/testserver/cfg/wiretapd.res +60 -0
- data/ext/testserver/db.sql +50 -0
- data/ext/testserver/server.cpp +206 -0
- data/ext/testserver/testserver.rb +146 -0
- data/ext/thread_worker.cpp +85 -0
- data/ext/wiretap.cpp +68 -0
- data/ext/wiretap.h +115 -0
- data/lib/wiretap.rb +280 -0
- data/test/audio.rb +27 -0
- data/test/convert.rb +35 -0
- data/test/image.rb +101 -0
- data/test/read_frames.rb +142 -0
- data/test/wiretap-images/01.ppm +0 -0
- data/test/wiretap-images/32bit.stoneimage +621 -0
- data/test/wiretap-images/36bit.stoneimage +1036 -0
- data/test/wiretap-images/48bit.stoneimage +800 -1
- data/test/wiretap-images/a.stoneimage +0 -0
- data/test/wiretap-images/a0.stoneimage +0 -0
- data/test/wiretap-images/a1.stoneimage +0 -0
- data/test/wiretap-images/a2.stoneimage +0 -0
- data/test/wiretap-images/a3.stoneimage +0 -0
- data/test/wiretap-images/a4.stoneimage +0 -0
- data/test/wiretap-images/b1.stonesound +0 -0
- data/test/wiretap-images/importable-seq/00000001.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000002.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000003.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000004.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000005.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000006.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000007.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000008.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000009.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000010.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000011.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000012.ppm +0 -0
- data/test/wiretap-images/monsters_001.tif +0 -0
- data/test/wiretap-images/monsters_002.tif +0 -0
- data/test/wiretap-images/monsters_003.tif +0 -0
- data/test/wiretap-images/output.mov +0 -0
- data/test/wiretap-images/output.wav +0 -0
- data/test/write_frames.rb +82 -0
- metadata +138 -0
data/LICENSE
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
Copyright (c) 2006
|
2
|
+
|
3
|
+
Hecticelectric BV, Amsterdam
|
4
|
+
Max Lapshin
|
5
|
+
Julian "Julik" Tarkhanov
|
6
|
+
|
7
|
+
<tools@hecticelectric.nl>
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
10
|
+
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
11
|
+
without limitation the rights to use, copy, modify and merge the copies of the Software, and to permit
|
12
|
+
persons to whom the Software is furnished to do so, subject to the following conditions:
|
13
|
+
|
14
|
+
a) The above copyright notice and this permission notice shall be included in all copies or substantial
|
15
|
+
portions of the Software.
|
16
|
+
|
17
|
+
b) Portions of the Software produced by Autodesk Media&Entertainment might not be included with the copies
|
18
|
+
or portions of the Software
|
19
|
+
|
20
|
+
c) The images and sound files provided with the Software (test footage) might not be used for anything but
|
21
|
+
testing the Software. Persons and organizations obtaining a copy of the Software do not retain the rights
|
22
|
+
to use the provided footage for different purposes.
|
23
|
+
|
24
|
+
d) Distribution (including commercial distribution) of the Software is possible only with explicit written permission
|
25
|
+
of Hecticelectric BV, Amsterdam and Autodesk Media&Entertainment, outside of distribution methods supplied by the
|
26
|
+
aforementioned parties.
|
27
|
+
|
28
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
29
|
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
30
|
+
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
31
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
32
|
+
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
=== Ruby bindings for Autodesk Wiretap
|
2
|
+
|
3
|
+
These bindings allow you to access Wiretap-enabled Autodesk Media&Entertainment systems such as Flame, Flint and Smoke.
|
4
|
+
To use the bindings with your Media system you will need the following:
|
5
|
+
|
6
|
+
* Wire license
|
7
|
+
* Wiretap daemon (should be installed and started separately on the machine to which the Stone storage devices are connected)
|
8
|
+
|
9
|
+
=== Dependencies for clip output
|
10
|
+
|
11
|
+
The bindings depend on the Wiretap SDK and ActiveSupport (available as part of Rails).
|
12
|
+
|
13
|
+
It is possible to export video frames as .sgi images without any dependencies (clips will be exported as image sequences).
|
14
|
+
|
15
|
+
However, if you need to export or import video or export and import audio you will need to have
|
16
|
+
additional libraries and binaries installed. These are used by the bindings to de/encode the graphics and sound.
|
17
|
+
|
18
|
+
For video files:
|
19
|
+
* mencoder + ffmpeg
|
20
|
+
|
21
|
+
For sound files:
|
22
|
+
* libsndfile
|
23
|
+
|
24
|
+
=== Running the unit tests
|
25
|
+
|
26
|
+
Define a RUBY_WIRETAP_TEST_HOST environment variable that will contain the hostname or IP address
|
27
|
+
of your IFFS system. Make a PAL 720x576 8-bit project on the system and name it "RubyWiretapTest".
|
28
|
+
|
29
|
+
Run rake.
|
30
|
+
|
31
|
+
=== Building the bindings
|
32
|
+
|
33
|
+
To build the bindings you will need the Wiretap SDK, distributed free of charge by Autodesk. Currently you also
|
34
|
+
need to use GCC 3.3 to compile against the supplied libraries (GCC 4.0 will not work with current stable libraries,
|
35
|
+
but it is required to build against new beta version).
|
36
|
+
|
37
|
+
Please note that it's currently not possible to build the bindings on a Windows system. If You require to build them on
|
38
|
+
Windows, contact authors. Supported build systems are Linux, MacOS (PowerPC only with current stable libraries) and
|
39
|
+
IRIX (although this configuration has not been tested yet).
|
40
|
+
|
41
|
+
Additionally, Wiretap SDK will only run and link in Rosetta on Intel Macs (therefore your Ruby will also need to be PPC).
|
42
|
+
(or You can try to use new beta version on Wiretap SDK)
|
43
|
+
|
44
|
+
Build the bindings by issuing the following commands:
|
45
|
+
|
46
|
+
export WIRETAP_INSTALL_DIR=/usr/local/lib/wiretap
|
47
|
+
rake build
|
48
|
+
|
49
|
+
=== Simplistic examples
|
50
|
+
|
51
|
+
Test a Wiretap connection:
|
52
|
+
|
53
|
+
require 'lib/wiretap'
|
54
|
+
server = Wiretap::Server.new("flame-01")
|
55
|
+
puts "Flame is running" if server.alive?
|
56
|
+
|
57
|
+
Retrieve frame 22 from a clip as an SGI file:
|
58
|
+
|
59
|
+
require 'lib/wiretap'
|
60
|
+
clip = Wiretap::open('192.168.2.2/stonefs/SuperCommercial/Default/capture')
|
61
|
+
raise "It has to be a clip" unless clip.clip?
|
62
|
+
clip.frames.dump(22, '/tmp/frame22.sgi')
|
63
|
+
|
64
|
+
See the documentation for more info on accessing Wiretap servers and nodes from your Ruby program.
|
65
|
+
|
66
|
+
=== Sound and image output
|
67
|
+
|
68
|
+
The bindings support decoding and encoding of all clip formats on Discreet framestores, inlcuding 8, 10 and 12bit video and
|
69
|
+
standard 48khz audio. Both 12-bit packed (36bit per pixel) and 12-bit unpacked (48bit per pixel) variants are supported.
|
70
|
+
Please note that when 10 or 12 bit video is extracted it's going to be upsampled to 16bit per channel
|
71
|
+
as supported by .sgi image format. There are no formats that natively support 10bit or 12bit color (except for Cineon and
|
72
|
+
DPX which are outside of the scope this extension).
|
73
|
+
|
74
|
+
Sound is exported as AIFF files.
|
75
|
+
|
76
|
+
=== Test footage
|
77
|
+
|
78
|
+
The test footage used for the bindings is courtesy of HecticElectric BV, Amsterdam. The use of these clips for testing the bindings has been explicitly and exclusively allowed for this product only. You are not allowed to distribute or use the footage separately from the bindings or for purposes other than testing the software.
|
79
|
+
|
80
|
+
=== Testing procedures
|
81
|
+
|
82
|
+
On your Flame, Flint or Inferno system, create a new project on the framestore called "RubyWiretapTest". Make sure that it's 8-bit PAL 720x576 and that it has a "Default" library (it gets created for you automatically).
|
83
|
+
|
84
|
+
If you are using Smoke, Fire, Backdraft or Backdraft Conform as Wiretap host and you want to test the bindings on it, you will need to have a top-level library called "RubyWiretapTest" and a project inside it called "Default".
|
85
|
+
|
86
|
+
Then define the environment variable referring to your system and run the test suite:
|
87
|
+
|
88
|
+
export RUBY_WIRETAP_TEST_HOST=address_of_your_flame_system
|
89
|
+
rake
|
90
|
+
|
91
|
+
During the test run the program will write frames and sound to this library. Authors hold no responsibility if other clips or materials on the framestore get lost or damaged during the operation.
|
92
|
+
|
93
|
+
After that the media has been written to the framestore (which tests the write operations) the same media is going to be retrieved. If the dependencies are met, the images are going to be converted and output to the test directory - you will receive a number of graphics files and a sound file. Please analyze the output carefully to make sure clip output is working as advertized.
|
data/ext/Makefile
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
|
2
|
+
SHELL = /bin/sh
|
3
|
+
|
4
|
+
#### Start of system configuration section. ####
|
5
|
+
|
6
|
+
srcdir = .
|
7
|
+
topdir = /opt/local/lib/ruby/1.8/i686-darwin8.8.3
|
8
|
+
hdrdir = $(topdir)
|
9
|
+
VPATH = $(srcdir):$(topdir):$(hdrdir)
|
10
|
+
prefix = $(DESTDIR)/opt/local
|
11
|
+
exec_prefix = $(DESTDIR)/opt/local
|
12
|
+
sitedir = $(prefix)/lib/ruby/site_ruby
|
13
|
+
rubylibdir = $(libdir)/ruby/$(ruby_version)
|
14
|
+
archdir = $(rubylibdir)/$(arch)
|
15
|
+
sbindir = $(exec_prefix)/sbin
|
16
|
+
vendordir = $(prefix)/lib/ruby/vendor_ruby
|
17
|
+
datadir = $(prefix)/share
|
18
|
+
includedir = $(prefix)/include
|
19
|
+
infodir = $(prefix)/info
|
20
|
+
sysconfdir = $(prefix)/etc
|
21
|
+
mandir = $(DESTDIR)/opt/local/share/man
|
22
|
+
libdir = $(DESTDIR)/opt/local/lib
|
23
|
+
sharedstatedir = $(prefix)/com
|
24
|
+
oldincludedir = $(DESTDIR)/usr/include
|
25
|
+
sitearchdir = $(sitelibdir)/$(sitearch)
|
26
|
+
vendorarchdir = $(vendorlibdir)/$(vendorarch)
|
27
|
+
bindir = $(exec_prefix)/bin
|
28
|
+
localstatedir = $(prefix)/var
|
29
|
+
vendorlibdir = $(vendordir)/$(ruby_version)
|
30
|
+
sitelibdir = $(sitedir)/$(ruby_version)
|
31
|
+
libexecdir = $(exec_prefix)/libexec
|
32
|
+
|
33
|
+
CC = g++
|
34
|
+
LIBRUBY = $(LIBRUBY_SO)
|
35
|
+
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
36
|
+
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
|
37
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
|
38
|
+
|
39
|
+
RUBY_EXTCONF_H =
|
40
|
+
CFLAGS = -fno-common -O -pipe -I/opt/local/include -fno-common -pipe -fno-common -I../../wiretap_api//api -Wall
|
41
|
+
INCFLAGS = -I. -I. -I/opt/local/lib/ruby/1.8/i686-darwin8.8.3 -I.
|
42
|
+
CPPFLAGS = -DHAVE_WIRETAPCLIENTAPI_H -DHAVE_SNDFILE_H -O -pipe -I/opt/local/include
|
43
|
+
CXXFLAGS = $(CFLAGS)
|
44
|
+
DLDFLAGS = -L/opt/local/lib -L../../wiretap_api//lib/dbg/MACOSX/fat/Darwin_8_3_0/GCC_4_0_1/
|
45
|
+
LDSHARED = cc -dynamic -bundle -undefined suppress -flat_namespace
|
46
|
+
AR = ar
|
47
|
+
EXEEXT =
|
48
|
+
|
49
|
+
RUBY_INSTALL_NAME = ruby
|
50
|
+
RUBY_SO_NAME = ruby
|
51
|
+
arch = i686-darwin8.8.3
|
52
|
+
sitearch = i686-darwin8.8.3
|
53
|
+
vendorarch = i686-darwin8.8.3
|
54
|
+
ruby_version = 1.8
|
55
|
+
ruby = /opt/local/bin/ruby
|
56
|
+
RUBY = $(ruby)
|
57
|
+
RM = rm -f
|
58
|
+
MAKEDIRS = mkdir -p
|
59
|
+
INSTALL = /usr/bin/install -c
|
60
|
+
INSTALL_PROG = $(INSTALL) -m 0755
|
61
|
+
INSTALL_DATA = $(INSTALL) -m 644
|
62
|
+
COPY = cp
|
63
|
+
|
64
|
+
#### End of system configuration section. ####
|
65
|
+
|
66
|
+
preload =
|
67
|
+
|
68
|
+
libpath = $(libdir)
|
69
|
+
LIBPATH = -L"$(libdir)"
|
70
|
+
DEFFILE =
|
71
|
+
|
72
|
+
CLEANFILES =
|
73
|
+
DISTCLEANFILES =
|
74
|
+
|
75
|
+
extout =
|
76
|
+
extout_prefix =
|
77
|
+
target_prefix =
|
78
|
+
LOCAL_LIBS =
|
79
|
+
LIBS = $(LIBRUBYARG_SHARED) -lwiretapClientAPI -lsndfile -lpthread -ldl -lobjc
|
80
|
+
SRCS = audio_format.cpp bmp.cpp format.cpp image_format.cpp node.cpp nodechildren.cpp nodeframes.cpp nodemetadata.cpp ppm.cpp server.cpp serverlist.cpp sgi.cpp thread_worker.cpp wiretap.cpp
|
81
|
+
OBJS = audio_format.o bmp.o format.o image_format.o node.o nodechildren.o nodeframes.o nodemetadata.o ppm.o server.o serverlist.o sgi.o thread_worker.o wiretap.o
|
82
|
+
TARGET = wiretap_bin
|
83
|
+
DLLIB = $(TARGET).bundle
|
84
|
+
EXTSTATIC =
|
85
|
+
STATIC_LIB =
|
86
|
+
|
87
|
+
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
88
|
+
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
89
|
+
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
90
|
+
|
91
|
+
TARGET_SO = $(DLLIB)
|
92
|
+
CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
|
93
|
+
CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
|
94
|
+
|
95
|
+
all: $(DLLIB)
|
96
|
+
static: $(STATIC_LIB)
|
97
|
+
|
98
|
+
clean:
|
99
|
+
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
|
100
|
+
|
101
|
+
distclean: clean
|
102
|
+
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
103
|
+
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
104
|
+
|
105
|
+
realclean: distclean
|
106
|
+
install: install-so install-rb
|
107
|
+
|
108
|
+
install-so: $(RUBYARCHDIR)
|
109
|
+
install-so: $(RUBYARCHDIR)/$(DLLIB)
|
110
|
+
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
|
111
|
+
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
|
112
|
+
install-rb: pre-install-rb install-rb-default
|
113
|
+
install-rb-default: pre-install-rb-default
|
114
|
+
pre-install-rb: Makefile
|
115
|
+
pre-install-rb-default: Makefile
|
116
|
+
$(RUBYARCHDIR):
|
117
|
+
$(MAKEDIRS) $@
|
118
|
+
|
119
|
+
site-install: site-install-so site-install-rb
|
120
|
+
site-install-so: install-so
|
121
|
+
site-install-rb: install-rb
|
122
|
+
|
123
|
+
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
|
124
|
+
|
125
|
+
.cc.o:
|
126
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
127
|
+
|
128
|
+
.cxx.o:
|
129
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
130
|
+
|
131
|
+
.cpp.o:
|
132
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
133
|
+
|
134
|
+
.C.o:
|
135
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
136
|
+
|
137
|
+
.c.o:
|
138
|
+
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
|
139
|
+
|
140
|
+
$(DLLIB): $(OBJS)
|
141
|
+
@-$(RM) $@
|
142
|
+
$(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LOCAL_LIBS) $(LIBS)
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
$(OBJS): ruby.h defines.h
|
@@ -0,0 +1,224 @@
|
|
1
|
+
#include "wiretap.h"
|
2
|
+
#ifdef HAVE_SNDFILE_H
|
3
|
+
#include <sndfile.h>
|
4
|
+
|
5
|
+
typedef struct {
|
6
|
+
sf_count_t position;
|
7
|
+
sf_count_t size;
|
8
|
+
unsigned char* frame;
|
9
|
+
} virtual_file;
|
10
|
+
|
11
|
+
static sf_count_t v_get_filelen(void *user_data) {
|
12
|
+
virtual_file* vf = (virtual_file *)user_data;
|
13
|
+
return vf->size;
|
14
|
+
}
|
15
|
+
static sf_count_t v_seek(sf_count_t offset, int whence, void *user_data) {
|
16
|
+
virtual_file* vf = (virtual_file *)user_data;
|
17
|
+
switch(whence) {
|
18
|
+
case SEEK_SET:
|
19
|
+
if(offset > vf->size || offset < 0) {
|
20
|
+
return -1;
|
21
|
+
}
|
22
|
+
vf->position = offset;
|
23
|
+
return 0;
|
24
|
+
case SEEK_CUR:
|
25
|
+
if(offset > vf->size - vf->position || vf->position + offset < 0) {
|
26
|
+
return -1;
|
27
|
+
}
|
28
|
+
vf->position += offset;
|
29
|
+
return 0;
|
30
|
+
case SEEK_END:
|
31
|
+
if(offset > 0 || vf->size + offset < 0) {
|
32
|
+
return -1;
|
33
|
+
}
|
34
|
+
vf->position = vf->size + offset;
|
35
|
+
return 0;
|
36
|
+
}
|
37
|
+
return -1;
|
38
|
+
}
|
39
|
+
static sf_count_t v_read(void *ptr, sf_count_t count, void *user_data) {
|
40
|
+
virtual_file* vf = (virtual_file *)user_data;
|
41
|
+
if(count <= 0) {
|
42
|
+
return 0;
|
43
|
+
}
|
44
|
+
sf_count_t len = count;
|
45
|
+
if(count + vf->position > vf->size) {
|
46
|
+
len = vf->size - vf->position;
|
47
|
+
}
|
48
|
+
memcpy(ptr, vf->frame + vf->position, len);
|
49
|
+
vf->position += len;
|
50
|
+
return len;
|
51
|
+
}
|
52
|
+
static sf_count_t v_write(const void *ptr, sf_count_t count, void *user_data) {
|
53
|
+
return 0;
|
54
|
+
}
|
55
|
+
static sf_count_t v_tell(void *user_data) {
|
56
|
+
virtual_file* vf = (virtual_file *)user_data;
|
57
|
+
return vf->position;
|
58
|
+
}
|
59
|
+
|
60
|
+
static int detect_audio_format(ID type) {
|
61
|
+
ID dlaudio_float = rb_intern("dlaudio_float");
|
62
|
+
ID dlaudio_float_le = rb_intern("dlaudio_float_le");
|
63
|
+
ID dlaudio_int16 = rb_intern("dlaudio_int16");
|
64
|
+
ID dlaudio_int16_le = rb_intern("dlaudio_int16_le");
|
65
|
+
ID dlaudio_int24 = rb_intern("dlaudio_int24");
|
66
|
+
ID dlaudio_int24_le = rb_intern("dlaudio_int24_le");
|
67
|
+
ID dlaudio_wav = rb_intern("dlaudio_wav");
|
68
|
+
ID dlaudio_aiff = rb_intern("dlaudio_aiff");
|
69
|
+
|
70
|
+
if(type == dlaudio_float) return SF_FORMAT_RAW | SF_FORMAT_FLOAT;
|
71
|
+
if(type == dlaudio_float_le) return SF_FORMAT_RAW | SF_FORMAT_FLOAT | SF_ENDIAN_LITTLE;
|
72
|
+
if(type == dlaudio_int16) return SF_FORMAT_RAW | SF_FORMAT_PCM_16;
|
73
|
+
if(type == dlaudio_int16_le) return SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
|
74
|
+
if(type == dlaudio_int24) return SF_FORMAT_RAW | SF_FORMAT_PCM_24;
|
75
|
+
if(type == dlaudio_int24_le) return SF_FORMAT_RAW | SF_FORMAT_PCM_24 | SF_ENDIAN_LITTLE;
|
76
|
+
if(type == dlaudio_wav) return SF_FORMAT_WAV | SF_FORMAT_PCM_24;
|
77
|
+
if(type == dlaudio_aiff) return SF_FORMAT_AIFF | SF_FORMAT_PCM_24;
|
78
|
+
THROW("Couldn't detect type");
|
79
|
+
return 0;
|
80
|
+
}
|
81
|
+
|
82
|
+
int wiretap_write_audio_frame(int samples, int rate, int bps, ID type, unsigned char* frame, const char* filename) {
|
83
|
+
const char* error = 0;
|
84
|
+
virtual_file vf = {0, samples*bps/8, frame};
|
85
|
+
SF_VIRTUAL_IO v_io = {v_get_filelen, v_seek, v_read, v_write, v_tell};
|
86
|
+
|
87
|
+
|
88
|
+
SF_INFO info;
|
89
|
+
int item_count = samples;
|
90
|
+
info.frames = item_count;
|
91
|
+
info.samplerate = rate;
|
92
|
+
info.channels = 2;
|
93
|
+
info.format = detect_audio_format(type);
|
94
|
+
SNDFILE *input = sf_open_virtual(&v_io, SFM_READ, &info, &vf);
|
95
|
+
|
96
|
+
if(!input) {
|
97
|
+
THROW("Couldn't open frame for reading");
|
98
|
+
}
|
99
|
+
|
100
|
+
std::auto_ptr<float> output_items(new float[item_count]);
|
101
|
+
int size = sf_read_float(input, output_items.get(), item_count);
|
102
|
+
|
103
|
+
if(size != item_count) {
|
104
|
+
error = sf_strerror(input);
|
105
|
+
}
|
106
|
+
sf_close(input);
|
107
|
+
if(error) {
|
108
|
+
output_items.release();
|
109
|
+
THROW("Waited to read %d frames, got %d: %s", item_count, size, error);
|
110
|
+
}
|
111
|
+
|
112
|
+
SF_INFO out_info = info;
|
113
|
+
out_info.format = SF_FORMAT_AIFF | SF_FORMAT_PCM_16;
|
114
|
+
if(!sf_format_check(&out_info)) {
|
115
|
+
output_items.release();
|
116
|
+
THROW("Invalid format provided for output file");
|
117
|
+
}
|
118
|
+
|
119
|
+
SNDFILE *output = sf_open(filename, SFM_RDWR, &out_info);
|
120
|
+
if(!output) {
|
121
|
+
output_items.release();
|
122
|
+
THROW("Couldn't open file %s for write", filename);
|
123
|
+
}
|
124
|
+
int out_size = sf_write_float(output, output_items.get(), item_count);
|
125
|
+
output_items.release();
|
126
|
+
if(out_size != item_count) {
|
127
|
+
error = sf_strerror(output);
|
128
|
+
}
|
129
|
+
|
130
|
+
sf_close(output);
|
131
|
+
if(error) {
|
132
|
+
THROW("Waited to write %d frames, got %d: %s", item_count, out_size, error);
|
133
|
+
}
|
134
|
+
|
135
|
+
return 0;
|
136
|
+
}
|
137
|
+
|
138
|
+
|
139
|
+
static VALUE wiretap_dump_audio_data(VALUE self, VALUE samples, VALUE rate, VALUE bps, VALUE type, VALUE raw, VALUE filename) {
|
140
|
+
wiretap_write_audio_frame(NUM2INT(samples), NUM2INT(rb_funcall(rate, rb_intern("to_i"), 0)), NUM2INT(bps), SYM2ID(type),
|
141
|
+
(unsigned char* )STR(raw), CSTR(filename));
|
142
|
+
return Qtrue;
|
143
|
+
}
|
144
|
+
|
145
|
+
static VALUE wiretap_get_audio_format(VALUE self, VALUE filename) {
|
146
|
+
Check_Type(filename, T_STRING);
|
147
|
+
|
148
|
+
SF_INFO sfinfo;
|
149
|
+
SNDFILE* snd = sf_open(CSTR(filename), SFM_READ, &sfinfo);
|
150
|
+
|
151
|
+
WireTapAudioFormat audio_format;
|
152
|
+
audio_format.setNumSamples(sfinfo.frames);
|
153
|
+
audio_format.setBitsPerSample(16);
|
154
|
+
audio_format.setSampleRate(sfinfo.samplerate);
|
155
|
+
audio_format.setFrameBufferSize(2*sfinfo.frames);
|
156
|
+
audio_format.setFormatTag("dlaudio_int16_le");
|
157
|
+
sf_close(snd);
|
158
|
+
return Data_Wrap_Struct(cAudioFormat, 0, wiretap_format_free, new WireTapAudioFormat(audio_format));
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE wiretap_audio_import_music(VALUE self, VALUE filename) {
|
162
|
+
Check_Type(filename, T_STRING);
|
163
|
+
|
164
|
+
SF_INFO sfinfo;
|
165
|
+
SNDFILE* snd = sf_open(CSTR(filename), SFM_READ, &sfinfo);
|
166
|
+
|
167
|
+
|
168
|
+
std::auto_ptr<short> frame(new short[sfinfo.frames]);
|
169
|
+
sf_count_t read_frames = sf_read_short(snd, frame.get(), sfinfo.frames);
|
170
|
+
if(read_frames != sfinfo.frames) {
|
171
|
+
rb_warn("Waited to read %lld audio frames, got only %lld", sfinfo.frames, read_frames);
|
172
|
+
sf_close(snd);
|
173
|
+
return Qnil;
|
174
|
+
}
|
175
|
+
sf_close(snd);
|
176
|
+
|
177
|
+
WireTapNodeHandle* node;
|
178
|
+
Data_Get_Struct(self, WireTapNodeHandle, node);
|
179
|
+
NODERUN_E(node, node->setNumFrames(1));
|
180
|
+
NODERUN_E(node, node->writeFrame(0, frame.get(), sfinfo.frames*2));
|
181
|
+
return self;
|
182
|
+
}
|
183
|
+
|
184
|
+
/* This is called on node. Not on NodeFrames */
|
185
|
+
|
186
|
+
static VALUE wiretap_audio_dump(VALUE self, VALUE file) {
|
187
|
+
WireTapNodeHandle* node;
|
188
|
+
Data_Get_Struct(self, WireTapNodeHandle, node);
|
189
|
+
|
190
|
+
WireTapAudioFormat format;
|
191
|
+
RUN(node->getClipFormat(format));
|
192
|
+
|
193
|
+
int num;
|
194
|
+
NODERUN_E(node, node->getNumFrames(num));
|
195
|
+
if(num <= 0) {
|
196
|
+
rb_warn("No frames in the audio stream");
|
197
|
+
return Qnil;
|
198
|
+
}
|
199
|
+
|
200
|
+
std::auto_ptr<unsigned char> frame(new unsigned char[format.frameBufferSize() * num]);
|
201
|
+
for(int i = 0; i < num; i++) {
|
202
|
+
if(!node->readFrame(i, frame.get() + i*format.frameBufferSize(), format.frameBufferSize())) {
|
203
|
+
frame.release();
|
204
|
+
NODERUN_E(node, false);
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
wiretap_write_audio_frame(format.numSamples(), int(format.sampleRate()),
|
209
|
+
format.bitsPerSample(), rb_intern(format.formatTag()), frame.get(), CSTR(file));
|
210
|
+
return self;
|
211
|
+
}
|
212
|
+
|
213
|
+
#endif /* HAVE_SNDFILE_H */
|
214
|
+
|
215
|
+
|
216
|
+
void Init_audio_format() {
|
217
|
+
#ifdef HAVE_SNDFILE_H
|
218
|
+
rb_define_singleton_method(mWiretap, "dump_audio_data", VALUEFUNC(wiretap_dump_audio_data), 6);
|
219
|
+
rb_define_singleton_method(mWiretap, "audio_format", VALUEFUNC(wiretap_get_audio_format), 1);
|
220
|
+
|
221
|
+
rb_define_method(cAudio, "import_music", VALUEFUNC(wiretap_audio_import_music), 1);
|
222
|
+
rb_define_method(cAudio, "dump", VALUEFUNC(wiretap_audio_dump), 1);
|
223
|
+
#endif /* HAVE_SNDFILE_H */
|
224
|
+
}
|
data/ext/bmp.cpp
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#include "wiretap.h"
|
2
|
+
static void write_int32_le_value(int value, bitstream_writer writer, void *data) {
|
3
|
+
writer(data, value >> 0 & 0xFF);
|
4
|
+
writer(data, value >> 8 & 0xFF);
|
5
|
+
writer(data, value >> 16& 0xFF);
|
6
|
+
writer(data, value >> 24& 0xFF);
|
7
|
+
}
|
8
|
+
|
9
|
+
static void write_int16_le_value(short value, bitstream_writer writer, void *data) {
|
10
|
+
writer(data, value >> 0 & 0xFF);
|
11
|
+
writer(data, value >> 8 & 0xFF);
|
12
|
+
}
|
13
|
+
|
14
|
+
void write_string_value(char* value, bitstream_writer writer, void *data) {
|
15
|
+
while(value && *value) {
|
16
|
+
writer(data, *value);
|
17
|
+
value++;
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
static int wiretap_write_bmp_header(int width, int height, bitstream_writer writer, void *data) {
|
23
|
+
const int header_size = 54;
|
24
|
+
int size = header_size + width * height * 3;
|
25
|
+
write_string_value("BM", writer, data); // 0,1
|
26
|
+
write_int32_le_value(size, writer, data); // 2,3,4,5
|
27
|
+
write_int32_le_value(0, writer, data); // 6,7,8,9: reserved data
|
28
|
+
write_int32_le_value(header_size, writer, data); // 10,11,12,13: Image header ends.
|
29
|
+
write_int32_le_value(40, writer, data); // 14,15,16,17: Image information size
|
30
|
+
write_int32_le_value(width, writer, data); // 18,19,20,21: Width
|
31
|
+
write_int32_le_value(height, writer, data); // 22,23,24,25: Height
|
32
|
+
write_int16_le_value(1, writer, data); // 26,27: Number of color planes
|
33
|
+
write_int16_le_value(24, writer, data); // 28,29: Bits per pixel. We write only 24 bit images
|
34
|
+
write_int32_le_value(0, writer, data); // 30,31,32,33: Compression schema. None
|
35
|
+
write_int32_le_value(width*height*3, writer, data); // 34,35,36,37: raw data size. 3 bytes per pixel.
|
36
|
+
write_int32_le_value(2834, writer, data); // 38,39,40,41: horisontal resolution. Perhaprs 72 dpi. I don't know
|
37
|
+
write_int32_le_value(2834, writer, data); // 42,43,44,45: vertical resolution
|
38
|
+
write_int32_le_value(0, writer, data); // 46,47,48,49: number of colors
|
39
|
+
write_int32_le_value(0, writer, data); // 50,51,52,53: number of important colors
|
40
|
+
return 0;
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
bool wiretap_write_frame_bmp(int width, int height, int bpp, unsigned char* frame, FILE* f) {
|
46
|
+
filestream stream;
|
47
|
+
memset(&stream, 0, sizeof(stream));
|
48
|
+
stream.f = f;
|
49
|
+
|
50
|
+
wiretap_write_bmp_header(width, height, write_to_file, (void *)&stream);
|
51
|
+
wiretap_write_image_data(width, height, bpp, frame, write_to_file_bgr, (void *)&stream);
|
52
|
+
|
53
|
+
return 0;
|
54
|
+
}
|
55
|
+
|
56
|
+
void write_to_file_bgr(void *stream, unsigned char channel) {
|
57
|
+
filestream* data = (filestream *)stream;
|
58
|
+
data->buffer[2 - data->count] = channel;
|
59
|
+
data->count++;
|
60
|
+
if(data->count == 3) {
|
61
|
+
fwrite(data->buffer, sizeof(data->buffer), 1, data->f);
|
62
|
+
data->count = 0;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "mkmf"
|
4
|
+
require 'optparse'
|
5
|
+
CONFIG["CPP"] = "g++ -E "
|
6
|
+
CONFIG["CC"] = "g++ "
|
7
|
+
CONFIG["LDSHARED"].gsub!(/^cc /,"g++ ")
|
8
|
+
|
9
|
+
#@wiretap_placements = [ "../../wiretap_api", "/Code/wiretap-api"]
|
10
|
+
@wiretap_placements = []
|
11
|
+
|
12
|
+
@includes = []
|
13
|
+
@libraries = []
|
14
|
+
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
opts.on("-S PATH", "--sndfile-dir=PATH", "Prefix, where libsndfile is installed: /usr/local or /opt/local") do |path|
|
17
|
+
@libraries << path + "/lib"
|
18
|
+
@includes << path + "/include"
|
19
|
+
end
|
20
|
+
opts.on("-W PATH", "--wiretap-dir=PATH", "Specify path to wiretap api placement: /Code/wiretap-api") do |path|
|
21
|
+
@wiretap_placements.unshift(path)
|
22
|
+
end
|
23
|
+
opts.parse!(ARGV.include?("--") ? ARGV[ARGV.index("--")+1..-1] : ARGV.clone)
|
24
|
+
end
|
25
|
+
|
26
|
+
def locations(suffix)
|
27
|
+
@wiretap_placements.map {|place| place + suffix}
|
28
|
+
end
|
29
|
+
|
30
|
+
def library_path
|
31
|
+
case PLATFORM
|
32
|
+
when /linux/
|
33
|
+
"LINUX/i686/RHEL4/GCC_3_4_4"
|
34
|
+
when /darwin/
|
35
|
+
"MACOSX/fat/Darwin_8_3_0/GCC_4_0_1/"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def old_library_path
|
40
|
+
case PLATFORM
|
41
|
+
when /linux/
|
42
|
+
"Linux/i686/RedHat/40/gcc_3.4.4/dbg/"
|
43
|
+
when /darwin/
|
44
|
+
"Mac/OSX/gcc_3.3/dbg"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def include_locations
|
49
|
+
locations("/api") + @includes
|
50
|
+
end
|
51
|
+
|
52
|
+
def library_locations
|
53
|
+
locations("/lib/dbg/"+library_path) + locations("/libs/"+old_library_path) + @libraries
|
54
|
+
end
|
55
|
+
|
56
|
+
def clear_locations(locations)
|
57
|
+
locations.reject {|location| !File.exists?(location)}
|
58
|
+
end
|
59
|
+
|
60
|
+
def include_flags
|
61
|
+
" "+(clear_locations(include_locations).map { |place| "-I"+place} + ["-Wall"]).join(" ")
|
62
|
+
end
|
63
|
+
def library_flags
|
64
|
+
" " + (clear_locations(library_locations) || []).map { |place| "-L"+place}.join(" ")
|
65
|
+
end
|
66
|
+
|
67
|
+
$CFLAGS << include_flags
|
68
|
+
$LDFLAGS << library_flags
|
69
|
+
|
70
|
+
have_header "WireTapClientAPI.h"
|
71
|
+
unless have_header("sndfile.h") && have_library("sndfile")
|
72
|
+
puts "*********************"
|
73
|
+
puts "You don't have libsndfile installed. You can use wiretap ruby binding without it,"
|
74
|
+
puts "but You will not have support of audio."
|
75
|
+
puts "If You install libsndfile, reinstall gem after it."
|
76
|
+
end
|
77
|
+
have_library "wiretapClientAPI", "WireTapClientInit" do <<-SRC
|
78
|
+
#include <WireTapClientAPI.h>
|
79
|
+
int main(void) {
|
80
|
+
WireTapClientInit();
|
81
|
+
}
|
82
|
+
SRC
|
83
|
+
end
|
84
|
+
create_makefile "wiretap_bin"
|
85
|
+
|