wiretap 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/LICENSE +32 -0
  2. data/README +93 -0
  3. data/ext/Makefile +146 -0
  4. data/ext/audio_format.cpp +224 -0
  5. data/ext/bmp.cpp +65 -0
  6. data/ext/extconf.rb +85 -0
  7. data/ext/format.cpp +347 -0
  8. data/ext/image.h +27 -0
  9. data/ext/image_format.cpp +194 -0
  10. data/ext/node.cpp +401 -0
  11. data/ext/nodechildren.cpp +67 -0
  12. data/ext/nodeframes.cpp +233 -0
  13. data/ext/nodemetadata.cpp +90 -0
  14. data/ext/ppm.cpp +132 -0
  15. data/ext/server.cpp +202 -0
  16. data/ext/serverlist.cpp +183 -0
  17. data/ext/sgi.cpp +69 -0
  18. data/ext/testserver/Makefile +5 -0
  19. data/ext/testserver/cfg/wiretap_path_translation_db.xml +44 -0
  20. data/ext/testserver/cfg/wiretapd.cfg +74 -0
  21. data/ext/testserver/cfg/wiretapd.res +60 -0
  22. data/ext/testserver/db.sql +50 -0
  23. data/ext/testserver/server.cpp +206 -0
  24. data/ext/testserver/testserver.rb +146 -0
  25. data/ext/thread_worker.cpp +85 -0
  26. data/ext/wiretap.cpp +68 -0
  27. data/ext/wiretap.h +115 -0
  28. data/lib/wiretap.rb +280 -0
  29. data/test/audio.rb +27 -0
  30. data/test/convert.rb +35 -0
  31. data/test/image.rb +101 -0
  32. data/test/read_frames.rb +142 -0
  33. data/test/wiretap-images/01.ppm +0 -0
  34. data/test/wiretap-images/32bit.stoneimage +621 -0
  35. data/test/wiretap-images/36bit.stoneimage +1036 -0
  36. data/test/wiretap-images/48bit.stoneimage +800 -1
  37. data/test/wiretap-images/a.stoneimage +0 -0
  38. data/test/wiretap-images/a0.stoneimage +0 -0
  39. data/test/wiretap-images/a1.stoneimage +0 -0
  40. data/test/wiretap-images/a2.stoneimage +0 -0
  41. data/test/wiretap-images/a3.stoneimage +0 -0
  42. data/test/wiretap-images/a4.stoneimage +0 -0
  43. data/test/wiretap-images/b1.stonesound +0 -0
  44. data/test/wiretap-images/importable-seq/00000001.ppm +0 -0
  45. data/test/wiretap-images/importable-seq/00000002.ppm +0 -0
  46. data/test/wiretap-images/importable-seq/00000003.ppm +0 -0
  47. data/test/wiretap-images/importable-seq/00000004.ppm +0 -0
  48. data/test/wiretap-images/importable-seq/00000005.ppm +0 -0
  49. data/test/wiretap-images/importable-seq/00000006.ppm +0 -0
  50. data/test/wiretap-images/importable-seq/00000007.ppm +0 -0
  51. data/test/wiretap-images/importable-seq/00000008.ppm +0 -0
  52. data/test/wiretap-images/importable-seq/00000009.ppm +0 -0
  53. data/test/wiretap-images/importable-seq/00000010.ppm +0 -0
  54. data/test/wiretap-images/importable-seq/00000011.ppm +0 -0
  55. data/test/wiretap-images/importable-seq/00000012.ppm +0 -0
  56. data/test/wiretap-images/monsters_001.tif +0 -0
  57. data/test/wiretap-images/monsters_002.tif +0 -0
  58. data/test/wiretap-images/monsters_003.tif +0 -0
  59. data/test/wiretap-images/output.mov +0 -0
  60. data/test/wiretap-images/output.wav +0 -0
  61. data/test/write_frames.rb +82 -0
  62. 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
+