ruby-shout 2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README +52 -0
  2. data/example.rb +34 -0
  3. data/ext/extconf.rb +11 -0
  4. data/ext/shout.c +700 -0
  5. metadata +48 -0
data/README ADDED
@@ -0,0 +1,52 @@
1
+ = Purpose
2
+
3
+ ruby-shout lets you send compressed audio over the network to an Icecast
4
+ streaming media server.
5
+
6
+ = Requirements
7
+
8
+ libshout 2.0, available from icecast.org. libshout 2 requires the ogg
9
+ and vorbis libraries.
10
+
11
+ = Summary of usage
12
+
13
+ This extension follows python-shout fairly closely. You make a Shout
14
+ object with Shout.new, set its properties, tell it to connect, then
15
+ send blocks of data, sync and repeat. Disconnect when done. There is
16
+ no #open that takes a block, as there is for a File or Socket: maybe later.
17
+
18
+ = Contributors
19
+
20
+ * Yauhen Kharuzhy: bugfixes and initial metadata support
21
+
22
+ = License
23
+ This is a BSD license.
24
+
25
+ Copyright (c) 2003-2005, Jared Jennings
26
+ All rights reserved.
27
+
28
+ Redistribution and use in source and binary forms, with or without
29
+ modification, are permitted provided that the following conditions are met:
30
+
31
+ * Redistributions of source code must retain the above copyright notice, this
32
+ list of conditions and the following disclaimer.
33
+
34
+ * Redistributions in binary form must reproduce the above copyright notice,
35
+ this list of conditions and the following disclaimer in the documentation
36
+ and/or other materials provided with the distribution.
37
+
38
+ * Neither the name of Jared Jennings nor the names of contributors may
39
+ be used to endorse or promote products derived from this software without
40
+ specific prior written permission.
41
+
42
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
43
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
45
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
46
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
49
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
51
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52
+
data/example.rb ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Stream all the files given on the commandline to the Icecast server on
4
+ # localhost.
5
+
6
+ require 'rubygems'
7
+ require 'shout'
8
+
9
+ BLOCKSIZE = 16384
10
+
11
+ s = Shout.new
12
+ s.host = "localhost"
13
+ s.port = 8000
14
+ s.mount = "/example.ogg"
15
+ s.user = "source"
16
+ s.pass = "hackme"
17
+
18
+ s.connect
19
+
20
+ ARGV.each do |filename|
21
+ File.open(filename) do |file|
22
+ puts "sending data from #{filename}"
23
+ m = ShoutMetadata.new
24
+ m.add 'filename', filename
25
+ s.metadata = m
26
+
27
+ while data = file.read(BLOCKSIZE)
28
+ s.send data
29
+ s.sync
30
+ end
31
+ end
32
+ end
33
+
34
+ s.disconnect
data/ext/extconf.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("shout")
4
+ have_library("ogg", "oggpack_writeinit")
5
+ have_library("vorbis", "vorbis_dsp_clear")
6
+ have_library("pthread", "pthread_create")
7
+ if find_library("shout", "shout_init","/usr","/usr/local") and have_header("shout/shout.h")
8
+ create_makefile("shout")
9
+ else
10
+ print "*** ERROR: need to have libshout and shout/shout.h to compile this module\n"
11
+ end
data/ext/shout.c ADDED
@@ -0,0 +1,700 @@
1
+ /*
2
+ shout.c - libshout extension for ruby
3
+ jared jennings
4
+ originally written 29 aug 2001
5
+ redone for libshout2 18 jul 2003
6
+
7
+ Copyright (c) 2003-2005, Jared Jennings
8
+ All rights reserved.
9
+
10
+ Redistribution and use in source and binary forms, with or without
11
+ modification, are permitted provided that the following conditions are met:
12
+
13
+ * Redistributions of source code must retain the above copyright notice,
14
+ this list of conditions and the following disclaimer.
15
+
16
+ * Redistributions in binary form must reproduce the above copyright notice,
17
+ this list of conditions and the following disclaimer in the documentation
18
+ and/or other materials provided with the distribution.
19
+
20
+ * Neither the name of Jared Jennings nor the names of contributors may
21
+ be used to endorse or promote products derived from this software without
22
+ specific prior written permission.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
+ POSSIBILITY OF SUCH DAMAGE.
35
+ */
36
+
37
+ #include "ruby.h"
38
+ #include <shout/shout.h>
39
+ #include <stdio.h>
40
+
41
+ #define DEFAULT_MOUNTPOINT "/default"
42
+
43
+ /*
44
+ ----------------- ShoutError --------------------
45
+ */
46
+ static VALUE cShoutError;
47
+
48
+ static void Init_shout_error() {
49
+ cShoutError = rb_define_class("ShoutError", rb_eRuntimeError);
50
+
51
+ rb_define_const(cShoutError, "SUCCESS",
52
+ INT2NUM(SHOUTERR_SUCCESS));
53
+ rb_define_const(cShoutError, "INSANE",
54
+ INT2NUM(SHOUTERR_INSANE));
55
+ rb_define_const(cShoutError, "CONNECTED",
56
+ INT2NUM(SHOUTERR_CONNECTED));
57
+ rb_define_const(cShoutError, "UNCONNECTED",
58
+ INT2NUM(SHOUTERR_UNCONNECTED));
59
+ rb_define_const(cShoutError, "NOCONNECT",
60
+ INT2NUM(SHOUTERR_NOCONNECT));
61
+ rb_define_const(cShoutError, "SOCKET",
62
+ INT2NUM(SHOUTERR_SOCKET));
63
+ rb_define_const(cShoutError, "UNSUPPORTED",
64
+ INT2NUM(SHOUTERR_UNSUPPORTED));
65
+ rb_define_const(cShoutError, "NOLOGIN",
66
+ INT2NUM(SHOUTERR_NOLOGIN));
67
+ rb_define_const(cShoutError, "MALLOC",
68
+ INT2NUM(SHOUTERR_MALLOC));
69
+ rb_define_const(cShoutError, "METADATA",
70
+ INT2NUM(SHOUTERR_METADATA));
71
+ rb_define_const(cShoutError, "BUSY",
72
+ INT2NUM(SHOUTERR_BUSY));
73
+ }
74
+
75
+ static void raise_shout_error(shout_t *conn) {
76
+ rb_raise(cShoutError, "%d: %s", shout_get_errno(conn),
77
+ shout_get_error(conn));
78
+ }
79
+
80
+ /* For metadata-related errors, which don't relate to a shout_t, so we can't
81
+ * use shout_get_errno or shout_get_error on them.
82
+ */
83
+ static void raise_nonspecific_shout_error(int errno) {
84
+ rb_raise(cShoutError, "%d", errno);
85
+ }
86
+
87
+ /*
88
+ ------------------- ShoutMetadata ---------------------
89
+ */
90
+
91
+ static VALUE cShoutMetadata;
92
+
93
+ static VALUE _sh_metadata_new(VALUE class) {
94
+ shout_metadata_t *m;
95
+ VALUE meta;
96
+
97
+ m = shout_metadata_new();
98
+
99
+ meta = Data_Wrap_Struct(class, 0, shout_metadata_free, m);
100
+
101
+ rb_obj_call_init(meta, 0, 0);
102
+
103
+ return meta;
104
+ }
105
+
106
+ static VALUE _sh_metadata_add(VALUE self, VALUE name, VALUE value) {
107
+ shout_metadata_t *m;
108
+ int err;
109
+
110
+ Data_Get_Struct(self, shout_metadata_t, m);
111
+ err = shout_metadata_add(m, STR2CSTR(name), STR2CSTR(value));
112
+
113
+ if(err != SHOUTERR_SUCCESS) {
114
+ raise_nonspecific_shout_error(err);
115
+ }
116
+
117
+ return value;
118
+ }
119
+
120
+ static void Init_shout_metadata() {
121
+
122
+ cShoutMetadata = rb_define_class("ShoutMetadata", rb_cObject);
123
+
124
+ rb_define_singleton_method(cShoutMetadata, "new", _sh_metadata_new, 0);
125
+ rb_define_method(cShoutMetadata, "add", _sh_metadata_add, 2);
126
+ }
127
+
128
+ /*
129
+ --------------------- Shout ---------------------------
130
+ */
131
+
132
+ static void invalid_object() {
133
+ rb_raise(rb_eRuntimeError, "invalid shout_connection");
134
+ }
135
+
136
+ #define GET_SC(obj, sc) { \
137
+ Data_Get_Struct(obj, shout_connection, sc); \
138
+ if(sc == NULL) invalid_object(); \
139
+ }
140
+
141
+ static VALUE cShout;
142
+
143
+ typedef struct _shout_connection {
144
+ shout_t *conn;
145
+ } shout_connection;
146
+
147
+ static void free_sh(shout_connection *cp) {
148
+ if(cp->conn) {
149
+ shout_close(cp->conn);
150
+ /* returns UNCONNECTED, INSANE or SUCCESS. we don't care. */
151
+ shout_free(cp->conn);
152
+ }
153
+ free(cp);
154
+ }
155
+
156
+
157
+ /* Make a new shout object. This method does not connect to any server. See
158
+ * #connect. */
159
+ static VALUE _sh_initialize(int argc, VALUE *argv, VALUE self) {
160
+ shout_connection *conn;
161
+
162
+ conn = ALLOC(shout_connection);
163
+ conn->conn = shout_new();
164
+ DATA_PTR(self) = conn;
165
+ return self;
166
+ }
167
+
168
+ static VALUE _Sh_new(int argc, VALUE *argv, VALUE klass) {
169
+ VALUE self = Data_Wrap_Struct(klass, 0, free_sh, 0);
170
+ rb_obj_call_init(self, argc, argv);
171
+ return self;
172
+ }
173
+
174
+ /* Returns the libshout version, as a string. */
175
+ static VALUE _Sh_version(VALUE klass) {
176
+ const char *version;
177
+ VALUE version_String;
178
+ version = shout_version(NULL, NULL, NULL);
179
+ version_String = rb_str_new2(version);
180
+ return version_String;
181
+ }
182
+
183
+ /* Connect to the server. You must set all the parameters you're going to set
184
+ * before connecting.
185
+ */
186
+ static VALUE _sh_connect(VALUE self) {
187
+ int err;
188
+ shout_connection *s;
189
+ GET_SC(self, s);
190
+
191
+ err = shout_open(s->conn);
192
+ if(err != SHOUTERR_SUCCESS) {
193
+ raise_shout_error(s->conn);
194
+ }
195
+ return Qtrue;
196
+ }
197
+
198
+ /* Disconnect from the server. */
199
+ static VALUE _sh_disconnect(VALUE self) {
200
+ int err;
201
+ shout_connection *s;
202
+ GET_SC(self, s);
203
+
204
+ err = shout_close(s->conn);
205
+ if(err != SHOUTERR_SUCCESS) {
206
+ raise_shout_error(s->conn);
207
+ }
208
+ return Qtrue;
209
+ }
210
+
211
+ /* Returns true if connected, false otherwise,
212
+ * nil if something really crazy happened.
213
+ */
214
+ static VALUE _sh_connectedp(VALUE self) {
215
+ int err;
216
+ shout_connection *s;
217
+ GET_SC(self, s);
218
+
219
+ err = shout_get_connected(s->conn);
220
+ if(err == SHOUTERR_CONNECTED) {
221
+ return Qtrue;
222
+ } else if(err == SHOUTERR_UNCONNECTED) {
223
+ return Qfalse;
224
+ } else {
225
+ return Qnil;
226
+ }
227
+ }
228
+
229
+ /* Send some data. to_send is a String containing the data to send. */
230
+ static VALUE _sh_send(VALUE self, VALUE to_send) {
231
+ int err;
232
+ shout_connection *s;
233
+ GET_SC(self, s);
234
+
235
+ Check_SafeStr(to_send);
236
+ err = shout_send(s->conn, (unsigned char *) (RSTRING(to_send)->ptr),
237
+ RSTRING(to_send)->len);
238
+ if(err != SHOUTERR_SUCCESS) {
239
+ raise_shout_error(s->conn);
240
+ }
241
+ return Qtrue;
242
+ }
243
+
244
+ /* Sleep the necessary amount of time to play back the audio data sent since
245
+ * the last call to #sync. After calling this, it's time to send more data. */
246
+ static VALUE _sh_sync(VALUE self) {
247
+ shout_connection *s;
248
+ GET_SC(self, s);
249
+
250
+ shout_sync(s->conn);
251
+ return Qtrue;
252
+ }
253
+
254
+ /* Return the proper amount of time, in milliseconds, before more data needs to
255
+ * be sent. This is for use when you would like to do something else in the
256
+ * intervening time period besides sleep. */
257
+ static VALUE _sh_delay(VALUE self) {
258
+ int ms;
259
+ shout_connection *s;
260
+ GET_SC(self, s);
261
+
262
+ ms = shout_delay(s->conn);
263
+ return INT2NUM(ms);
264
+ }
265
+
266
+
267
+
268
+
269
+ /* */
270
+ VALUE _sh_host(VALUE self) {
271
+ const char *value;
272
+ shout_connection *s; GET_SC(self, s);
273
+
274
+ value = shout_get_host(s->conn);
275
+ return rb_str_new2(value);
276
+ }
277
+
278
+ /* */
279
+ VALUE _sh_port(VALUE self) {
280
+ int value;
281
+ shout_connection *s; GET_SC(self, s);
282
+
283
+ value = shout_get_port(s->conn);
284
+ return INT2FIX(value);
285
+ }
286
+
287
+ /* */
288
+ VALUE _sh_user(VALUE self) {
289
+ const char *value;
290
+ shout_connection *s; GET_SC(self, s);
291
+
292
+ value = shout_get_user(s->conn);
293
+ return rb_str_new2(value);
294
+ }
295
+
296
+ /* */
297
+ VALUE _sh_pass(VALUE self) {
298
+ const char *value;
299
+ shout_connection *s; GET_SC(self, s);
300
+
301
+ value = shout_get_password(s->conn);
302
+ return rb_str_new2(value);
303
+ }
304
+
305
+ /* */
306
+ VALUE _sh_proto(VALUE self) {
307
+ int value;
308
+ shout_connection *s; GET_SC(self, s);
309
+
310
+ value = shout_get_protocol(s->conn);
311
+ return INT2FIX(value);
312
+ }
313
+
314
+ /* */
315
+ VALUE _sh_format(VALUE self) {
316
+ int value;
317
+ shout_connection *s; GET_SC(self, s);
318
+
319
+ value = shout_get_format(s->conn);
320
+ return INT2FIX(value);
321
+ }
322
+
323
+ /* */
324
+ VALUE _sh_mount(VALUE self) {
325
+ const char *value;
326
+ shout_connection *s; GET_SC(self, s);
327
+
328
+ value = shout_get_mount(s->conn);
329
+ return rb_str_new2(value);
330
+ }
331
+
332
+ /* */
333
+ VALUE _sh_dumpfile(VALUE self) {
334
+ const char *value;
335
+ shout_connection *s; GET_SC(self, s);
336
+
337
+ value = shout_get_dumpfile(s->conn);
338
+ return rb_str_new2(value);
339
+ }
340
+
341
+ /* */
342
+ VALUE _sh_agent(VALUE self) {
343
+ const char *value;
344
+ shout_connection *s; GET_SC(self, s);
345
+
346
+ value = shout_get_agent(s->conn);
347
+ return rb_str_new2(value);
348
+ }
349
+
350
+ /* */
351
+ VALUE _sh_public(VALUE self) {
352
+ int value;
353
+ shout_connection *s; GET_SC(self, s);
354
+
355
+ value = shout_get_public(s->conn);
356
+ return INT2FIX(value);
357
+ }
358
+
359
+ /* */
360
+ VALUE _sh_name(VALUE self) {
361
+ const char *value;
362
+ shout_connection *s; GET_SC(self, s);
363
+
364
+ value = shout_get_name(s->conn);
365
+ return rb_str_new2(value);
366
+ }
367
+
368
+ /* */
369
+ VALUE _sh_url(VALUE self) {
370
+ const char *value;
371
+ shout_connection *s; GET_SC(self, s);
372
+
373
+ value = shout_get_url(s->conn);
374
+ return rb_str_new2(value);
375
+ }
376
+
377
+ /* */
378
+ VALUE _sh_genre(VALUE self) {
379
+ const char *value;
380
+ shout_connection *s; GET_SC(self, s);
381
+
382
+ value = shout_get_genre(s->conn);
383
+ return rb_str_new2(value);
384
+ }
385
+
386
+ /* */
387
+ VALUE _sh_description(VALUE self) {
388
+ const char *value;
389
+ shout_connection *s; GET_SC(self, s);
390
+
391
+ value = shout_get_description(s->conn);
392
+ return rb_str_new2(value);
393
+ }
394
+
395
+ /* Unimplemented: audio_info */
396
+
397
+ /* audio_info and metadata should both be objects that always exist, and have
398
+ * [] and []= methods by which you get to the stuff in them. i.e. act like
399
+ * Hashes, because they are, albeit in another language.
400
+ */
401
+
402
+ /*
403
+ --------------------------- setters ------------------------------
404
+ */
405
+
406
+ /* Set the hostname to connect to. The default is localhost. */
407
+ VALUE _sh_host_eq(VALUE self, VALUE value) {
408
+ int err;
409
+ shout_connection *s; GET_SC(self, s);
410
+
411
+ Check_Type(value, T_STRING);
412
+ err = shout_set_host(s->conn, RSTRING(value)->ptr);
413
+ if(err != SHOUTERR_SUCCESS) {
414
+ raise_shout_error(s->conn);
415
+ }
416
+ return value;
417
+ }
418
+
419
+ /* Set the destination port. The default is 8000. */
420
+ VALUE _sh_port_eq(VALUE self, VALUE value) {
421
+ int err;
422
+ shout_connection *s; GET_SC(self, s);
423
+
424
+ Check_Type(value, T_FIXNUM);
425
+ err = shout_set_port(s->conn, FIX2INT(value));
426
+ if(err != SHOUTERR_SUCCESS) {
427
+ raise_shout_error(s->conn);
428
+ }
429
+ return value;
430
+ }
431
+
432
+ /* Set the user to authenticate as. The default is "source". */
433
+ VALUE _sh_user_eq(VALUE self, VALUE value) {
434
+ int err;
435
+ shout_connection *s; GET_SC(self, s);
436
+
437
+ Check_Type(value, T_STRING);
438
+ err = shout_set_user(s->conn, RSTRING(value)->ptr);
439
+ if(err != SHOUTERR_SUCCESS) {
440
+ raise_shout_error(s->conn);
441
+ }
442
+ return value;
443
+ }
444
+
445
+ /* Set the password to authenticate with. The default is no password. */
446
+ VALUE _sh_pass_eq(VALUE self, VALUE value) {
447
+ int err;
448
+ shout_connection *s; GET_SC(self, s);
449
+
450
+ Check_Type(value, T_STRING);
451
+ err = shout_set_password(s->conn, RSTRING(value)->ptr);
452
+ if(err != SHOUTERR_SUCCESS) {
453
+ raise_shout_error(s->conn);
454
+ }
455
+ return value;
456
+ }
457
+
458
+ /* Set the protocol to use when connecting. Default is Shout::HTTP. Possible
459
+ * values are:
460
+ * [Shout::HTTP] HTTP; the protocol used by Icecast.
461
+ * [Shout::XAUDIOCAST] XAudioCast. Obsolete.
462
+ * [Shout::ICY] Icy. Obsolete. Used by Shoutcast.
463
+ */
464
+ VALUE _sh_proto_eq(VALUE self, VALUE value) {
465
+ int err;
466
+ shout_connection *s; GET_SC(self, s);
467
+
468
+ Check_Type(value, T_FIXNUM);
469
+ err = shout_set_protocol(s->conn, FIX2INT(value));
470
+ if(err != SHOUTERR_SUCCESS) {
471
+ raise_shout_error(s->conn);
472
+ }
473
+ return value;
474
+ }
475
+
476
+ /* Set the format of the audio. Possible values are:
477
+ * [Shout::VORBIS] Ogg Vorbis
478
+ * [Shout::MP3] MP3
479
+ */
480
+ VALUE _sh_format_eq(VALUE self, VALUE value) {
481
+ int err;
482
+ shout_connection *s; GET_SC(self, s);
483
+
484
+ Check_Type(value, T_FIXNUM);
485
+ err = shout_set_format(s->conn, FIX2INT(value));
486
+ if(err != SHOUTERR_SUCCESS) {
487
+ raise_shout_error(s->conn);
488
+ }
489
+ return value;
490
+ }
491
+
492
+ /* Set the mountpoint on the server. */
493
+ VALUE _sh_mount_eq(VALUE self, VALUE value) {
494
+ int err;
495
+ shout_connection *s; GET_SC(self, s);
496
+
497
+ Check_Type(value, T_STRING);
498
+ err = shout_set_mount(s->conn, RSTRING(value)->ptr);
499
+ if(err != SHOUTERR_SUCCESS) {
500
+ raise_shout_error(s->conn);
501
+ }
502
+ return value;
503
+ }
504
+
505
+ /* Set a filename where the server should dump the data from this stream. Only
506
+ * do this if you know what you are doing. */
507
+ VALUE _sh_dumpfile_eq(VALUE self, VALUE value) {
508
+ int err;
509
+ shout_connection *s; GET_SC(self, s);
510
+
511
+ Check_Type(value, T_STRING);
512
+ err = shout_set_dumpfile(s->conn, RSTRING(value)->ptr);
513
+ if(err != SHOUTERR_SUCCESS) {
514
+ raise_shout_error(s->conn);
515
+ }
516
+ return value;
517
+ }
518
+
519
+ /* Set the User-Agent reported. The default is "libshout/<libshout version>",
520
+ * e.g. "libshout/2.0.0". */
521
+ VALUE _sh_agent_eq(VALUE self, VALUE value) {
522
+ int err;
523
+ shout_connection *s; GET_SC(self, s);
524
+
525
+ Check_Type(value, T_STRING);
526
+ err = shout_set_agent(s->conn, RSTRING(value)->ptr);
527
+ if(err != SHOUTERR_SUCCESS) {
528
+ raise_shout_error(s->conn);
529
+ }
530
+ return value;
531
+ }
532
+
533
+ /* Set whether or not this stream should be "public", i.e. advertised to a yp
534
+ * server such as yp.icecast.org. True or false. Nil counts as false. */
535
+ VALUE _sh_public_eq(VALUE self, VALUE value) {
536
+ int err;
537
+ shout_connection *s; GET_SC(self, s);
538
+
539
+ if(value == Qfalse || value == Qnil ||
540
+ (FIXNUM_P(value) && FIX2INT(value) == 0) ) {
541
+ err = shout_set_public(s->conn, 0);
542
+ } else {
543
+ err = shout_set_public(s->conn, 1);
544
+ }
545
+ if(err != SHOUTERR_SUCCESS) {
546
+ raise_shout_error(s->conn);
547
+ }
548
+ return value;
549
+ }
550
+
551
+ /* Set the name of the stream, e.g. "monkey's radio tunes." */
552
+ VALUE _sh_name_eq(VALUE self, VALUE value) {
553
+ int err;
554
+ shout_connection *s; GET_SC(self, s);
555
+
556
+ Check_Type(value, T_STRING);
557
+ err = shout_set_name(s->conn, RSTRING(value)->ptr);
558
+ if(err != SHOUTERR_SUCCESS) {
559
+ raise_shout_error(s->conn);
560
+ }
561
+ return value;
562
+ }
563
+
564
+ /* Set the URL to send the data to. Takes a string. */
565
+ VALUE _sh_url_eq(VALUE self, VALUE value) {
566
+ int err;
567
+ shout_connection *s; GET_SC(self, s);
568
+
569
+ Check_Type(value, T_STRING);
570
+ err = shout_set_url(s->conn, RSTRING(value)->ptr);
571
+ if(err != SHOUTERR_SUCCESS) {
572
+ raise_shout_error(s->conn);
573
+ }
574
+ return value;
575
+ }
576
+
577
+ /* Set the 'genre' of the stream. */
578
+ VALUE _sh_genre_eq(VALUE self, VALUE value) {
579
+ int err;
580
+ shout_connection *s; GET_SC(self, s);
581
+
582
+ Check_Type(value, T_STRING);
583
+ err = shout_set_genre(s->conn, RSTRING(value)->ptr);
584
+ if(err != SHOUTERR_SUCCESS) {
585
+ raise_shout_error(s->conn);
586
+ }
587
+ return value;
588
+ }
589
+
590
+ /* Set a longer description of the stream. Probably several lines of text. */
591
+ VALUE _sh_description_eq(VALUE self, VALUE value) {
592
+ int err;
593
+ shout_connection *s; GET_SC(self, s);
594
+
595
+ Check_Type(value, T_STRING);
596
+ err = shout_set_description(s->conn, RSTRING(value)->ptr);
597
+ if(err != SHOUTERR_SUCCESS) {
598
+ raise_shout_error(s->conn);
599
+ }
600
+ return value;
601
+ }
602
+
603
+ /* Set MP3 metadata. Create a ShoutMetadata object, add some stuff to it and
604
+ * pass it to this method. If the format of the stream isn't MP3, and you try
605
+ * to set its metadata, an exception will most likely be raised.
606
+ */
607
+ VALUE _sh_metadata_eq(VALUE self, VALUE meta) {
608
+ int err;
609
+ shout_connection *s; GET_SC(self, s);
610
+ shout_metadata_t *m; Data_Get_Struct(meta, shout_metadata_t, m);
611
+
612
+ err = shout_set_metadata(s->conn, m);
613
+
614
+ if(err != SHOUTERR_SUCCESS) {
615
+ raise_shout_error(s->conn);
616
+ }
617
+ return meta;
618
+ }
619
+
620
+
621
+
622
+ /*
623
+ ----------------------------------------------------------------
624
+ */
625
+
626
+ void Init_shout()
627
+ {
628
+ cShout = rb_define_class("Shout", rb_cObject);
629
+
630
+ shout_init();
631
+
632
+ rb_define_singleton_method(cShout, "new", _Sh_new, -1);
633
+ rb_define_singleton_method(cShout, "version", _Sh_version, 0);
634
+
635
+ rb_define_method(cShout, "initialize", _sh_initialize, -1);
636
+ rb_define_method(cShout, "connect", _sh_connect, 0);
637
+ rb_define_method(cShout, "open", _sh_connect, 0);
638
+ rb_define_method(cShout, "disconnect", _sh_disconnect, 0);
639
+ rb_define_method(cShout, "close", _sh_disconnect, 0);
640
+ rb_define_method(cShout, "connected?", _sh_connectedp, 0);
641
+
642
+ rb_define_method(cShout, "send", _sh_send, 1);
643
+ rb_define_method(cShout, "sync", _sh_sync, 0);
644
+ rb_define_method(cShout, "delay", _sh_delay, 0);
645
+
646
+ /* getters */
647
+ rb_define_method(cShout, "host", _sh_host, 0);
648
+ rb_define_method(cShout, "port", _sh_port, 0);
649
+ rb_define_method(cShout, "user", _sh_user, 0);
650
+ rb_define_method(cShout, "username", _sh_user, 0);
651
+ rb_define_method(cShout, "pass", _sh_pass, 0);
652
+ rb_define_method(cShout, "password", _sh_pass, 0);
653
+ rb_define_method(cShout, "protocol", _sh_proto, 0);
654
+ rb_define_method(cShout, "format", _sh_format, 0);
655
+ rb_define_method(cShout, "mount", _sh_mount, 0);
656
+ rb_define_method(cShout, "dumpfile", _sh_dumpfile, 0);
657
+ rb_define_method(cShout, "agent", _sh_agent, 0);
658
+ rb_define_method(cShout, "user_agent",_sh_agent, 0);
659
+ rb_define_method(cShout, "public", _sh_public, 0);
660
+ rb_define_method(cShout, "name", _sh_name, 0);
661
+ rb_define_method(cShout, "url", _sh_url, 0);
662
+ rb_define_method(cShout, "genre", _sh_genre, 0);
663
+ rb_define_method(cShout, "description",_sh_description,0);
664
+ /* metadata getting is still unsupported. */
665
+ /* audio info thingy. */
666
+ /* leave for version 2.2 */
667
+
668
+ /* setters */
669
+ rb_define_method(cShout, "host=", _sh_host_eq, 1);
670
+ rb_define_method(cShout, "port=", _sh_port_eq, 1);
671
+ rb_define_method(cShout, "user=", _sh_user_eq, 1);
672
+ rb_define_method(cShout, "username=", _sh_user_eq, 1);
673
+ rb_define_method(cShout, "pass=", _sh_pass_eq, 1);
674
+ rb_define_method(cShout, "password=", _sh_pass_eq, 1);
675
+ rb_define_method(cShout, "protocol=", _sh_proto_eq, 1);
676
+ rb_define_method(cShout, "format=", _sh_format_eq, 1);
677
+ rb_define_method(cShout, "mount=", _sh_mount_eq, 1);
678
+ rb_define_method(cShout, "dumpfile=", _sh_dumpfile_eq, 1);
679
+ rb_define_method(cShout, "agent=", _sh_agent_eq, 1);
680
+ rb_define_method(cShout, "user_agent=", _sh_agent_eq, 1);
681
+ rb_define_method(cShout, "public=", _sh_public_eq, 1);
682
+ rb_define_method(cShout, "name=", _sh_name_eq, 1);
683
+ rb_define_method(cShout, "url=", _sh_url_eq, 1);
684
+ rb_define_method(cShout, "genre=", _sh_genre_eq, 1);
685
+ rb_define_method(cShout, "description=", _sh_description_eq,1);
686
+ rb_define_method(cShout, "metadata=", _sh_metadata_eq, 1);
687
+
688
+ rb_define_const(cShout, "HTTP", INT2FIX(SHOUT_PROTOCOL_HTTP));
689
+ rb_define_const(cShout, "XAUDIOCAST", INT2FIX(SHOUT_PROTOCOL_XAUDIOCAST));
690
+ rb_define_const(cShout, "ICY", INT2FIX(SHOUT_PROTOCOL_ICY));
691
+
692
+ rb_define_const(cShout, "MP3", INT2FIX(SHOUT_FORMAT_MP3));
693
+ rb_define_const(cShout, "OGG", INT2FIX(SHOUT_FORMAT_OGG));
694
+ rb_define_const(cShout, "VORBIS", INT2FIX(SHOUT_FORMAT_VORBIS));
695
+
696
+ Init_shout_error();
697
+ Init_shout_metadata();
698
+
699
+ /* shout_shutdown(); goes somewhere. *shrug* */
700
+ }
metadata ADDED
@@ -0,0 +1,48 @@
1
+ !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: ruby-shout
5
+ version: !ruby/object:Gem::Version
6
+ version: "2.1"
7
+ date: 2005-11-19 00:00:00 -06:00
8
+ summary: Send audio over the network to an Icecast server
9
+ require_paths:
10
+ - .
11
+ email: jjenning@fastmail.fm
12
+ homepage: http://www.dingoskidneys.com/~jaredj/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: shout
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - Jared Jennings
30
+ files:
31
+ - ext/shout.c
32
+ - ext/extconf.rb
33
+ - example.rb
34
+ - README
35
+ test_files: []
36
+
37
+ rdoc_options: []
38
+
39
+ extra_rdoc_files:
40
+ - README
41
+ executables: []
42
+
43
+ extensions:
44
+ - ext/extconf.rb
45
+ requirements: []
46
+
47
+ dependencies: []
48
+