greenstripes 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/greenstripes/extconf.rb +4 -0
- data/ext/greenstripes/greenstripes.c +1494 -0
- data/lib/greenstripes.rb +163 -0
- data/test/config.rb.sample +9 -0
- data/test/test_greenstripes.rb +222 -0
- metadata +58 -0
|
@@ -0,0 +1,1494 @@
|
|
|
1
|
+
#include <ruby.h>
|
|
2
|
+
#include <spotify/api.h>
|
|
3
|
+
|
|
4
|
+
// modules and classes
|
|
5
|
+
|
|
6
|
+
static VALUE module_greenstripes;
|
|
7
|
+
|
|
8
|
+
static VALUE module_error;
|
|
9
|
+
static VALUE module_connection_state;
|
|
10
|
+
static VALUE module_link_type;
|
|
11
|
+
|
|
12
|
+
static VALUE class_session;
|
|
13
|
+
static VALUE class_user;
|
|
14
|
+
static VALUE class_playlist_container;
|
|
15
|
+
static VALUE class_playlist;
|
|
16
|
+
static VALUE class_search;
|
|
17
|
+
static VALUE class_artist_browse;
|
|
18
|
+
static VALUE class_album_browse;
|
|
19
|
+
static VALUE class_artist;
|
|
20
|
+
static VALUE class_album;
|
|
21
|
+
static VALUE class_track;
|
|
22
|
+
static VALUE class_link;
|
|
23
|
+
|
|
24
|
+
// callbacks
|
|
25
|
+
|
|
26
|
+
static void logged_in_callback(sp_session *session, sp_error error)
|
|
27
|
+
{
|
|
28
|
+
//fprintf(stderr, "logged_in_callback: %s\n", sp_error_message(error));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static void logged_out_callback(sp_session *session)
|
|
32
|
+
{
|
|
33
|
+
//fprintf(stderr, "logged_out_callback\n");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static void metadata_updated_callback(sp_session *session)
|
|
37
|
+
{
|
|
38
|
+
//fprintf(stderr, "metadata_updated_callback\n");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static void connection_error_callback(sp_session *session, sp_error error)
|
|
42
|
+
{
|
|
43
|
+
//fprintf(stderr, "connection_error_callback: %s\n", sp_error_message(error));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static void message_to_user_callback(sp_session *session, const char *message)
|
|
47
|
+
{
|
|
48
|
+
//fprintf(stderr, "message_to_user_callback: %s\n", message);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static void notify_main_thread_callback(sp_session *session)
|
|
52
|
+
{
|
|
53
|
+
//fprintf(stderr, "notify_main_thread_callback\n");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static void log_message_callback(sp_session *session, const char *data)
|
|
57
|
+
{
|
|
58
|
+
//fprintf(stderr, "log_message_callback: %s\n", data);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static void search_complete_callback(sp_search *result, void *userdata)
|
|
62
|
+
{
|
|
63
|
+
//fprintf(stderr, "search_complete_callback\n");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static void artist_browse_complete_callback(sp_artistbrowse *result, void *userdata)
|
|
67
|
+
{
|
|
68
|
+
//fprintf(stderr, "artist_browse_complete_callback\n");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static void album_browse_complete_callback(sp_albumbrowse *result, void *userdata)
|
|
72
|
+
{
|
|
73
|
+
//fprintf(stderr, "album_browse_complete_callback\n");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
* call-seq: Session.new(application_key, user_agent, cache_location, settings_location) -> session or nil
|
|
78
|
+
*
|
|
79
|
+
* Returns a new session.
|
|
80
|
+
*/
|
|
81
|
+
static VALUE session_new(VALUE klass, VALUE application_key, VALUE user_agent, VALUE cache_location, VALUE settings_location)
|
|
82
|
+
{
|
|
83
|
+
// TODO: session callbacks should not be hardcoded
|
|
84
|
+
sp_session_callbacks callbacks =
|
|
85
|
+
{
|
|
86
|
+
logged_in_callback,
|
|
87
|
+
logged_out_callback,
|
|
88
|
+
metadata_updated_callback,
|
|
89
|
+
connection_error_callback,
|
|
90
|
+
message_to_user_callback,
|
|
91
|
+
notify_main_thread_callback,
|
|
92
|
+
NULL, // music_delivery
|
|
93
|
+
NULL, // play_token_lost
|
|
94
|
+
log_message_callback
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
sp_session_config config =
|
|
98
|
+
{
|
|
99
|
+
SPOTIFY_API_VERSION,
|
|
100
|
+
StringValuePtr(cache_location),
|
|
101
|
+
StringValuePtr(settings_location),
|
|
102
|
+
RSTRING_PTR(application_key),
|
|
103
|
+
RSTRING_LEN(application_key),
|
|
104
|
+
StringValuePtr(user_agent),
|
|
105
|
+
&callbacks,
|
|
106
|
+
NULL
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
sp_session *session = NULL;
|
|
110
|
+
sp_error error = sp_session_init(&config, &session);
|
|
111
|
+
|
|
112
|
+
// TODO: handle error in a better way?
|
|
113
|
+
if(error != SP_ERROR_OK)
|
|
114
|
+
{
|
|
115
|
+
fprintf(stderr, "error: %s\n", sp_error_message(error));
|
|
116
|
+
return Qnil;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
VALUE session_value = Data_Wrap_Struct(class_session, NULL, NULL, session);
|
|
120
|
+
VALUE argv[4] = {application_key, user_agent, cache_location, settings_location};
|
|
121
|
+
rb_obj_call_init(session_value, 4, argv);
|
|
122
|
+
return session_value;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/*
|
|
126
|
+
* call-seq: session.login(username, password) -> error
|
|
127
|
+
*
|
|
128
|
+
* Attempts to log in with the given username and password. Returns one of the
|
|
129
|
+
* constants defined in Error.
|
|
130
|
+
*/
|
|
131
|
+
static VALUE session_login(VALUE self, VALUE username, VALUE password)
|
|
132
|
+
{
|
|
133
|
+
sp_session *session;
|
|
134
|
+
Data_Get_Struct(self, sp_session, session);
|
|
135
|
+
sp_error error = sp_session_login(session, StringValuePtr(username), StringValuePtr(password));
|
|
136
|
+
// TODO: throw an exception instead?
|
|
137
|
+
return INT2FIX(error);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/*
|
|
141
|
+
* call-seq: session.logout -> error
|
|
142
|
+
*
|
|
143
|
+
* Attempts to log out. Returns one of the constants defined in Error.
|
|
144
|
+
*/
|
|
145
|
+
static VALUE session_logout(VALUE self)
|
|
146
|
+
{
|
|
147
|
+
sp_session *session;
|
|
148
|
+
Data_Get_Struct(self, sp_session, session);
|
|
149
|
+
sp_error error = sp_session_logout(session);
|
|
150
|
+
// TODO: throw an exception instead?
|
|
151
|
+
return INT2FIX(error);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/*
|
|
155
|
+
* call-seq: session.connection_state -> state
|
|
156
|
+
*
|
|
157
|
+
* Returns one of the constants defined in ConnectionState.
|
|
158
|
+
*/
|
|
159
|
+
static VALUE session_connection_state(VALUE self)
|
|
160
|
+
{
|
|
161
|
+
sp_session *session;
|
|
162
|
+
Data_Get_Struct(self, sp_session, session);
|
|
163
|
+
int state = sp_session_connectionstate(session);
|
|
164
|
+
return INT2FIX(state);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/*
|
|
168
|
+
* call-seq: session.process_events -> fixnum
|
|
169
|
+
*
|
|
170
|
+
* Makes the session process any pending events. Returns the number of
|
|
171
|
+
* milliseconds until you should call this method again.
|
|
172
|
+
*/
|
|
173
|
+
static VALUE session_process_events(VALUE self)
|
|
174
|
+
{
|
|
175
|
+
sp_session *session;
|
|
176
|
+
Data_Get_Struct(self, sp_session, session);
|
|
177
|
+
int next_timeout;
|
|
178
|
+
sp_session_process_events(session, &next_timeout);
|
|
179
|
+
return INT2FIX(next_timeout);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/*
|
|
183
|
+
* call-seq: session.user -> user or nil
|
|
184
|
+
*
|
|
185
|
+
* Returns the user for the session.
|
|
186
|
+
*/
|
|
187
|
+
static VALUE session_user(VALUE self)
|
|
188
|
+
{
|
|
189
|
+
sp_session *s;
|
|
190
|
+
Data_Get_Struct(self, sp_session, s);
|
|
191
|
+
sp_user *user = NULL;
|
|
192
|
+
user = sp_session_user(s);
|
|
193
|
+
return user ? Data_Wrap_Struct(class_user, NULL, NULL, user) : Qnil;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
* call-seq: session.playlist_container -> playlist_container or nil
|
|
198
|
+
*
|
|
199
|
+
* Returns the playlist container for the session.
|
|
200
|
+
*/
|
|
201
|
+
static VALUE session_playlist_container(VALUE self)
|
|
202
|
+
{
|
|
203
|
+
sp_session *s;
|
|
204
|
+
Data_Get_Struct(self, sp_session, s);
|
|
205
|
+
sp_playlistcontainer *pc = NULL;
|
|
206
|
+
pc = sp_session_playlistcontainer(s);
|
|
207
|
+
return pc ? Data_Wrap_Struct(class_playlist_container, NULL, NULL, pc) : Qnil;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/*
|
|
211
|
+
* call-seq: user.loaded? -> true or false
|
|
212
|
+
*
|
|
213
|
+
* Returns true if the user is loaded, false otherwise.
|
|
214
|
+
*/
|
|
215
|
+
static VALUE user_loaded(VALUE self)
|
|
216
|
+
{
|
|
217
|
+
sp_user *user;
|
|
218
|
+
Data_Get_Struct(self, sp_user, user);
|
|
219
|
+
return sp_user_is_loaded(user) ? Qtrue : Qfalse;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/*
|
|
223
|
+
* call-seq: user.canonical_name -> string or nil
|
|
224
|
+
*
|
|
225
|
+
* Returns the user's canonical name.
|
|
226
|
+
*/
|
|
227
|
+
static VALUE user_canonical_name(VALUE self)
|
|
228
|
+
{
|
|
229
|
+
sp_user *user;
|
|
230
|
+
Data_Get_Struct(self, sp_user, user);
|
|
231
|
+
const char *name = sp_user_canonical_name(user);
|
|
232
|
+
return name ? rb_str_new2(name) : Qnil;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/*
|
|
236
|
+
* call-seq: user.display_name -> string or nil
|
|
237
|
+
*
|
|
238
|
+
* Returns the user's display name, or the canonical name if the display name is
|
|
239
|
+
* not known.
|
|
240
|
+
*/
|
|
241
|
+
static VALUE user_display_name(VALUE self)
|
|
242
|
+
{
|
|
243
|
+
sp_user *user;
|
|
244
|
+
Data_Get_Struct(self, sp_user, user);
|
|
245
|
+
const char *name = sp_user_display_name(user);
|
|
246
|
+
return name ? rb_str_new2(name) : Qnil;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/*
|
|
250
|
+
* call-seq: playlist_container.num_playlists -> fixnum or nil
|
|
251
|
+
*
|
|
252
|
+
*/
|
|
253
|
+
static VALUE playlist_container_num_playlists(VALUE self)
|
|
254
|
+
{
|
|
255
|
+
sp_playlistcontainer *playlistcontainer;
|
|
256
|
+
Data_Get_Struct(self, sp_playlistcontainer, playlistcontainer);
|
|
257
|
+
int n = sp_playlistcontainer_num_playlists(playlistcontainer);
|
|
258
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/*
|
|
262
|
+
* call-seq: playlist_container.playlist(index) -> playlist or nil
|
|
263
|
+
*
|
|
264
|
+
*/
|
|
265
|
+
static VALUE playlist_container_playlist(VALUE self, VALUE index)
|
|
266
|
+
{
|
|
267
|
+
sp_playlistcontainer *playlistcontainer;
|
|
268
|
+
Data_Get_Struct(self, sp_playlistcontainer, playlistcontainer);
|
|
269
|
+
int i = FIX2INT(index);
|
|
270
|
+
sp_playlist *playlist = NULL;
|
|
271
|
+
playlist = sp_playlistcontainer_playlist(playlistcontainer, i);
|
|
272
|
+
return playlist ? Data_Wrap_Struct(class_playlist, NULL, NULL, playlist) : Qnil;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/*
|
|
276
|
+
* call-seq: playlist_container.add_new_playlist(name) -> error
|
|
277
|
+
*
|
|
278
|
+
*/
|
|
279
|
+
static VALUE playlist_container_add_new_playlist(VALUE self, VALUE name)
|
|
280
|
+
{
|
|
281
|
+
sp_playlistcontainer *pc;
|
|
282
|
+
Data_Get_Struct(self, sp_playlistcontainer, pc);
|
|
283
|
+
sp_playlist *p = sp_playlistcontainer_add_new_playlist(pc, StringValuePtr(name));
|
|
284
|
+
return p ? Data_Wrap_Struct(class_playlist, NULL, NULL, p) : Qnil;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/*
|
|
288
|
+
* call-seq: playlist_container.add_playlist(link) -> error
|
|
289
|
+
*
|
|
290
|
+
*/
|
|
291
|
+
static VALUE playlist_container_add_playlist(VALUE self, VALUE link)
|
|
292
|
+
{
|
|
293
|
+
sp_playlistcontainer *pc;
|
|
294
|
+
Data_Get_Struct(self, sp_playlistcontainer, pc);
|
|
295
|
+
sp_link *l;
|
|
296
|
+
Data_Get_Struct(link, sp_link, l);
|
|
297
|
+
sp_playlist *p = sp_playlistcontainer_add_playlist(pc, l);
|
|
298
|
+
return p ? Data_Wrap_Struct(class_playlist, NULL, NULL, p) : Qnil;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/*
|
|
302
|
+
* call-seq: playlist_container.remove_playlist(index) -> error
|
|
303
|
+
*
|
|
304
|
+
*/
|
|
305
|
+
static VALUE playlist_container_remove_playlist(VALUE self, VALUE index)
|
|
306
|
+
{
|
|
307
|
+
sp_playlistcontainer *pc;
|
|
308
|
+
Data_Get_Struct(self, sp_playlistcontainer, pc);
|
|
309
|
+
sp_error e = sp_playlistcontainer_remove_playlist(pc, FIX2INT(index));
|
|
310
|
+
return INT2FIX(e);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/*
|
|
314
|
+
* call-seq: playlist_container.move_playlist(index, new_position) -> error
|
|
315
|
+
*
|
|
316
|
+
*/
|
|
317
|
+
static VALUE playlist_container_move_playlist(VALUE self, VALUE indices, VALUE new_position)
|
|
318
|
+
{
|
|
319
|
+
sp_playlistcontainer *pc;
|
|
320
|
+
Data_Get_Struct(self, sp_playlistcontainer, pc);
|
|
321
|
+
sp_error e = sp_playlistcontainer_move_playlist(pc, FIX2INT(index), FIX2INT(new_position));
|
|
322
|
+
return INT2FIX(e);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/*
|
|
326
|
+
* call-seq: playlist.loaded? -> true or false
|
|
327
|
+
*
|
|
328
|
+
* Returns true if the playlist is loaded, false otherwise.
|
|
329
|
+
*/
|
|
330
|
+
static VALUE playlist_loaded(VALUE self)
|
|
331
|
+
{
|
|
332
|
+
sp_playlist *playlist;
|
|
333
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
334
|
+
return sp_playlist_is_loaded(playlist) ? Qtrue : Qfalse;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/*
|
|
338
|
+
* call-seq: playlist.name -> string or nil
|
|
339
|
+
*
|
|
340
|
+
* Returns the playlist's name.
|
|
341
|
+
*/
|
|
342
|
+
static VALUE playlist_name(VALUE self)
|
|
343
|
+
{
|
|
344
|
+
sp_playlist *playlist;
|
|
345
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
346
|
+
const char *name = sp_playlist_name(playlist);
|
|
347
|
+
return name ? rb_str_new2(name) : Qnil;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/*
|
|
351
|
+
* call-seq: playlist.name = new_name -> string or nil
|
|
352
|
+
*
|
|
353
|
+
* Sets the playlist's name to the value of new_name.
|
|
354
|
+
*/
|
|
355
|
+
static VALUE playlist_name_set(VALUE self, VALUE new_name)
|
|
356
|
+
{
|
|
357
|
+
sp_playlist *playlist;
|
|
358
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
359
|
+
|
|
360
|
+
sp_error error = sp_playlist_rename(playlist, StringValuePtr(new_name));
|
|
361
|
+
|
|
362
|
+
// TODO: throw exception instead?
|
|
363
|
+
if(error != SP_ERROR_OK)
|
|
364
|
+
return Qnil;
|
|
365
|
+
|
|
366
|
+
return new_name;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/*
|
|
370
|
+
* call-seq: playlist.owner -> user or nil
|
|
371
|
+
*
|
|
372
|
+
* Returns the playlist's owner.
|
|
373
|
+
*/
|
|
374
|
+
static VALUE playlist_owner(VALUE self)
|
|
375
|
+
{
|
|
376
|
+
sp_playlist *playlist;
|
|
377
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
378
|
+
sp_user *user = NULL;
|
|
379
|
+
user = sp_playlist_owner(playlist);
|
|
380
|
+
return user ? Data_Wrap_Struct(class_user, NULL, NULL, user) : Qnil;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/*
|
|
384
|
+
* call-seq: playlist.collaborative? -> true or false
|
|
385
|
+
*
|
|
386
|
+
* Returns true if the playlist is collaborative, false otherwise.
|
|
387
|
+
*/
|
|
388
|
+
static VALUE playlist_collaborative(VALUE self)
|
|
389
|
+
{
|
|
390
|
+
sp_playlist *playlist;
|
|
391
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
392
|
+
return sp_playlist_is_collaborative(playlist) ? Qtrue : Qfalse;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/*
|
|
396
|
+
* call-seq: playlist.collaborative = true or false -> true or false
|
|
397
|
+
*
|
|
398
|
+
* Sets the collaborative status of the playlist.
|
|
399
|
+
*/
|
|
400
|
+
static VALUE playlist_collaborative_set(VALUE self, VALUE collaborative)
|
|
401
|
+
{
|
|
402
|
+
sp_playlist *playlist;
|
|
403
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
404
|
+
sp_playlist_set_collaborative(playlist, collaborative != Qnil && collaborative != Qfalse);
|
|
405
|
+
return collaborative;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/*
|
|
409
|
+
* call-seq: playlist.num_tracks -> fixnum or nil
|
|
410
|
+
*
|
|
411
|
+
*/
|
|
412
|
+
static VALUE playlist_num_tracks(VALUE self)
|
|
413
|
+
{
|
|
414
|
+
sp_playlist *playlist;
|
|
415
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
416
|
+
int n = sp_playlist_num_tracks(playlist);
|
|
417
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/*
|
|
421
|
+
* call-seq: playlist.track(index) -> track or nil
|
|
422
|
+
*
|
|
423
|
+
*/
|
|
424
|
+
static VALUE playlist_track(VALUE self, VALUE index)
|
|
425
|
+
{
|
|
426
|
+
sp_playlist *playlist;
|
|
427
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
428
|
+
int i = FIX2INT(index);
|
|
429
|
+
sp_track *track = NULL;
|
|
430
|
+
track = sp_playlist_track(playlist, i);
|
|
431
|
+
return track ? Data_Wrap_Struct(class_track, NULL, NULL, track) : Qnil;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/*
|
|
435
|
+
* call-seq: playlist.pending_changes? -> true or false
|
|
436
|
+
*
|
|
437
|
+
* Returns true if the playlist has local changes that have not yet been
|
|
438
|
+
* acknowledged by the server, false otherwise.
|
|
439
|
+
*/
|
|
440
|
+
static VALUE playlist_pending_changes(VALUE self)
|
|
441
|
+
{
|
|
442
|
+
sp_playlist *playlist;
|
|
443
|
+
Data_Get_Struct(self, sp_playlist, playlist);
|
|
444
|
+
return sp_playlist_has_pending_changes(playlist) ? Qtrue : Qfalse;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/*
|
|
448
|
+
* call-seq: playlist.add_tracks(tracks, position) -> error
|
|
449
|
+
*
|
|
450
|
+
* Add tracks at position in the playlist.
|
|
451
|
+
*/
|
|
452
|
+
static VALUE playlist_add_tracks(VALUE self, VALUE tracks, VALUE position)
|
|
453
|
+
{
|
|
454
|
+
sp_playlist *p;
|
|
455
|
+
Data_Get_Struct(self, sp_playlist, p);
|
|
456
|
+
int n = rb_ary_length(tracks);
|
|
457
|
+
const sp_track **ts = malloc(n*sizeof(sp_track *));
|
|
458
|
+
int i;
|
|
459
|
+
for(i = 0; i < n; ++i)
|
|
460
|
+
{
|
|
461
|
+
sp_track *t;
|
|
462
|
+
Data_Get_Struct(rb_ary_entry(tracks, i), sp_track, t);
|
|
463
|
+
ts[i] = t;
|
|
464
|
+
}
|
|
465
|
+
sp_error e = sp_playlist_add_tracks(p, ts, n, FIX2INT(position));
|
|
466
|
+
free(ts);
|
|
467
|
+
return INT2FIX(e);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/*
|
|
471
|
+
* call-seq: playlist.remove_tracks(indices) -> error
|
|
472
|
+
*
|
|
473
|
+
* Remove the tracks at indices from the playlist.
|
|
474
|
+
*/
|
|
475
|
+
static VALUE playlist_remove_tracks(VALUE self, VALUE indices)
|
|
476
|
+
{
|
|
477
|
+
sp_playlist *p;
|
|
478
|
+
Data_Get_Struct(self, sp_playlist, p);
|
|
479
|
+
int n = rb_ary_length(indices);
|
|
480
|
+
int *is = malloc(n*sizeof(int));
|
|
481
|
+
int i;
|
|
482
|
+
for(i = 0; i < n; ++i)
|
|
483
|
+
is[i] = FIX2INT(rb_ary_entry(indices, i));
|
|
484
|
+
sp_error e = sp_playlist_remove_tracks(p, is, n);
|
|
485
|
+
free(is);
|
|
486
|
+
return INT2FIX(e);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/*
|
|
490
|
+
* call-seq: playlist.reorder_tracks(indices, new_position) -> error
|
|
491
|
+
*
|
|
492
|
+
* Move the tracks at indices to new_position in the playlist.
|
|
493
|
+
*/
|
|
494
|
+
static VALUE playlist_reorder_tracks(VALUE self, VALUE indices, VALUE new_position)
|
|
495
|
+
{
|
|
496
|
+
sp_playlist *p;
|
|
497
|
+
Data_Get_Struct(self, sp_playlist, p);
|
|
498
|
+
int n = rb_ary_length(indices);
|
|
499
|
+
int *is = malloc(n*sizeof(int));
|
|
500
|
+
int i;
|
|
501
|
+
for(i = 0; i < n; ++i)
|
|
502
|
+
is[i] = FIX2INT(rb_ary_entry(indices, i));
|
|
503
|
+
sp_error e = sp_playlist_reorder_tracks(p, is, n, FIX2INT(new_position));
|
|
504
|
+
free(is);
|
|
505
|
+
return INT2FIX(e);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
static void search_free(void *search)
|
|
509
|
+
{
|
|
510
|
+
sp_search_release(search);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/*
|
|
514
|
+
* call-seq: Search.new(session, query, offset, count) -> search or nil
|
|
515
|
+
*
|
|
516
|
+
* Returns a new search object.
|
|
517
|
+
*/
|
|
518
|
+
static VALUE search_new(VALUE klass, VALUE session, VALUE query, VALUE offset, VALUE count)
|
|
519
|
+
{
|
|
520
|
+
// TODO: search callback should not be hardcoded
|
|
521
|
+
|
|
522
|
+
sp_session *sess;
|
|
523
|
+
Data_Get_Struct(session, sp_session, sess);
|
|
524
|
+
|
|
525
|
+
sp_search *search = NULL;
|
|
526
|
+
search = sp_search_create(sess,
|
|
527
|
+
StringValuePtr(query),
|
|
528
|
+
FIX2INT(offset),
|
|
529
|
+
FIX2INT(count),
|
|
530
|
+
0,
|
|
531
|
+
100,
|
|
532
|
+
0,
|
|
533
|
+
100,
|
|
534
|
+
search_complete_callback,
|
|
535
|
+
NULL);
|
|
536
|
+
|
|
537
|
+
if(!search)
|
|
538
|
+
return Qnil;
|
|
539
|
+
|
|
540
|
+
VALUE search_value = Data_Wrap_Struct(class_search, NULL, search_free, search);
|
|
541
|
+
VALUE argv[4] = {session, query, offset, count};
|
|
542
|
+
rb_obj_call_init(search_value, 4, argv);
|
|
543
|
+
return search_value;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/*
|
|
547
|
+
* call-seq: search.loaded? -> true or false
|
|
548
|
+
*
|
|
549
|
+
* Returns true if the search object is loaded, false otherwise.
|
|
550
|
+
*/
|
|
551
|
+
static VALUE search_loaded(VALUE self)
|
|
552
|
+
{
|
|
553
|
+
sp_search *search;
|
|
554
|
+
Data_Get_Struct(self, sp_search, search);
|
|
555
|
+
return sp_search_is_loaded(search) ? Qtrue : Qfalse;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/*
|
|
559
|
+
* call-seq: search.error -> error
|
|
560
|
+
*
|
|
561
|
+
* Returns one of the constants defined in Error.
|
|
562
|
+
*/
|
|
563
|
+
static VALUE search_error(VALUE self)
|
|
564
|
+
{
|
|
565
|
+
sp_search *search;
|
|
566
|
+
Data_Get_Struct(self, sp_search, search);
|
|
567
|
+
sp_error error = sp_search_error(search);
|
|
568
|
+
return INT2FIX(error);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/*
|
|
572
|
+
* call-seq: search.num_artists -> fixnum or nil
|
|
573
|
+
*
|
|
574
|
+
*/
|
|
575
|
+
static VALUE search_num_artists(VALUE self)
|
|
576
|
+
{
|
|
577
|
+
sp_search *search;
|
|
578
|
+
Data_Get_Struct(self, sp_search, search);
|
|
579
|
+
int n = sp_search_num_artists(search);
|
|
580
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/*
|
|
584
|
+
* call-seq: search.artist(index) -> artist or nil
|
|
585
|
+
*
|
|
586
|
+
*/
|
|
587
|
+
static VALUE search_artist(VALUE self, VALUE index)
|
|
588
|
+
{
|
|
589
|
+
sp_search *search;
|
|
590
|
+
Data_Get_Struct(self, sp_search, search);
|
|
591
|
+
int i = FIX2INT(index);
|
|
592
|
+
sp_artist *artist = NULL;
|
|
593
|
+
artist = sp_search_artist(search, i);
|
|
594
|
+
return artist ? Data_Wrap_Struct(class_artist, NULL, NULL, artist) : Qnil;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/*
|
|
598
|
+
* call-seq: search.num_albums -> fixnum or nil
|
|
599
|
+
*
|
|
600
|
+
*/
|
|
601
|
+
static VALUE search_num_albums(VALUE self)
|
|
602
|
+
{
|
|
603
|
+
sp_search *search;
|
|
604
|
+
Data_Get_Struct(self, sp_search, search);
|
|
605
|
+
int n = sp_search_num_albums(search);
|
|
606
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/*
|
|
610
|
+
* call-seq: search.album(index) -> album or nil
|
|
611
|
+
*
|
|
612
|
+
*/
|
|
613
|
+
static VALUE search_album(VALUE self, VALUE index)
|
|
614
|
+
{
|
|
615
|
+
sp_search *search;
|
|
616
|
+
Data_Get_Struct(self, sp_search, search);
|
|
617
|
+
int i = FIX2INT(index);
|
|
618
|
+
sp_album *album = NULL;
|
|
619
|
+
album = sp_search_album(search, i);
|
|
620
|
+
return album ? Data_Wrap_Struct(class_album, NULL, NULL, album) : Qnil;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/*
|
|
624
|
+
* call-seq: search.num_tracks -> fixnum or nil
|
|
625
|
+
*
|
|
626
|
+
*/
|
|
627
|
+
static VALUE search_num_tracks(VALUE self)
|
|
628
|
+
{
|
|
629
|
+
sp_search *search;
|
|
630
|
+
Data_Get_Struct(self, sp_search, search);
|
|
631
|
+
int n = sp_search_num_tracks(search);
|
|
632
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/*
|
|
636
|
+
* call-seq: search.track(index) -> track or nil
|
|
637
|
+
*
|
|
638
|
+
*/
|
|
639
|
+
static VALUE search_track(VALUE self, VALUE index)
|
|
640
|
+
{
|
|
641
|
+
sp_search *search;
|
|
642
|
+
Data_Get_Struct(self, sp_search, search);
|
|
643
|
+
int i = FIX2INT(index);
|
|
644
|
+
sp_track *track = NULL;
|
|
645
|
+
track = sp_search_track(search, i);
|
|
646
|
+
return track ? Data_Wrap_Struct(class_track, NULL, NULL, track) : Qnil;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/*
|
|
650
|
+
* call-seq: search.total_tracks -> fixnum or nil
|
|
651
|
+
*
|
|
652
|
+
* Returns the total number of track hits for the search query.
|
|
653
|
+
*/
|
|
654
|
+
static VALUE search_total_tracks(VALUE self)
|
|
655
|
+
{
|
|
656
|
+
sp_search *search;
|
|
657
|
+
Data_Get_Struct(self, sp_search, search);
|
|
658
|
+
int n = sp_search_total_tracks(search);
|
|
659
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/*
|
|
663
|
+
* call-seq: search.query -> string or nil
|
|
664
|
+
*
|
|
665
|
+
* Returns the query for the search object.
|
|
666
|
+
*/
|
|
667
|
+
static VALUE search_query(VALUE self)
|
|
668
|
+
{
|
|
669
|
+
sp_search *search;
|
|
670
|
+
Data_Get_Struct(self, sp_search, search);
|
|
671
|
+
const char *q = sp_search_query(search);
|
|
672
|
+
return q ? rb_str_new2(q) : Qnil;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/*
|
|
676
|
+
* call-seq: search.did_you_mean -> string or nil
|
|
677
|
+
*
|
|
678
|
+
* Returns the "did you mean" suggestion for the search object, or nil if no
|
|
679
|
+
* suggestion is available.
|
|
680
|
+
*/
|
|
681
|
+
static VALUE search_did_you_mean(VALUE self)
|
|
682
|
+
{
|
|
683
|
+
sp_search *search;
|
|
684
|
+
Data_Get_Struct(self, sp_search, search);
|
|
685
|
+
const char *d = sp_search_did_you_mean(search);
|
|
686
|
+
return d ? rb_str_new2(d) : Qnil;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
static void artist_browse_free(void *ab)
|
|
690
|
+
{
|
|
691
|
+
sp_artistbrowse_release(ab);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/*
|
|
695
|
+
* call-seq: ArtistBrowse.new(session, artist) -> artist_browse or nil
|
|
696
|
+
*
|
|
697
|
+
* Returns a new artist browse object.
|
|
698
|
+
*/
|
|
699
|
+
static VALUE artist_browse_new(VALUE klass, VALUE session, VALUE artist)
|
|
700
|
+
{
|
|
701
|
+
// TODO: artist browse callback should not be hardcoded
|
|
702
|
+
|
|
703
|
+
sp_session *s;
|
|
704
|
+
Data_Get_Struct(session, sp_session, s);
|
|
705
|
+
|
|
706
|
+
sp_artist *a;
|
|
707
|
+
Data_Get_Struct(artist, sp_artist, a);
|
|
708
|
+
|
|
709
|
+
sp_artistbrowse *artistbrowse = NULL;
|
|
710
|
+
artistbrowse = sp_artistbrowse_create(s, a, artist_browse_complete_callback, NULL);
|
|
711
|
+
|
|
712
|
+
if(!artistbrowse)
|
|
713
|
+
return Qnil;
|
|
714
|
+
|
|
715
|
+
VALUE ab_value = Data_Wrap_Struct(class_artist_browse, NULL, artist_browse_free, artistbrowse);
|
|
716
|
+
VALUE argv[2] = {session, artist};
|
|
717
|
+
rb_obj_call_init(ab_value, 2, argv);
|
|
718
|
+
return ab_value;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/*
|
|
722
|
+
* call-seq: artist_browse.loaded? -> true or false
|
|
723
|
+
*
|
|
724
|
+
* Returns true if the artist browse object is loaded, false otherwise.
|
|
725
|
+
*/
|
|
726
|
+
static VALUE artist_browse_loaded(VALUE self)
|
|
727
|
+
{
|
|
728
|
+
sp_artistbrowse *artistbrowse;
|
|
729
|
+
Data_Get_Struct(self, sp_artistbrowse, artistbrowse);
|
|
730
|
+
return sp_artistbrowse_is_loaded(artistbrowse) ? Qtrue : Qfalse;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
/*
|
|
734
|
+
* call-seq: artist_browse.error -> error
|
|
735
|
+
*
|
|
736
|
+
* Returns one of the constants defined in Error.
|
|
737
|
+
*/
|
|
738
|
+
static VALUE artist_browse_error(VALUE self)
|
|
739
|
+
{
|
|
740
|
+
sp_artistbrowse *artistbrowse;
|
|
741
|
+
Data_Get_Struct(self, sp_artistbrowse, artistbrowse);
|
|
742
|
+
sp_error error = sp_artistbrowse_error(artistbrowse);
|
|
743
|
+
return INT2FIX(error);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/*
|
|
747
|
+
* call-seq: artist_browse.artist -> artist or nil
|
|
748
|
+
*
|
|
749
|
+
* Returns the artist for the artist browse object.
|
|
750
|
+
*/
|
|
751
|
+
static VALUE artist_browse_artist(VALUE self)
|
|
752
|
+
{
|
|
753
|
+
sp_artistbrowse *artistbrowse;
|
|
754
|
+
Data_Get_Struct(self, sp_artistbrowse, artistbrowse);
|
|
755
|
+
sp_artist *artist = sp_artistbrowse_artist(artistbrowse);
|
|
756
|
+
return artist ? Data_Wrap_Struct(class_artist, NULL, NULL, artist) : Qnil;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/*
|
|
760
|
+
* call-seq: artist_browse.num_tracks -> fixnum or nil
|
|
761
|
+
*
|
|
762
|
+
*/
|
|
763
|
+
static VALUE artist_browse_num_tracks(VALUE self)
|
|
764
|
+
{
|
|
765
|
+
sp_artistbrowse *artistbrowse;
|
|
766
|
+
Data_Get_Struct(self, sp_artistbrowse, artistbrowse);
|
|
767
|
+
int n = sp_artistbrowse_num_tracks(artistbrowse);
|
|
768
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/*
|
|
772
|
+
* call-seq: artist_browse.track(index) -> track or nil
|
|
773
|
+
*
|
|
774
|
+
*/
|
|
775
|
+
static VALUE artist_browse_track(VALUE self, VALUE index)
|
|
776
|
+
{
|
|
777
|
+
sp_artistbrowse *artistbrowse;
|
|
778
|
+
Data_Get_Struct(self, sp_artistbrowse, artistbrowse);
|
|
779
|
+
int i = FIX2INT(index);
|
|
780
|
+
sp_track *track = NULL;
|
|
781
|
+
track = sp_artistbrowse_track(artistbrowse, i);
|
|
782
|
+
return track ? Data_Wrap_Struct(class_track, NULL, NULL, track) : Qnil;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/*
|
|
786
|
+
* call-seq: artist_browse.num_similar_artists -> fixnum or nil
|
|
787
|
+
*
|
|
788
|
+
*/
|
|
789
|
+
static VALUE artist_browse_num_similar_artists(VALUE self)
|
|
790
|
+
{
|
|
791
|
+
sp_artistbrowse *artistbrowse;
|
|
792
|
+
Data_Get_Struct(self, sp_artistbrowse, artistbrowse);
|
|
793
|
+
int n = sp_artistbrowse_num_similar_artists(artistbrowse);
|
|
794
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/*
|
|
798
|
+
* call-seq: artist_browse.similar_artist(index) -> artist or nil
|
|
799
|
+
*
|
|
800
|
+
*/
|
|
801
|
+
static VALUE artist_browse_similar_artist(VALUE self, VALUE index)
|
|
802
|
+
{
|
|
803
|
+
sp_artistbrowse *artistbrowse;
|
|
804
|
+
Data_Get_Struct(self, sp_artistbrowse, artistbrowse);
|
|
805
|
+
int i = FIX2INT(index);
|
|
806
|
+
sp_artist *artist = NULL;
|
|
807
|
+
artist = sp_artistbrowse_similar_artist(artistbrowse, i);
|
|
808
|
+
return artist ? Data_Wrap_Struct(class_artist, NULL, NULL, artist) : Qnil;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/*
|
|
812
|
+
* call-seq: artist_browse.biography -> string or nil
|
|
813
|
+
*
|
|
814
|
+
* Returns the biography for the artist browse object, or nil if no biography is
|
|
815
|
+
* available.
|
|
816
|
+
*/
|
|
817
|
+
static VALUE artist_browse_biography(VALUE self)
|
|
818
|
+
{
|
|
819
|
+
sp_artistbrowse *artistbrowse;
|
|
820
|
+
Data_Get_Struct(self, sp_artistbrowse, artistbrowse);
|
|
821
|
+
const char *bio = sp_artistbrowse_biography(artistbrowse);
|
|
822
|
+
return bio ? rb_str_new2(bio) : Qnil;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
static void album_browse_free(void *ab)
|
|
826
|
+
{
|
|
827
|
+
sp_albumbrowse_release(ab);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/*
|
|
831
|
+
* call-seq: AlbumBrowse.new(session, album) -> album_browse or nil
|
|
832
|
+
*
|
|
833
|
+
* Returns a new album browse object.
|
|
834
|
+
*/
|
|
835
|
+
static VALUE album_browse_new(VALUE klass, VALUE session, VALUE album)
|
|
836
|
+
{
|
|
837
|
+
// TODO: album browse callback should not be hardcoded
|
|
838
|
+
|
|
839
|
+
sp_session *s;
|
|
840
|
+
Data_Get_Struct(session, sp_session, s);
|
|
841
|
+
|
|
842
|
+
sp_album *a;
|
|
843
|
+
Data_Get_Struct(album, sp_album, a);
|
|
844
|
+
|
|
845
|
+
sp_albumbrowse *albumbrowse = NULL;
|
|
846
|
+
albumbrowse = sp_albumbrowse_create(s, a, album_browse_complete_callback, NULL);
|
|
847
|
+
|
|
848
|
+
if(!albumbrowse)
|
|
849
|
+
return Qnil;
|
|
850
|
+
|
|
851
|
+
VALUE ab_value = Data_Wrap_Struct(class_album_browse, NULL, album_browse_free, albumbrowse);
|
|
852
|
+
VALUE argv[2] = {session, album};
|
|
853
|
+
rb_obj_call_init(ab_value, 2, argv);
|
|
854
|
+
return ab_value;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
/*
|
|
858
|
+
* call-seq: album_browse.loaded? -> true or false
|
|
859
|
+
*
|
|
860
|
+
* Returns true if the album browse object is loaded, false otherwise.
|
|
861
|
+
*/
|
|
862
|
+
static VALUE album_browse_loaded(VALUE self)
|
|
863
|
+
{
|
|
864
|
+
sp_albumbrowse *albumbrowse;
|
|
865
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
866
|
+
return sp_albumbrowse_is_loaded(albumbrowse) ? Qtrue : Qfalse;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/*
|
|
870
|
+
* call-seq: album_browse.error -> error
|
|
871
|
+
*
|
|
872
|
+
* Returns one of the constants defined in Error.
|
|
873
|
+
*/
|
|
874
|
+
static VALUE album_browse_error(VALUE self)
|
|
875
|
+
{
|
|
876
|
+
sp_albumbrowse *albumbrowse;
|
|
877
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
878
|
+
sp_error error = sp_albumbrowse_error(albumbrowse);
|
|
879
|
+
return INT2FIX(error);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/*
|
|
883
|
+
* call-seq: album_browse.artist -> artist or nil
|
|
884
|
+
*
|
|
885
|
+
* Returns the artist for the album browse object.
|
|
886
|
+
*/
|
|
887
|
+
static VALUE album_browse_artist(VALUE self)
|
|
888
|
+
{
|
|
889
|
+
sp_albumbrowse *albumbrowse;
|
|
890
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
891
|
+
sp_artist *artist = sp_albumbrowse_artist(albumbrowse);
|
|
892
|
+
return artist ? Data_Wrap_Struct(class_artist, NULL, NULL, artist) : Qnil;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/*
|
|
896
|
+
* call-seq: album_browse.album -> album or nil
|
|
897
|
+
*
|
|
898
|
+
* Returns the album for the album browse object.
|
|
899
|
+
*/
|
|
900
|
+
static VALUE album_browse_album(VALUE self)
|
|
901
|
+
{
|
|
902
|
+
sp_albumbrowse *albumbrowse;
|
|
903
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
904
|
+
sp_album *album = sp_albumbrowse_album(albumbrowse);
|
|
905
|
+
return album ? Data_Wrap_Struct(class_album, NULL, NULL, album) : Qnil;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/*
|
|
909
|
+
* call-seq: album_browse.num_tracks -> fixnum or nil
|
|
910
|
+
*
|
|
911
|
+
*/
|
|
912
|
+
static VALUE album_browse_num_tracks(VALUE self)
|
|
913
|
+
{
|
|
914
|
+
sp_albumbrowse *albumbrowse;
|
|
915
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
916
|
+
int n = sp_albumbrowse_num_tracks(albumbrowse);
|
|
917
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
/*
|
|
921
|
+
* call-seq: album_browse_track(index) -> track or nil
|
|
922
|
+
*
|
|
923
|
+
*/
|
|
924
|
+
static VALUE album_browse_track(VALUE self, VALUE index)
|
|
925
|
+
{
|
|
926
|
+
sp_albumbrowse *albumbrowse;
|
|
927
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
928
|
+
int i = FIX2INT(index);
|
|
929
|
+
sp_track *track = NULL;
|
|
930
|
+
track = sp_albumbrowse_track(albumbrowse, i);
|
|
931
|
+
return track ? Data_Wrap_Struct(class_track, NULL, NULL, track) : Qnil;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/*
|
|
935
|
+
* call-seq: album_browse.num_copyrights -> fixnum or nil
|
|
936
|
+
*
|
|
937
|
+
*/
|
|
938
|
+
static VALUE album_browse_num_copyrights(VALUE self)
|
|
939
|
+
{
|
|
940
|
+
sp_albumbrowse *albumbrowse;
|
|
941
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
942
|
+
int n = sp_albumbrowse_num_copyrights(albumbrowse);
|
|
943
|
+
return (n >= 0) ? INT2FIX(n) : Qnil;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/*
|
|
947
|
+
* call-seq: album_browse.copyright(index) -> string or nil
|
|
948
|
+
*
|
|
949
|
+
*/
|
|
950
|
+
static VALUE album_browse_copyright(VALUE self, VALUE index)
|
|
951
|
+
{
|
|
952
|
+
sp_albumbrowse *albumbrowse;
|
|
953
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
954
|
+
int i = FIX2INT(index);
|
|
955
|
+
const char *c = sp_albumbrowse_copyright(albumbrowse, i);
|
|
956
|
+
return c ? rb_str_new2(c) : Qnil;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/*
|
|
960
|
+
* call-seq: album_browse.review -> string or nil
|
|
961
|
+
*
|
|
962
|
+
* Returns the review for the album browse object, or nil if no review is
|
|
963
|
+
* available.
|
|
964
|
+
*/
|
|
965
|
+
static VALUE album_browse_review(VALUE self)
|
|
966
|
+
{
|
|
967
|
+
sp_albumbrowse *albumbrowse;
|
|
968
|
+
Data_Get_Struct(self, sp_albumbrowse, albumbrowse);
|
|
969
|
+
const char *r = sp_albumbrowse_review(albumbrowse);
|
|
970
|
+
return r ? rb_str_new2(r) : Qnil;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
/*
|
|
974
|
+
* call-seq: artist.loaded? -> true or false
|
|
975
|
+
*
|
|
976
|
+
* Returns true if the artist is loaded, false otherwise.
|
|
977
|
+
*/
|
|
978
|
+
static VALUE artist_loaded(VALUE self)
|
|
979
|
+
{
|
|
980
|
+
sp_artist *artist;
|
|
981
|
+
Data_Get_Struct(self, sp_artist, artist);
|
|
982
|
+
return sp_artist_is_loaded(artist) ? Qtrue : Qfalse;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/*
|
|
986
|
+
* call-seq: artist.name -> string or nil
|
|
987
|
+
*
|
|
988
|
+
* Returns the artist's name.
|
|
989
|
+
*/
|
|
990
|
+
static VALUE artist_name(VALUE self)
|
|
991
|
+
{
|
|
992
|
+
sp_artist *artist;
|
|
993
|
+
Data_Get_Struct(self, sp_artist, artist);
|
|
994
|
+
const char *name = sp_artist_name(artist);
|
|
995
|
+
return name ? rb_str_new2(name) : Qnil;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/*
|
|
999
|
+
* call-seq: album.loaded? -> true or false
|
|
1000
|
+
*
|
|
1001
|
+
* Returns true if the album is loaded, false otherwise.
|
|
1002
|
+
*/
|
|
1003
|
+
static VALUE album_loaded(VALUE self)
|
|
1004
|
+
{
|
|
1005
|
+
sp_album *album;
|
|
1006
|
+
Data_Get_Struct(self, sp_album, album);
|
|
1007
|
+
return sp_album_is_loaded(album) ? Qtrue : Qfalse;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/*
|
|
1011
|
+
* call-seq: album.artist -> artist or nil
|
|
1012
|
+
*
|
|
1013
|
+
* Returns the album's artist.
|
|
1014
|
+
*/
|
|
1015
|
+
static VALUE album_artist(VALUE self)
|
|
1016
|
+
{
|
|
1017
|
+
sp_album *album;
|
|
1018
|
+
Data_Get_Struct(self, sp_album, album);
|
|
1019
|
+
sp_artist *artist = sp_album_artist(album);
|
|
1020
|
+
return artist ? Data_Wrap_Struct(class_artist, NULL, NULL, artist) : Qnil;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/*
|
|
1024
|
+
* call-seq: album.name -> string or nil
|
|
1025
|
+
*
|
|
1026
|
+
* Returns the album's name.
|
|
1027
|
+
*/
|
|
1028
|
+
static VALUE album_name(VALUE self)
|
|
1029
|
+
{
|
|
1030
|
+
sp_album *album;
|
|
1031
|
+
Data_Get_Struct(self, sp_album, album);
|
|
1032
|
+
const char *name = sp_album_name(album);
|
|
1033
|
+
return name ? rb_str_new2(name) : Qnil;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/*
|
|
1037
|
+
* call-seq: album.year -> fixnum or nil
|
|
1038
|
+
*
|
|
1039
|
+
* Returns the year the album was released.
|
|
1040
|
+
*/
|
|
1041
|
+
static VALUE album_year(VALUE self)
|
|
1042
|
+
{
|
|
1043
|
+
sp_album *album;
|
|
1044
|
+
Data_Get_Struct(self, sp_album, album);
|
|
1045
|
+
int year = sp_album_year(album);
|
|
1046
|
+
return year ? INF2FIX(year) : Qnil;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/*
|
|
1050
|
+
* call-seq: track.loaded? -> true or false
|
|
1051
|
+
*
|
|
1052
|
+
* Returns true if the track is loaded, false otherwise.
|
|
1053
|
+
*/
|
|
1054
|
+
static VALUE track_loaded(VALUE self)
|
|
1055
|
+
{
|
|
1056
|
+
sp_track *track;
|
|
1057
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1058
|
+
return sp_track_is_loaded(track) ? Qtrue : Qfalse;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/*
|
|
1062
|
+
* call-seq: track.error -> error
|
|
1063
|
+
*
|
|
1064
|
+
* Returns one of the constants defined in Error.
|
|
1065
|
+
*/
|
|
1066
|
+
static VALUE track_error(VALUE self)
|
|
1067
|
+
{
|
|
1068
|
+
sp_track *track;
|
|
1069
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1070
|
+
sp_error error = sp_track_error(track);
|
|
1071
|
+
return INT2FIX(error);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/*
|
|
1075
|
+
* call-seq: track.num_artists -> fixnum or nil
|
|
1076
|
+
*
|
|
1077
|
+
*/
|
|
1078
|
+
static VALUE track_num_artists(VALUE self)
|
|
1079
|
+
{
|
|
1080
|
+
sp_track *track;
|
|
1081
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1082
|
+
int n = sp_track_num_artists(track);
|
|
1083
|
+
return n ? INT2FIX(n) : Qnil;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/*
|
|
1087
|
+
* call-seq: track.artist(index) -> artist or nil
|
|
1088
|
+
*
|
|
1089
|
+
*/
|
|
1090
|
+
static VALUE track_artist(VALUE self, VALUE index)
|
|
1091
|
+
{
|
|
1092
|
+
sp_track *track;
|
|
1093
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1094
|
+
int i = FIX2INT(index);
|
|
1095
|
+
sp_artist *artist = sp_track_artist(track, i);
|
|
1096
|
+
return artist ? Data_Wrap_Struct(class_artist, NULL, NULL, artist) : Qnil;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
/*
|
|
1100
|
+
* call-seq: track.album -> album or nil
|
|
1101
|
+
*
|
|
1102
|
+
* Returns the track's album.
|
|
1103
|
+
*/
|
|
1104
|
+
static VALUE track_album(VALUE self)
|
|
1105
|
+
{
|
|
1106
|
+
sp_track *track;
|
|
1107
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1108
|
+
sp_album *album = sp_track_album(track);
|
|
1109
|
+
return album ? Data_Wrap_Struct(class_album, NULL, NULL, album) : Qnil;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
/*
|
|
1113
|
+
* call-seq: track.name -> string or nil
|
|
1114
|
+
*
|
|
1115
|
+
* Returns the track's name.
|
|
1116
|
+
*/
|
|
1117
|
+
static VALUE track_name(VALUE self)
|
|
1118
|
+
{
|
|
1119
|
+
sp_track *track;
|
|
1120
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1121
|
+
const char *name = sp_track_name(track);
|
|
1122
|
+
return name ? rb_str_new2(name) : Qnil;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/*
|
|
1126
|
+
* call-seq: track.duration -> fixnum
|
|
1127
|
+
*
|
|
1128
|
+
* Returns the track's duration in milliseconds.
|
|
1129
|
+
*/
|
|
1130
|
+
static VALUE track_duration(VALUE self)
|
|
1131
|
+
{
|
|
1132
|
+
sp_track *track;
|
|
1133
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1134
|
+
int d = sp_track_duration(track);
|
|
1135
|
+
return INT2FIX(d);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/*
|
|
1139
|
+
* call-seq: track.popularity -> fixnum
|
|
1140
|
+
*
|
|
1141
|
+
* Returns the track's popularity as a number in the range [0, 100].
|
|
1142
|
+
*/
|
|
1143
|
+
static VALUE track_popularity(VALUE self)
|
|
1144
|
+
{
|
|
1145
|
+
sp_track *track;
|
|
1146
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1147
|
+
int p = sp_track_popularity(track);
|
|
1148
|
+
return INT2FIX(p);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/*
|
|
1152
|
+
* call-seq: track.disc -> fixnum or nil
|
|
1153
|
+
*
|
|
1154
|
+
* Returns the index of the disc the track is on, counting from 1.
|
|
1155
|
+
*/
|
|
1156
|
+
static VALUE track_disc(VALUE self)
|
|
1157
|
+
{
|
|
1158
|
+
sp_track *track;
|
|
1159
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1160
|
+
int d = sp_track_disc(track);
|
|
1161
|
+
return d ? INT2FIX(d) : Qnil;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
/*
|
|
1165
|
+
* call-seq: track.index -> fixnum or nil
|
|
1166
|
+
*
|
|
1167
|
+
* Returns the index of the track on its disc, counting from 1.
|
|
1168
|
+
*/
|
|
1169
|
+
static VALUE track_index(VALUE self)
|
|
1170
|
+
{
|
|
1171
|
+
sp_track *track;
|
|
1172
|
+
Data_Get_Struct(self, sp_track, track);
|
|
1173
|
+
int i = sp_track_index(track);
|
|
1174
|
+
return i ? INT2FIX(i) : Qnil;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
static void link_free(void *link)
|
|
1178
|
+
{
|
|
1179
|
+
sp_link_release(link);
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
/*
|
|
1183
|
+
* call-seq:
|
|
1184
|
+
* Link.new(artist) -> link
|
|
1185
|
+
* Link.new(album) -> link
|
|
1186
|
+
* Link.new(track) -> link
|
|
1187
|
+
* Link.new(playlist) -> link
|
|
1188
|
+
* Link.new(search) -> link
|
|
1189
|
+
* Link.new(string) -> link or nil
|
|
1190
|
+
*
|
|
1191
|
+
* Returns a new link pointing to the given resource.
|
|
1192
|
+
*/
|
|
1193
|
+
static VALUE link_new(VALUE klass, VALUE object)
|
|
1194
|
+
{
|
|
1195
|
+
sp_link *link = NULL;
|
|
1196
|
+
|
|
1197
|
+
if(rb_obj_is_kind_of(object, class_artist))
|
|
1198
|
+
{
|
|
1199
|
+
sp_artist *a;
|
|
1200
|
+
Data_Get_Struct(object, sp_artist, a);
|
|
1201
|
+
link = sp_link_create_from_artist(a);
|
|
1202
|
+
}
|
|
1203
|
+
else if(rb_obj_is_kind_of(object, class_album))
|
|
1204
|
+
{
|
|
1205
|
+
sp_album *a;
|
|
1206
|
+
Data_Get_Struct(object, sp_album, a);
|
|
1207
|
+
link = sp_link_create_from_album(a);
|
|
1208
|
+
}
|
|
1209
|
+
else if(rb_obj_is_kind_of(object, class_track))
|
|
1210
|
+
{
|
|
1211
|
+
sp_track *t;
|
|
1212
|
+
Data_Get_Struct(object, sp_track, t);
|
|
1213
|
+
link = sp_link_create_from_track(t, 0); // TODO: offset
|
|
1214
|
+
}
|
|
1215
|
+
else if(rb_obj_is_kind_of(object, class_playlist))
|
|
1216
|
+
{
|
|
1217
|
+
sp_playlist *p;
|
|
1218
|
+
Data_Get_Struct(object, sp_playlist, p);
|
|
1219
|
+
link = sp_link_create_from_playlist(p);
|
|
1220
|
+
}
|
|
1221
|
+
else if(rb_obj_is_kind_of(object, class_search))
|
|
1222
|
+
{
|
|
1223
|
+
sp_search *s;
|
|
1224
|
+
Data_Get_Struct(object, sp_search, s);
|
|
1225
|
+
link = sp_link_create_from_search(s);
|
|
1226
|
+
}
|
|
1227
|
+
else
|
|
1228
|
+
{
|
|
1229
|
+
link = sp_link_create_from_string(StringValuePtr(object));
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
if(!link)
|
|
1233
|
+
return Qnil;
|
|
1234
|
+
|
|
1235
|
+
VALUE link_value = Data_Wrap_Struct(class_link, NULL, link_free, link);
|
|
1236
|
+
VALUE argv[1] = {object};
|
|
1237
|
+
rb_obj_call_init(link_value, 1, argv);
|
|
1238
|
+
return link_value;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
/*
|
|
1242
|
+
* call-seq: link.link_type -> type
|
|
1243
|
+
*
|
|
1244
|
+
* Returns the link type. Named link_type instead of just type to avoid
|
|
1245
|
+
* overriding a method in Object.
|
|
1246
|
+
*/
|
|
1247
|
+
static VALUE link_link_type(VALUE self)
|
|
1248
|
+
{
|
|
1249
|
+
sp_link *link;
|
|
1250
|
+
Data_Get_Struct(self, sp_link, link);
|
|
1251
|
+
int type = sp_link_type(link);
|
|
1252
|
+
return INT2FIX(type);
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
/*
|
|
1256
|
+
* call-seq: link.to_s -> string or nil
|
|
1257
|
+
*
|
|
1258
|
+
* Returns a string representation of the link.
|
|
1259
|
+
*/
|
|
1260
|
+
static VALUE link_to_s(VALUE self)
|
|
1261
|
+
{
|
|
1262
|
+
sp_link *link;
|
|
1263
|
+
Data_Get_Struct(self, sp_link, link);
|
|
1264
|
+
char buffer[100];
|
|
1265
|
+
int n = sp_link_as_string(link, buffer, 100);
|
|
1266
|
+
return (n < 100) ? rb_str_new2(buffer) : Qnil;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/*
|
|
1270
|
+
* call-seq: link.to_artist -> artist or nil
|
|
1271
|
+
*
|
|
1272
|
+
*/
|
|
1273
|
+
static VALUE link_to_artist(VALUE self)
|
|
1274
|
+
{
|
|
1275
|
+
sp_link *l;
|
|
1276
|
+
Data_Get_Struct(self, sp_link, l);
|
|
1277
|
+
sp_artist *a = sp_link_as_artist(l);
|
|
1278
|
+
return a ? Data_Wrap_Struct(class_artist, NULL, NULL, a) : Qnil;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/*
|
|
1282
|
+
* call-seq: link.to_album -> album or nil
|
|
1283
|
+
*
|
|
1284
|
+
*/
|
|
1285
|
+
static VALUE link_to_album(VALUE self)
|
|
1286
|
+
{
|
|
1287
|
+
sp_link *l;
|
|
1288
|
+
Data_Get_Struct(self, sp_link, l);
|
|
1289
|
+
sp_album *a = sp_link_as_album(l);
|
|
1290
|
+
return a ? Data_Wrap_Struct(class_album, NULL, NULL, a) : Qnil;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/*
|
|
1294
|
+
* call-seq: link.to_track -> track or nil
|
|
1295
|
+
*
|
|
1296
|
+
*/
|
|
1297
|
+
static VALUE link_to_track(VALUE self)
|
|
1298
|
+
{
|
|
1299
|
+
sp_link *l;
|
|
1300
|
+
Data_Get_Struct(self, sp_link, l);
|
|
1301
|
+
sp_track *t = sp_link_as_track(l);
|
|
1302
|
+
return t ? Data_Wrap_Struct(class_track, NULL, NULL, t) : Qnil;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
// init
|
|
1306
|
+
|
|
1307
|
+
void Init_greenstripes()
|
|
1308
|
+
{
|
|
1309
|
+
/*
|
|
1310
|
+
* GreenStripes
|
|
1311
|
+
*/
|
|
1312
|
+
module_greenstripes = rb_define_module("GreenStripes");
|
|
1313
|
+
|
|
1314
|
+
/*
|
|
1315
|
+
* The Error module defines constants for error codes returned by various
|
|
1316
|
+
* methods.
|
|
1317
|
+
*/
|
|
1318
|
+
module_error = rb_define_module_under(module_greenstripes, "Error");
|
|
1319
|
+
rb_define_const(module_error, "OK", INT2FIX(SP_ERROR_OK));
|
|
1320
|
+
rb_define_const(module_error, "BAD_API_VERSION", INT2FIX(SP_ERROR_BAD_API_VERSION));
|
|
1321
|
+
rb_define_const(module_error, "API_INITIALIZATION_FAILED", INT2FIX(SP_ERROR_API_INITIALIZATION_FAILED));
|
|
1322
|
+
rb_define_const(module_error, "TRACK_NOT_PLAYABLE", INT2FIX(SP_ERROR_TRACK_NOT_PLAYABLE));
|
|
1323
|
+
rb_define_const(module_error, "RESOURCE_NOT_LOADED", INT2FIX(SP_ERROR_RESOURCE_NOT_LOADED));
|
|
1324
|
+
rb_define_const(module_error, "BAD_APPLICATION_KEY", INT2FIX(SP_ERROR_BAD_APPLICATION_KEY));
|
|
1325
|
+
rb_define_const(module_error, "BAD_USERNAME_OR_PASSWORD", INT2FIX(SP_ERROR_BAD_USERNAME_OR_PASSWORD));
|
|
1326
|
+
rb_define_const(module_error, "USER_BANNED", INT2FIX(SP_ERROR_USER_BANNED));
|
|
1327
|
+
rb_define_const(module_error, "UNABLE_TO_CONTACT_SERVER", INT2FIX(SP_ERROR_UNABLE_TO_CONTACT_SERVER));
|
|
1328
|
+
rb_define_const(module_error, "CLIENT_TOO_OLD", INT2FIX(SP_ERROR_CLIENT_TOO_OLD));
|
|
1329
|
+
rb_define_const(module_error, "OTHER_PERMANENT", INT2FIX(SP_ERROR_CLIENT_TOO_OLD));
|
|
1330
|
+
rb_define_const(module_error, "BAD_USER_AGENT", INT2FIX(SP_ERROR_BAD_USER_AGENT));
|
|
1331
|
+
rb_define_const(module_error, "MISSING_CALLBACK", INT2FIX(SP_ERROR_MISSING_CALLBACK));
|
|
1332
|
+
rb_define_const(module_error, "INVALID_INDATA", INT2FIX(SP_ERROR_INVALID_INDATA));
|
|
1333
|
+
rb_define_const(module_error, "INDEX_OUT_OF_RANGE", INT2FIX(SP_ERROR_INDEX_OUT_OF_RANGE));
|
|
1334
|
+
rb_define_const(module_error, "USER_NEEDS_PREMIUM", INT2FIX(SP_ERROR_USER_NEEDS_PREMIUM));
|
|
1335
|
+
rb_define_const(module_error, "OTHER_TRANSIENT", INT2FIX(SP_ERROR_OTHER_TRANSIENT));
|
|
1336
|
+
rb_define_const(module_error, "IS_LOADING", INT2FIX(SP_ERROR_IS_LOADING));
|
|
1337
|
+
|
|
1338
|
+
/*
|
|
1339
|
+
* The ConnectionState module defines constants describing the current state
|
|
1340
|
+
* of a connection.
|
|
1341
|
+
*/
|
|
1342
|
+
module_connection_state = rb_define_module_under(module_greenstripes, "ConnectionState");
|
|
1343
|
+
rb_define_const(module_connection_state, "LOGGED_OUT", INT2FIX(SP_CONNECTION_STATE_LOGGED_OUT));
|
|
1344
|
+
rb_define_const(module_connection_state, "LOGGED_IN", INT2FIX(SP_CONNECTION_STATE_LOGGED_IN));
|
|
1345
|
+
rb_define_const(module_connection_state, "DISCONNECTED", INT2FIX(SP_CONNECTION_STATE_DISCONNECTED));
|
|
1346
|
+
rb_define_const(module_connection_state, "UNDEFINED", INT2FIX(SP_CONNECTION_STATE_UNDEFINED));
|
|
1347
|
+
|
|
1348
|
+
/*
|
|
1349
|
+
* The LinkType module defines constants for link types.
|
|
1350
|
+
*/
|
|
1351
|
+
module_link_type = rb_define_module_under(module_greenstripes, "LinkType");
|
|
1352
|
+
rb_define_const(module_link_type, "INVALID", INT2FIX(SP_LINKTYPE_INVALID));
|
|
1353
|
+
rb_define_const(module_link_type, "TRACK", INT2FIX(SP_LINKTYPE_TRACK));
|
|
1354
|
+
rb_define_const(module_link_type, "ALBUM", INT2FIX(SP_LINKTYPE_ALBUM));
|
|
1355
|
+
rb_define_const(module_link_type, "ARTIST", INT2FIX(SP_LINKTYPE_ARTIST));
|
|
1356
|
+
rb_define_const(module_link_type, "SEARCH", INT2FIX(SP_LINKTYPE_SEARCH));
|
|
1357
|
+
rb_define_const(module_link_type, "PLAYLIST", INT2FIX(SP_LINKTYPE_PLAYLIST));
|
|
1358
|
+
|
|
1359
|
+
/*
|
|
1360
|
+
* Session
|
|
1361
|
+
*/
|
|
1362
|
+
class_session = rb_define_class_under(module_greenstripes, "Session", rb_cObject);
|
|
1363
|
+
rb_define_singleton_method(class_session, "new", session_new, 4);
|
|
1364
|
+
rb_define_method(class_session, "login", session_login, 2);
|
|
1365
|
+
rb_define_method(class_session, "logout", session_logout, 0);
|
|
1366
|
+
rb_define_method(class_session, "connection_state", session_connection_state, 0);
|
|
1367
|
+
rb_define_method(class_session, "process_events", session_process_events, 0);
|
|
1368
|
+
rb_define_method(class_session, "user", session_user, 0);
|
|
1369
|
+
rb_define_method(class_session, "playlist_container", session_playlist_container, 0);
|
|
1370
|
+
|
|
1371
|
+
/*
|
|
1372
|
+
* User
|
|
1373
|
+
*/
|
|
1374
|
+
class_user = rb_define_class_under(module_greenstripes, "User", rb_cObject);
|
|
1375
|
+
rb_define_method(class_user, "loaded?", user_loaded, 0);
|
|
1376
|
+
rb_define_method(class_user, "canonical_name", user_canonical_name, 0);
|
|
1377
|
+
rb_define_method(class_user, "display_name", user_display_name, 0);
|
|
1378
|
+
|
|
1379
|
+
/*
|
|
1380
|
+
* PlaylistContainer
|
|
1381
|
+
*/
|
|
1382
|
+
class_playlist_container = rb_define_class_under(module_greenstripes, "PlaylistContainer", rb_cObject);
|
|
1383
|
+
rb_define_method(class_playlist_container, "num_playlists", playlist_container_num_playlists, 0);
|
|
1384
|
+
rb_define_method(class_playlist_container, "playlist", playlist_container_playlist, 1);
|
|
1385
|
+
rb_define_method(class_playlist_container, "add_new_playlist", playlist_container_add_new_playlist, 1);
|
|
1386
|
+
rb_define_method(class_playlist_container, "add_playlist", playlist_container_add_playlist, 1);
|
|
1387
|
+
rb_define_method(class_playlist_container, "remove_playlist", playlist_container_remove_playlist, 1);
|
|
1388
|
+
rb_define_method(class_playlist_container, "move_playlist", playlist_container_move_playlist, 2);
|
|
1389
|
+
|
|
1390
|
+
/*
|
|
1391
|
+
* Playlist
|
|
1392
|
+
*/
|
|
1393
|
+
class_playlist = rb_define_class_under(module_greenstripes, "Playlist", rb_cObject);
|
|
1394
|
+
rb_define_method(class_playlist, "loaded?", playlist_loaded, 0);
|
|
1395
|
+
rb_define_method(class_playlist, "name", playlist_name, 0);
|
|
1396
|
+
rb_define_method(class_playlist, "name=", playlist_name_set, 1);
|
|
1397
|
+
rb_define_method(class_playlist, "owner", playlist_owner, 0);
|
|
1398
|
+
rb_define_method(class_playlist, "collaborative?", playlist_collaborative, 0);
|
|
1399
|
+
rb_define_method(class_playlist, "collaborative=", playlist_collaborative_set, 1);
|
|
1400
|
+
rb_define_method(class_playlist, "num_tracks", playlist_num_tracks, 0);
|
|
1401
|
+
rb_define_method(class_playlist, "track", playlist_track, 1);
|
|
1402
|
+
rb_define_method(class_playlist, "pending_changes?", playlist_pending_changes, 0);
|
|
1403
|
+
rb_define_method(class_playlist, "add_tracks", playlist_add_tracks, 2);
|
|
1404
|
+
rb_define_method(class_playlist, "remove_tracks", playlist_remove_tracks, 1);
|
|
1405
|
+
rb_define_method(class_playlist, "reorder_tracks", playlist_reorder_tracks, 2);
|
|
1406
|
+
|
|
1407
|
+
/*
|
|
1408
|
+
* Search
|
|
1409
|
+
*/
|
|
1410
|
+
class_search = rb_define_class_under(module_greenstripes, "Search", rb_cObject);
|
|
1411
|
+
rb_define_singleton_method(class_search, "new", search_new, 4);
|
|
1412
|
+
rb_define_method(class_search, "loaded?", search_loaded, 0);
|
|
1413
|
+
rb_define_method(class_search, "error", search_error, 0);
|
|
1414
|
+
rb_define_method(class_search, "num_artists", search_num_artists, 0);
|
|
1415
|
+
rb_define_method(class_search, "artist", search_artist, 1);
|
|
1416
|
+
rb_define_method(class_search, "num_albums", search_num_albums, 0);
|
|
1417
|
+
rb_define_method(class_search, "album", search_album, 1);
|
|
1418
|
+
rb_define_method(class_search, "num_tracks", search_num_tracks, 0);
|
|
1419
|
+
rb_define_method(class_search, "track", search_track, 1);
|
|
1420
|
+
rb_define_method(class_search, "total_tracks", search_total_tracks, 0);
|
|
1421
|
+
rb_define_method(class_search, "query", search_query, 0);
|
|
1422
|
+
rb_define_method(class_search, "did_you_mean", search_did_you_mean, 0);
|
|
1423
|
+
|
|
1424
|
+
/*
|
|
1425
|
+
* ArtistBrowse
|
|
1426
|
+
*/
|
|
1427
|
+
class_artist_browse = rb_define_class_under(module_greenstripes, "ArtistBrowse", rb_cObject);
|
|
1428
|
+
rb_define_singleton_method(class_artist_browse, "new", artist_browse_new, 2);
|
|
1429
|
+
rb_define_method(class_artist_browse, "loaded?", artist_browse_loaded, 0);
|
|
1430
|
+
rb_define_method(class_artist_browse, "error", artist_browse_error, 0);
|
|
1431
|
+
rb_define_method(class_artist_browse, "artist", artist_browse_artist, 0);
|
|
1432
|
+
rb_define_method(class_artist_browse, "num_tracks", artist_browse_num_tracks, 0);
|
|
1433
|
+
rb_define_method(class_artist_browse, "track", artist_browse_track, 1);
|
|
1434
|
+
rb_define_method(class_artist_browse, "num_similar_artists", artist_browse_num_similar_artists, 0);
|
|
1435
|
+
rb_define_method(class_artist_browse, "similar_artist", artist_browse_similar_artist, 1);
|
|
1436
|
+
rb_define_method(class_artist_browse, "biography", artist_browse_biography, 0);
|
|
1437
|
+
|
|
1438
|
+
/*
|
|
1439
|
+
* AlbumBrowse
|
|
1440
|
+
*/
|
|
1441
|
+
class_album_browse = rb_define_class_under(module_greenstripes, "AlbumBrowse", rb_cObject);
|
|
1442
|
+
rb_define_singleton_method(class_album_browse, "new", album_browse_new, 2);
|
|
1443
|
+
rb_define_method(class_album_browse, "loaded?", album_browse_loaded, 0);
|
|
1444
|
+
rb_define_method(class_album_browse, "error", album_browse_error, 0);
|
|
1445
|
+
rb_define_method(class_album_browse, "artist", album_browse_artist, 0);
|
|
1446
|
+
rb_define_method(class_album_browse, "album", album_browse_album, 0);
|
|
1447
|
+
rb_define_method(class_album_browse, "num_tracks", album_browse_num_tracks, 0);
|
|
1448
|
+
rb_define_method(class_album_browse, "track", album_browse_track, 1);
|
|
1449
|
+
rb_define_method(class_album_browse, "num_copyrights", album_browse_num_copyrights, 0);
|
|
1450
|
+
rb_define_method(class_album_browse, "copyright", album_browse_copyright, 1);
|
|
1451
|
+
rb_define_method(class_album_browse, "review", album_browse_review, 0);
|
|
1452
|
+
|
|
1453
|
+
/*
|
|
1454
|
+
* Artist
|
|
1455
|
+
*/
|
|
1456
|
+
class_artist = rb_define_class_under(module_greenstripes, "Artist", rb_cObject);
|
|
1457
|
+
rb_define_method(class_artist, "loaded?", artist_loaded, 0);
|
|
1458
|
+
rb_define_method(class_artist, "name", artist_name, 0);
|
|
1459
|
+
|
|
1460
|
+
/*
|
|
1461
|
+
* Album
|
|
1462
|
+
*/
|
|
1463
|
+
class_album = rb_define_class_under(module_greenstripes, "Album", rb_cObject);
|
|
1464
|
+
rb_define_method(class_album, "loaded?", album_loaded, 0);
|
|
1465
|
+
rb_define_method(class_album, "artist", album_artist, 0);
|
|
1466
|
+
rb_define_method(class_album, "name", album_name, 0);
|
|
1467
|
+
rb_define_method(class_album, "year", album_year, 0);
|
|
1468
|
+
|
|
1469
|
+
/*
|
|
1470
|
+
* Track
|
|
1471
|
+
*/
|
|
1472
|
+
class_track = rb_define_class_under(module_greenstripes, "Track", rb_cObject);
|
|
1473
|
+
rb_define_method(class_track, "loaded?", track_loaded, 0);
|
|
1474
|
+
rb_define_method(class_track, "error", track_error, 0);
|
|
1475
|
+
rb_define_method(class_track, "num_artists", track_num_artists, 0);
|
|
1476
|
+
rb_define_method(class_track, "artist", track_artist, 1);
|
|
1477
|
+
rb_define_method(class_track, "album", track_album, 0);
|
|
1478
|
+
rb_define_method(class_track, "name", track_name, 0);
|
|
1479
|
+
rb_define_method(class_track, "duration", track_duration, 0);
|
|
1480
|
+
rb_define_method(class_track, "popularity", track_popularity, 0);
|
|
1481
|
+
rb_define_method(class_track, "disc", track_disc, 0);
|
|
1482
|
+
rb_define_method(class_track, "index", track_index, 0);
|
|
1483
|
+
|
|
1484
|
+
/*
|
|
1485
|
+
* Link
|
|
1486
|
+
*/
|
|
1487
|
+
class_link = rb_define_class_under(module_greenstripes, "Link", rb_cObject);
|
|
1488
|
+
rb_define_singleton_method(class_link, "new", link_new, 1);
|
|
1489
|
+
rb_define_method(class_link, "link_type", link_link_type, 0);
|
|
1490
|
+
rb_define_method(class_link, "to_s", link_to_s, 0);
|
|
1491
|
+
rb_define_method(class_link, "to_artist", link_to_artist, 0);
|
|
1492
|
+
rb_define_method(class_link, "to_album", link_to_album, 0);
|
|
1493
|
+
rb_define_method(class_link, "to_track", link_to_track, 0);
|
|
1494
|
+
}
|