ruby-shout 2.2.0 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +70 -4
- data/Rakefile +13 -7
- data/VERSION +1 -1
- data/ext/extconf.rb +11 -2
- data/ext/{shout.c → shout_ext.c} +97 -25
- data/lib/shout.rb +55 -0
- metadata +27 -43
- data/test/integration-test.rb +0 -90
data/README.textile
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
h1. Ruby-Shout
|
2
2
|
|
3
|
+
h2. Compatibility note
|
4
|
+
|
5
|
+
If you have installed a previous version of ruby-shout you have to make shure the shout.o files aren't there any more. Otherwise the build will fail.
|
6
|
+
|
3
7
|
h2. Purpose
|
4
8
|
|
5
9
|
ruby-shout lets you send compressed audio over the network to an "Icecast":http://www.icecast.org/ streaming media server.
|
@@ -16,11 +20,73 @@ h2. Usage
|
|
16
20
|
|
17
21
|
See example.rb. Run it like
|
18
22
|
|
19
|
-
|
23
|
+
<pre><code>./example.rb spec/test.mp3
|
24
|
+
</code></pre>
|
25
|
+
|
26
|
+
h2. Ruby 1.9 and encoding
|
27
|
+
|
28
|
+
Ruby 1.9 features really good encoding support: Each string has it's own explicit encoding. The default encoding for Icecast is ISO-8859-1 for station data and meta data.
|
29
|
+
|
30
|
+
In order to make ruby-shout play nice with ruby 1.9 I added a Shout#charset setter and all string accessors for station data are wrapped:
|
31
|
+
|
32
|
+
* setters convert the given string to the given charset
|
33
|
+
* and store the original string, available under #original_..., for example #original_description. This is done because converting may alter your string (characters incompatible with conversion are just swallowed). That way you are able to get your original string back (should you need it) and the getter is enabled to:
|
34
|
+
* getters convert the value back to the original encoding, determined by the #original_... method.
|
35
|
+
|
36
|
+
The idea is: We want to guaranty that strings keep their encoding when assigning them via a Shout accessor. In case strings are not compatible with Icecasts charset we want to degrade as gracefully as possible. IMHO just dropping incompatible characters does this best (when being listed in an external YP directory these "???br?" things just look awful). If you want to make sure this doesn't happen you have to compare the value before and after assigning it (or just compare for example #description with #original_description).
|
37
|
+
|
38
|
+
h3. Synopsis:
|
39
|
+
|
40
|
+
<pre><code>s = Shout.new
|
41
|
+
s.charset = 'UTF-8'
|
42
|
+
s.description = 'dikşîne MUSłϾ'
|
43
|
+
puts s.description # => 'dikşîne MUSłϾ'
|
44
|
+
|
45
|
+
s = Shout.new
|
46
|
+
s.charset = 'ISO-8859-1' # this is the default
|
47
|
+
s.description = 'dikşîne MUSłϾ'
|
48
|
+
puts s.description # => 'dikîne MUSłϾ'
|
49
|
+
puts s.original_description # => 'dikşîne MUSłϾ'
|
50
|
+
</code></pre>
|
51
|
+
|
52
|
+
h3. Icecast charset config
|
53
|
+
|
54
|
+
If you use s/th else than ISO-8859-1 you should configure your icecast accordingly: In the mount section set the charset:
|
55
|
+
|
56
|
+
<pre><code><mount>
|
57
|
+
<mount-name>/your_station</mount-name>
|
58
|
+
<charset>UTF-8</charset>
|
59
|
+
...
|
60
|
+
</mount>
|
61
|
+
</code></pre>
|
62
|
+
|
63
|
+
or (in the latest icecast builds)
|
64
|
+
|
65
|
+
<pre><code><mount>
|
66
|
+
<mount-name>/*</mount-name>
|
67
|
+
<charset>UTF-8</charset>
|
68
|
+
...
|
69
|
+
</mount>
|
70
|
+
</code></pre>
|
71
|
+
|
72
|
+
to set UTF-8 for all mountpoints.
|
73
|
+
|
74
|
+
h2. Running the spec
|
75
|
+
|
76
|
+
h3. General note: use rake spec:build
|
77
|
+
|
78
|
+
Before each run you have to run the build specs first as the other specs use its output (the built gem).
|
79
|
+
|
80
|
+
<pre><code>rake spec:build && rake spec
|
81
|
+
</code></pre>
|
82
|
+
|
83
|
+
h3. For the integration spec
|
84
|
+
|
85
|
+
You need to have an icecast server running. Perhaps you want to adopt the server setting quite at the top of the intergration_spec.rb
|
20
86
|
|
21
87
|
h2. Todo
|
22
88
|
|
23
|
-
* proper unit tests (blush)
|
89
|
+
* proper unit tests (blush) ; working on that
|
24
90
|
|
25
91
|
h2. History & Credits
|
26
92
|
|
@@ -35,9 +101,9 @@ h2. Recent Changes
|
|
35
101
|
* Included the "ruby 1.9 patch":http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/dev-ruby/ruby-shout/files/ruby-shout-2.1%2Bruby-1.9.patch?revision=1.1&view=markup although it seems to have "some issues":http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/dev-ruby/ruby-shout/files/ruby-shout-2.1%2Bruby-1.9.patch?view=log. I hope to have fixed the issues with this:
|
36
102
|
* Replaced STR2CSTR for StringValuePtr as STR2CSTR doesn't work for 1.9 any more
|
37
103
|
* Added format = Shout::MP3 to the example as this is absolutely needed by the latest versions of libshout.
|
38
|
-
* Added
|
104
|
+
* Added a build test which builds and installs the gem and an integration test that plays some sound on a local icecast server. Be sure to adopt the server setting before running. I mainly did that because the old version of ruby-shout didn't even compile for ruby 1.9.
|
39
105
|
|
40
|
-
|
106
|
+
* Added Ruby 1.9 encoding support.
|
41
107
|
|
42
108
|
h2. State
|
43
109
|
|
data/Rakefile
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake/gempackagetask'
|
3
|
+
require 'spec/rake/spectask'
|
3
4
|
|
4
|
-
|
5
|
+
desc "Run spec with specdoc output"
|
6
|
+
Spec::Rake::SpecTask.new do |t|
|
7
|
+
spec_files = Dir.glob('spec/*_spec.rb')
|
8
|
+
spec_files.delete 'spec/build_spec.rb'
|
9
|
+
t.spec_files = spec_files
|
10
|
+
t.spec_opts << '--format specdoc -c'
|
11
|
+
end
|
5
12
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
13
|
+
desc "Run the build spec"
|
14
|
+
Spec::Rake::SpecTask.new 'spec:build' do |t|
|
15
|
+
t.spec_files = ['spec/build_spec.rb']
|
16
|
+
t.spec_opts << '--format specdoc -c'
|
11
17
|
end
|
12
18
|
|
13
19
|
begin
|
@@ -21,7 +27,7 @@ begin
|
|
21
27
|
s.authors = ["Jared Jennings", "Niko Dittmann"]
|
22
28
|
s.require_paths = ["lib"]
|
23
29
|
s.rubyforge_project = 'ruby-shout'
|
24
|
-
s.files = FileList["[A-Z]*", "{ext}/*"]
|
30
|
+
s.files = FileList["[A-Z]*", "{ext}/*", "{lib}/**/*"]
|
25
31
|
|
26
32
|
end
|
27
33
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.2.
|
1
|
+
2.2.1
|
data/ext/extconf.rb
CHANGED
@@ -1,11 +1,20 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
+
case
|
4
|
+
when RUBY_VERSION >= '1.9' then $CFLAGS += ' -DRUBY_1_9_x'
|
5
|
+
when RUBY_VERSION < '1.9' then $CFLAGS += ' -DRUBY_1_8_x'
|
6
|
+
end
|
7
|
+
|
8
|
+
if have_func('rb_thread_blocking_region')
|
9
|
+
$CFLAGS += " -DHAVE_RB_THREAD_BLOCKING_REGION"
|
10
|
+
end
|
11
|
+
|
3
12
|
dir_config("shout")
|
4
13
|
have_library("ogg", "oggpack_writeinit")
|
5
14
|
have_library("vorbis", "vorbis_dsp_clear")
|
6
15
|
have_library("pthread", "pthread_create")
|
7
16
|
if find_library("shout", "shout_init","/usr","/usr/local") and have_header("shout/shout.h")
|
8
|
-
|
17
|
+
create_makefile("shout_ext")
|
9
18
|
else
|
10
|
-
|
19
|
+
print "*** ERROR: need to have libshout and shout/shout.h to compile this module\n"
|
11
20
|
end
|
data/ext/{shout.c → shout_ext.c}
RENAMED
@@ -42,8 +42,8 @@
|
|
42
42
|
#define DEFAULT_MOUNTPOINT "/default"
|
43
43
|
|
44
44
|
#ifndef RSTRING_LEN
|
45
|
-
#define RSTRING_LEN(str)
|
46
|
-
#define RSTRING_PTR(str)
|
45
|
+
#define RSTRING_LEN(str) RSTRING(str)->len
|
46
|
+
#define RSTRING_PTR(str) RSTRING(str)->ptr
|
47
47
|
#endif
|
48
48
|
|
49
49
|
/*
|
@@ -74,10 +74,11 @@ static void Init_shout_error() {
|
|
74
74
|
INT2NUM(SHOUTERR_MALLOC));
|
75
75
|
rb_define_const(cShoutError, "METADATA",
|
76
76
|
INT2NUM(SHOUTERR_METADATA));
|
77
|
-
|
78
|
-
|
77
|
+
rb_define_const(cShoutError, "BUSY",
|
78
|
+
INT2NUM(SHOUTERR_BUSY));
|
79
79
|
}
|
80
80
|
|
81
|
+
|
81
82
|
static void raise_shout_error(shout_t *conn) {
|
82
83
|
rb_raise(cShoutError, "%d: %s", shout_get_errno(conn),
|
83
84
|
shout_get_error(conn));
|
@@ -87,7 +88,7 @@ static void raise_shout_error(shout_t *conn) {
|
|
87
88
|
* use shout_get_errno or shout_get_error on them.
|
88
89
|
*/
|
89
90
|
static void raise_nonspecific_shout_error(int errno) {
|
90
|
-
|
91
|
+
rb_raise(cShoutError, "%d", errno);
|
91
92
|
}
|
92
93
|
|
93
94
|
/*
|
@@ -117,7 +118,7 @@ static VALUE _sh_metadata_add(VALUE self, VALUE name, VALUE value) {
|
|
117
118
|
err = shout_metadata_add(m, StringValuePtr(name), StringValuePtr(value));
|
118
119
|
|
119
120
|
if(err != SHOUTERR_SUCCESS) {
|
120
|
-
|
121
|
+
raise_nonspecific_shout_error(err);
|
121
122
|
}
|
122
123
|
|
123
124
|
return value;
|
@@ -201,6 +202,17 @@ static VALUE _sh_connect(VALUE self) {
|
|
201
202
|
return Qtrue;
|
202
203
|
}
|
203
204
|
|
205
|
+
|
206
|
+
#if HAVE_RB_THREAD_BLOCKING_REGION
|
207
|
+
/* The new _sh_connect_non_blocking function (aka #connect_non_blocking method)
|
208
|
+
* wrapping _sh_connect in a rb_thread_blocking_region call.
|
209
|
+
*/
|
210
|
+
static VALUE _sh_connect_non_blocking(VALUE self) {
|
211
|
+
return rb_thread_blocking_region(_sh_connect, self, RUBY_UBF_IO, NULL);
|
212
|
+
}
|
213
|
+
#endif
|
214
|
+
|
215
|
+
|
204
216
|
/* Disconnect from the server. */
|
205
217
|
static VALUE _sh_disconnect(VALUE self) {
|
206
218
|
int err;
|
@@ -214,22 +226,22 @@ static VALUE _sh_disconnect(VALUE self) {
|
|
214
226
|
return Qtrue;
|
215
227
|
}
|
216
228
|
|
217
|
-
/* Returns true if connected, false otherwise,
|
218
|
-
* nil if something really crazy happened.
|
229
|
+
/* Returns true if connected, false otherwise,
|
230
|
+
* nil if something really crazy happened.
|
219
231
|
*/
|
220
232
|
static VALUE _sh_connectedp(VALUE self) {
|
221
|
-
|
222
|
-
|
223
|
-
|
233
|
+
int err;
|
234
|
+
shout_connection *s;
|
235
|
+
GET_SC(self, s);
|
224
236
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
237
|
+
err = shout_get_connected(s->conn);
|
238
|
+
if(err == SHOUTERR_CONNECTED) {
|
239
|
+
return Qtrue;
|
240
|
+
} else if(err == SHOUTERR_UNCONNECTED) {
|
241
|
+
return Qfalse;
|
242
|
+
} else {
|
243
|
+
return Qnil;
|
244
|
+
}
|
233
245
|
}
|
234
246
|
|
235
247
|
/* Send some data. to_send is a String containing the data to send. */
|
@@ -247,6 +259,33 @@ static VALUE _sh_send(VALUE self, VALUE to_send) {
|
|
247
259
|
return Qtrue;
|
248
260
|
}
|
249
261
|
|
262
|
+
|
263
|
+
#if HAVE_RB_THREAD_BLOCKING_REGION
|
264
|
+
/* The struct into which the arguments of _sh_send get packed
|
265
|
+
* to be able to wrap _sh_send in a rb_thread_blocking_region call. */
|
266
|
+
typedef struct {
|
267
|
+
VALUE *self;
|
268
|
+
unsigned char *to_send;
|
269
|
+
} SHOUT_SEND_ARGS;
|
270
|
+
|
271
|
+
/* The function to unpack the arguments out of the struct after
|
272
|
+
* having been wrapped in the rb_thread_blocking_region call. */
|
273
|
+
static VALUE _sh_send_non_block_unpack(SHOUT_SEND_ARGS *send_args) {
|
274
|
+
return _sh_send(send_args->self, send_args->to_send);
|
275
|
+
}
|
276
|
+
|
277
|
+
/* The new _sh_send_non_blocking function (aka #send_non_blocking method)
|
278
|
+
* packing the arguments of _sh_send in a struct and wrapping the _sh_send
|
279
|
+
* call into a rb_thread_blocking_region call. */
|
280
|
+
static VALUE _sh_send_non_blocking(VALUE self, VALUE to_send) {
|
281
|
+
SHOUT_SEND_ARGS send_args;
|
282
|
+
send_args.self = self;
|
283
|
+
send_args.to_send = (unsigned char *) to_send;
|
284
|
+
return rb_thread_blocking_region(_sh_send_non_block_unpack, &send_args, RUBY_UBF_IO, NULL);
|
285
|
+
}
|
286
|
+
#endif
|
287
|
+
|
288
|
+
|
250
289
|
/* Sleep the necessary amount of time to play back the audio data sent since
|
251
290
|
* the last call to #sync. After calling this, it's time to send more data. */
|
252
291
|
static VALUE _sh_sync(VALUE self) {
|
@@ -398,6 +437,15 @@ VALUE _sh_description(VALUE self) {
|
|
398
437
|
return rb_str_new2(value);
|
399
438
|
}
|
400
439
|
|
440
|
+
VALUE _sh_bitrate(VALUE self) {
|
441
|
+
const char *value;
|
442
|
+
|
443
|
+
shout_connection *s; GET_SC(self, s);
|
444
|
+
|
445
|
+
value = shout_get_audio_info(s->conn, SHOUT_AI_BITRATE);
|
446
|
+
return rb_str_new2(value);
|
447
|
+
}
|
448
|
+
|
401
449
|
/* Unimplemented: audio_info */
|
402
450
|
|
403
451
|
/* audio_info and metadata should both be objects that always exist, and have
|
@@ -623,13 +671,25 @@ VALUE _sh_metadata_eq(VALUE self, VALUE meta) {
|
|
623
671
|
return meta;
|
624
672
|
}
|
625
673
|
|
674
|
+
/* Set the 'bitrate' in the audio_info of the stream. */
|
675
|
+
VALUE _sh_bitrate_eq(VALUE self, VALUE value) {
|
676
|
+
int err;
|
677
|
+
shout_connection *s; GET_SC(self, s);
|
678
|
+
|
679
|
+
Check_Type(value, T_STRING);
|
680
|
+
err = shout_set_audio_info(s->conn, SHOUT_AI_BITRATE, RSTRING_PTR(value));
|
681
|
+
if(err != SHOUTERR_SUCCESS) {
|
682
|
+
raise_shout_error(s->conn);
|
683
|
+
}
|
684
|
+
return value;
|
685
|
+
}
|
626
686
|
|
627
687
|
|
628
688
|
/*
|
629
689
|
----------------------------------------------------------------
|
630
690
|
*/
|
631
691
|
|
632
|
-
void
|
692
|
+
void Init_shout_ext()
|
633
693
|
{
|
634
694
|
cShout = rb_define_class("Shout", rb_cObject);
|
635
695
|
|
@@ -640,12 +700,22 @@ void Init_shout()
|
|
640
700
|
|
641
701
|
rb_define_method(cShout, "initialize", _sh_initialize, -1);
|
642
702
|
rb_define_method(cShout, "connect", _sh_connect, 0);
|
703
|
+
|
704
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
705
|
+
rb_define_method(cShout, "connect_non_blocking", _sh_connect_non_blocking, 0);
|
706
|
+
#endif
|
707
|
+
|
643
708
|
rb_define_method(cShout, "open", _sh_connect, 0);
|
644
709
|
rb_define_method(cShout, "disconnect", _sh_disconnect, 0);
|
645
710
|
rb_define_method(cShout, "close", _sh_disconnect, 0);
|
646
|
-
|
711
|
+
rb_define_method(cShout, "connected?", _sh_connectedp, 0);
|
647
712
|
|
648
713
|
rb_define_method(cShout, "send", _sh_send, 1);
|
714
|
+
|
715
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
716
|
+
rb_define_method(cShout, "send_non_blocking", _sh_send_non_blocking, 1);
|
717
|
+
#endif
|
718
|
+
|
649
719
|
rb_define_method(cShout, "sync", _sh_sync, 0);
|
650
720
|
rb_define_method(cShout, "delay", _sh_delay, 0);
|
651
721
|
|
@@ -667,7 +737,8 @@ void Init_shout()
|
|
667
737
|
rb_define_method(cShout, "url", _sh_url, 0);
|
668
738
|
rb_define_method(cShout, "genre", _sh_genre, 0);
|
669
739
|
rb_define_method(cShout, "description",_sh_description,0);
|
670
|
-
|
740
|
+
rb_define_method(cShout, "bitrate", _sh_bitrate, 0);
|
741
|
+
/* metadata getting is still unsupported. */
|
671
742
|
/* audio info thingy. */
|
672
743
|
/* leave for version 2.2 */
|
673
744
|
|
@@ -690,10 +761,11 @@ void Init_shout()
|
|
690
761
|
rb_define_method(cShout, "genre=", _sh_genre_eq, 1);
|
691
762
|
rb_define_method(cShout, "description=", _sh_description_eq,1);
|
692
763
|
rb_define_method(cShout, "metadata=", _sh_metadata_eq, 1);
|
764
|
+
rb_define_method(cShout, "bitrate=", _sh_bitrate_eq, 1);
|
693
765
|
|
694
|
-
|
695
|
-
|
696
|
-
|
766
|
+
rb_define_const(cShout, "HTTP", INT2FIX(SHOUT_PROTOCOL_HTTP));
|
767
|
+
rb_define_const(cShout, "XAUDIOCAST", INT2FIX(SHOUT_PROTOCOL_XAUDIOCAST));
|
768
|
+
rb_define_const(cShout, "ICY", INT2FIX(SHOUT_PROTOCOL_ICY));
|
697
769
|
|
698
770
|
rb_define_const(cShout, "MP3", INT2FIX(SHOUT_FORMAT_MP3));
|
699
771
|
rb_define_const(cShout, "OGG", INT2FIX(SHOUT_FORMAT_OGG));
|
data/lib/shout.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
2
|
+
require 'shout_ext'
|
3
|
+
|
4
|
+
class Shout
|
5
|
+
attr_writer :charset
|
6
|
+
|
7
|
+
INT_ACCESSORS = :port, :format
|
8
|
+
STRING_ACCESSORS = :host, :user, :username, :pass, :password, :protocol, :mount, :dumpfile,
|
9
|
+
:agent, :user_agent, :public, :name, :url, :genre, :description, :bitrate
|
10
|
+
|
11
|
+
alias :ext_initialize :initialize
|
12
|
+
def initialize(opts={})
|
13
|
+
ext_initialize
|
14
|
+
|
15
|
+
(STRING_ACCESSORS + INT_ACCESSORS + [:charset]).each do |a|
|
16
|
+
self.__send__ :"#{a}=", opts[a] if opts[a]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
STRING_ACCESSORS.each do |accessor|
|
21
|
+
attr_accessor :"original_#{accessor}"
|
22
|
+
|
23
|
+
alias :"raw_#{accessor}" :"#{accessor}"
|
24
|
+
define_method accessor do
|
25
|
+
return nil unless orig_acc = self.__send__("original_#{accessor}")
|
26
|
+
|
27
|
+
decode self.__send__(:"raw_#{accessor}"), orig_acc
|
28
|
+
end
|
29
|
+
|
30
|
+
alias :"raw_#{accessor}=" :"#{accessor}="
|
31
|
+
define_method :"#{accessor}=" do |value|
|
32
|
+
self.__send__ "original_#{accessor}=", value
|
33
|
+
|
34
|
+
self.__send__ :"raw_#{accessor}=", encode(value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def charset
|
39
|
+
@charset || ((format && format==Shout::MP3) ? 'ISO-8859-1' : 'UTF-8')
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def encode(s)
|
44
|
+
return s unless s.is_a? String
|
45
|
+
|
46
|
+
s.encode(charset, :invalid => :replace, :undef => :replace, :replace => '')
|
47
|
+
end
|
48
|
+
def decode(s, orig_string)
|
49
|
+
return s unless s.is_a? String
|
50
|
+
|
51
|
+
orig_charset = orig_string.encoding.name
|
52
|
+
s.encode(orig_charset, charset, :invalid => :replace, :undef => :replace, :replace => '')
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
metadata
CHANGED
@@ -1,70 +1,54 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-shout
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 2
|
7
|
-
- 2
|
8
|
-
- 0
|
9
|
-
version: 2.2.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.1
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Jared Jennings
|
13
9
|
- Niko Dittmann
|
14
10
|
autorequire:
|
15
11
|
bindir: bin
|
16
12
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2010-09-05 00:00:00 +02:00
|
19
|
-
default_executable:
|
13
|
+
date: 2011-11-15 00:00:00.000000000Z
|
20
14
|
dependencies: []
|
21
|
-
|
22
|
-
|
15
|
+
description: Ruby bindings for libshout 2, a "Library which can be used to write a
|
16
|
+
source client like ices" for Icecast (http://www.icecast.org/download.php).
|
23
17
|
email: mail@niko-dittmann.com
|
24
18
|
executables: []
|
25
|
-
|
26
|
-
extensions:
|
19
|
+
extensions:
|
27
20
|
- ext/extconf.rb
|
28
|
-
extra_rdoc_files:
|
21
|
+
extra_rdoc_files:
|
29
22
|
- README.textile
|
30
|
-
files:
|
23
|
+
files:
|
31
24
|
- README.textile
|
32
25
|
- Rakefile
|
33
26
|
- VERSION
|
34
27
|
- ext/extconf.rb
|
35
|
-
- ext/
|
36
|
-
-
|
37
|
-
has_rdoc: true
|
28
|
+
- ext/shout_ext.c
|
29
|
+
- lib/shout.rb
|
38
30
|
homepage: http://github.com/niko/ruby-shout
|
39
31
|
licenses: []
|
40
|
-
|
41
32
|
post_install_message:
|
42
|
-
rdoc_options:
|
43
|
-
|
44
|
-
require_paths:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
45
35
|
- lib
|
46
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
37
|
none: false
|
48
|
-
requirements:
|
49
|
-
- -
|
50
|
-
- !ruby/object:Gem::Version
|
51
|
-
|
52
|
-
|
53
|
-
version: "0"
|
54
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
43
|
none: false
|
56
|
-
requirements:
|
57
|
-
- -
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
|
60
|
-
- 0
|
61
|
-
version: "0"
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
62
48
|
requirements: []
|
63
|
-
|
64
49
|
rubyforge_project: ruby-shout
|
65
|
-
rubygems_version: 1.
|
50
|
+
rubygems_version: 1.8.10
|
66
51
|
signing_key:
|
67
52
|
specification_version: 3
|
68
53
|
summary: Send audio over the network to an Icecast server
|
69
|
-
test_files:
|
70
|
-
- test/integration-test.rb
|
54
|
+
test_files: []
|
data/test/integration-test.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
# This test builds the gem (there where build errors on 1.9 without the patch),
|
2
|
-
# installs it and starts a station on mountpoint /test.
|
3
|
-
# You should have an icecast-server listening on 8000 (that's the default)
|
4
|
-
# for incoming source connections.
|
5
|
-
# Point your radio client to http://localhost:8000/test.
|
6
|
-
# Look for the metadata being correctly set ('gromozek - melange').
|
7
|
-
|
8
|
-
# test.mp3 is 'melange' by 'gromozek' http://ccmixter.org/files/gromozek/20114
|
9
|
-
# licensed CC Attribution Noncommercial (3.0) http://creativecommons.org/licenses/by-nc/3.0/
|
10
|
-
|
11
|
-
def base_dir
|
12
|
-
File.expand_path File.join(File.dirname(__FILE__), '..')
|
13
|
-
end
|
14
|
-
|
15
|
-
def version
|
16
|
-
File.open(File.join(base_dir, 'VERSION')).readline.strip
|
17
|
-
end
|
18
|
-
|
19
|
-
def remove_pkg
|
20
|
-
puts '=> removing pkg/'
|
21
|
-
command = %Q{
|
22
|
-
cd #{base_dir}
|
23
|
-
rm -rf pkg
|
24
|
-
}
|
25
|
-
`#{command}`
|
26
|
-
end
|
27
|
-
|
28
|
-
def clean_test_gem
|
29
|
-
puts '=> removing test/test_gem_installation/'
|
30
|
-
command = %Q{
|
31
|
-
cd #{base_dir}
|
32
|
-
rm -rf test/test_gem_installation
|
33
|
-
}
|
34
|
-
`#{command}`
|
35
|
-
end
|
36
|
-
|
37
|
-
def install_gem
|
38
|
-
puts '=> building the gem into pkg/ and installing into test/test_gem_installation/'
|
39
|
-
command = %Q{
|
40
|
-
cd #{base_dir}
|
41
|
-
rake build
|
42
|
-
gem install --no-test --no-rdoc --no-ri --install-dir test/test_gem_installation --bindir test/test_gem_installation pkg/ruby-shout-#{version}.gem
|
43
|
-
}
|
44
|
-
`#{command}`
|
45
|
-
end
|
46
|
-
|
47
|
-
clean_test_gem
|
48
|
-
install_gem
|
49
|
-
remove_pkg
|
50
|
-
|
51
|
-
$LOAD_PATH.clear
|
52
|
-
$LOAD_PATH << File.join(base_dir, "test/test_gem_installation/gems/ruby-shout-#{version}/lib")
|
53
|
-
require 'shout'
|
54
|
-
|
55
|
-
def test_all
|
56
|
-
blocksize = 16384
|
57
|
-
|
58
|
-
s = Shout.new
|
59
|
-
s.host = "localhost"
|
60
|
-
s.port = 8000
|
61
|
-
s.mount = "/test"
|
62
|
-
s.user = "source"
|
63
|
-
s.pass = "hackme"
|
64
|
-
s.format = Shout::MP3
|
65
|
-
|
66
|
-
s.connect
|
67
|
-
|
68
|
-
filename = File.join(File.dirname(__FILE__), 'test.mp3')
|
69
|
-
|
70
|
-
File.open(filename) do |file|
|
71
|
-
puts "=> sending data from #{filename}...\n go check http://localhost:8000/test"
|
72
|
-
m = ShoutMetadata.new
|
73
|
-
m.add 'filename', filename
|
74
|
-
m.add 'artist', 'gromozek'
|
75
|
-
m.add 'title', 'melange'
|
76
|
-
s.metadata = m
|
77
|
-
|
78
|
-
while data = file.read(blocksize)
|
79
|
-
s.send data
|
80
|
-
print '.'
|
81
|
-
s.sync
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
s.disconnect
|
86
|
-
ensure
|
87
|
-
clean_test_gem
|
88
|
-
end
|
89
|
-
|
90
|
-
test_all
|