rbpod 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +9 -9
- data/Rakefile +5 -3
- data/ext/rbpod/collection.c +58 -60
- data/ext/rbpod/collection.h +1 -3
- data/ext/rbpod/database.c +46 -15
- data/ext/rbpod/device.c +2 -1
- data/ext/rbpod/error.c +27 -0
- data/ext/rbpod/error.h +12 -0
- data/ext/rbpod/playlist.c +14 -22
- data/ext/rbpod/playlist_collection.c +74 -41
- data/ext/rbpod/playlist_collection.h +1 -5
- data/ext/rbpod/rbpod.c +35 -23
- data/ext/rbpod/rbpod.h +3 -1
- data/ext/rbpod/track_collection.c +38 -10
- data/ext/rbpod/track_collection.h +1 -5
- data/lib/rbpod/version.rb +1 -1
- data/spec/rbpod/collection_spec.rb +25 -0
- data/spec/{database_spec.rb → rbpod/database_spec.rb} +14 -21
- data/spec/rbpod/device_spec.rb +70 -0
- data/spec/rbpod/playlist_collection_spec.rb +44 -0
- data/spec/{playlist_spec.rb → rbpod/playlist_spec.rb} +1 -1
- data/spec/rbpod/track_collection_spec.rb +15 -0
- data/spec/{track_spec.rb → rbpod/track_spec.rb} +1 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/support/shared_contexts.rb +18 -0
- metadata +24 -16
- data/spec/collection_spec.rb +0 -39
- data/spec/device_spec.rb +0 -83
- /data/spec/{rbpod_spec.rb → rbpod/rbpod_spec.rb} +0 -0
data/README.md
CHANGED
@@ -70,12 +70,12 @@ device['PotsdamConf45'] = "Kilroy Was Here"
|
|
70
70
|
device.save!
|
71
71
|
```
|
72
72
|
|
73
|
-
### RbPod::
|
73
|
+
### RbPod::PlaylistCollection
|
74
74
|
|
75
|
-
|
75
|
+
You can get direct access to the playlists on the device:
|
76
76
|
|
77
77
|
```ruby
|
78
|
-
database.playlists # => #<RbPod::
|
78
|
+
database.playlists # => #<RbPod::PlaylistCollection:0xdeadbeef>
|
79
79
|
|
80
80
|
# For a list of all the names of playlists on the iPod:
|
81
81
|
database.playlists.map(&:name) # => ["iPod", "Podcasts", "Recently Added"]
|
@@ -83,8 +83,8 @@ database.playlists.map(&:name) # => ["iPod", "Podcasts", "Recently Added"]
|
|
83
83
|
# For direct access to the master playlist:
|
84
84
|
database.playlists.master # => #<RbPod::Playlist:0xdeadbeef>
|
85
85
|
|
86
|
-
# For direct access to the
|
87
|
-
database.playlists.
|
86
|
+
# For direct access to the podcast playlist:
|
87
|
+
database.playlists.podcast # => #<RbPod::Playlist:0xdeadbeef>
|
88
88
|
```
|
89
89
|
|
90
90
|
### RbPod::Playlist
|
@@ -98,11 +98,11 @@ playlist.name # => "iPod"
|
|
98
98
|
playlist.length # => 400
|
99
99
|
playlist.created_on # => 2008-04-05 08:47:46 -0700
|
100
100
|
|
101
|
-
playlist.
|
102
|
-
playlist.
|
103
|
-
playlist.
|
101
|
+
playlist.master? # => true
|
102
|
+
playlist.smart? # => false
|
103
|
+
playlist.podcast? # => false
|
104
104
|
|
105
|
-
playlist.tracks # => #<RbPod::
|
105
|
+
playlist.tracks # => #<RbPod::TrackCollection:0xdeadbeef>
|
106
106
|
```
|
107
107
|
|
108
108
|
### RbPod::Track
|
data/Rakefile
CHANGED
@@ -13,8 +13,8 @@ require 'rspec/core/rake_task'
|
|
13
13
|
# Bring in RDoc's built-in rake task.
|
14
14
|
require 'rdoc/task'
|
15
15
|
|
16
|
-
# By default,
|
17
|
-
task :default => [ :
|
16
|
+
# By default, run rspec tests.
|
17
|
+
task :default => [ :test ]
|
18
18
|
|
19
19
|
# Let Rake know what is safe to remove.
|
20
20
|
CLEAN.include [ 'pkg/*', 'doc/*' ]
|
@@ -27,7 +27,7 @@ Rake::ExtensionTask.new do |extension|
|
|
27
27
|
extension.lib_dir = 'lib/rbpod'
|
28
28
|
|
29
29
|
# Monitor sources for change tracking.
|
30
|
-
extension.source_pattern = '*.
|
30
|
+
extension.source_pattern = '*.[ch]'
|
31
31
|
end
|
32
32
|
|
33
33
|
desc "Run all available RSpec tests."
|
@@ -36,6 +36,8 @@ RSpec::Core::RakeTask.new(:test) do |task|
|
|
36
36
|
# Execute ruby with warnings enabled.
|
37
37
|
task.ruby_opts = '-w'
|
38
38
|
end
|
39
|
+
# Make compilation a prerequisite of testing.
|
40
|
+
Rake::Task[:test].prerequisites << :compile
|
39
41
|
|
40
42
|
desc "Build all RDoc documentation."
|
41
43
|
RDoc::Task.new(:rdoc) do |task|
|
data/ext/rbpod/collection.c
CHANGED
@@ -3,37 +3,28 @@
|
|
3
3
|
#include "rbpod.h"
|
4
4
|
#include "collection.h"
|
5
5
|
|
6
|
-
struct collection {
|
7
|
-
VALUE klass;
|
8
|
-
GList *list;
|
9
|
-
};
|
10
|
-
|
11
|
-
inline VALUE rbpod_collection_create(GList *list, VALUE type)
|
12
|
-
{
|
13
|
-
struct collection *collection = ALLOC(struct collection);
|
14
|
-
collection->list = list;
|
15
|
-
collection->klass = type;
|
16
|
-
return Data_Wrap_Struct(cRbPodCollection, NULL, NULL, (void *) collection);
|
17
|
-
}
|
18
|
-
|
19
6
|
/*
|
20
7
|
* call-seq:
|
21
8
|
* [](index) -> Object or nil
|
22
9
|
*
|
23
|
-
*
|
10
|
+
* Given an integer +index+, return the item at that position in the collection.
|
24
11
|
*/
|
25
12
|
static VALUE rbpod_collection_get(VALUE self, VALUE key)
|
26
13
|
{
|
27
|
-
|
28
|
-
|
14
|
+
GList *current = NULL, *collection = TYPED_DATA_PTR(self, GList);
|
15
|
+
VALUE klass = rb_funcall(self, rb_intern("type"), 0);
|
29
16
|
|
30
17
|
if (FIXNUM_P(key) == FALSE) {
|
31
18
|
return Qnil;
|
32
19
|
}
|
33
20
|
|
34
|
-
current = g_list_nth(collection
|
21
|
+
current = g_list_nth(collection, FIX2INT(key));
|
35
22
|
|
36
|
-
|
23
|
+
if (current == NULL) {
|
24
|
+
return Qnil;
|
25
|
+
}
|
26
|
+
|
27
|
+
return rb_class_new_instance_with_data(0, NULL, klass, current->data);
|
37
28
|
}
|
38
29
|
|
39
30
|
/*
|
@@ -44,14 +35,15 @@ static VALUE rbpod_collection_get(VALUE self, VALUE key)
|
|
44
35
|
*/
|
45
36
|
static VALUE rbpod_collection_last(VALUE self)
|
46
37
|
{
|
47
|
-
|
48
|
-
GList *
|
38
|
+
VALUE klass = rb_funcall(self, rb_intern("type"), 0);
|
39
|
+
GList *collection = TYPED_DATA_PTR(self, GList);
|
40
|
+
GList *current = g_list_last(collection);
|
49
41
|
|
50
42
|
if (current == NULL) {
|
51
43
|
return Qnil;
|
52
44
|
}
|
53
45
|
|
54
|
-
return
|
46
|
+
return rb_class_new_instance_with_data(0, NULL, klass, current->data);
|
55
47
|
}
|
56
48
|
|
57
49
|
/*
|
@@ -62,26 +54,27 @@ static VALUE rbpod_collection_last(VALUE self)
|
|
62
54
|
*/
|
63
55
|
static VALUE rbpod_collection_first(VALUE self)
|
64
56
|
{
|
65
|
-
|
66
|
-
GList *
|
57
|
+
VALUE klass = rb_funcall(self, rb_intern("type"), 0);
|
58
|
+
GList *collection = TYPED_DATA_PTR(self, GList);
|
59
|
+
GList *current = g_list_first(collection);
|
67
60
|
|
68
61
|
if (current == NULL) {
|
69
62
|
return Qnil;
|
70
63
|
}
|
71
64
|
|
72
|
-
return
|
65
|
+
return rb_class_new_instance_with_data(0, NULL, klass, current->data);
|
73
66
|
}
|
74
67
|
|
75
68
|
/*
|
76
69
|
* call-seq:
|
77
|
-
*
|
70
|
+
* size() -> Integer
|
78
71
|
*
|
79
72
|
* Return the total length of all items in the collection.
|
80
73
|
*/
|
81
|
-
static VALUE
|
74
|
+
static VALUE rbpod_collection_size(VALUE self)
|
82
75
|
{
|
83
|
-
|
84
|
-
return INT2NUM(g_list_length(collection
|
76
|
+
GList *collection = TYPED_DATA_PTR(self, GList);
|
77
|
+
return INT2NUM(g_list_length(collection));
|
85
78
|
}
|
86
79
|
|
87
80
|
/*
|
@@ -95,19 +88,25 @@ static VALUE rbpod_collection_length(VALUE self)
|
|
95
88
|
*/
|
96
89
|
static VALUE rbpod_collection_each(VALUE self, VALUE argv)
|
97
90
|
{
|
98
|
-
|
99
|
-
VALUE item
|
100
|
-
GList *current = NULL;
|
91
|
+
GList *current = NULL, *collection = TYPED_DATA_PTR(self, GList);
|
92
|
+
VALUE klass, item, arguments;
|
101
93
|
|
102
94
|
/* Return an enumerator if a block was not supplied. */
|
103
95
|
RETURN_ENUMERATOR(self, 0, 0);
|
104
96
|
|
97
|
+
/* What sort of items are we casting this data to? */
|
98
|
+
klass = rb_funcall(self, rb_intern("type"), 0);
|
99
|
+
|
100
|
+
/* Create a shallow copy of the passed arguments. */
|
101
|
+
arguments = rb_ary_dup(argv);
|
102
|
+
|
105
103
|
/* Prepend an empty element as a placeholder. */
|
106
104
|
rb_ary_unshift(arguments, Qnil);
|
107
105
|
|
108
106
|
/* If we were supplied a block, enumerate the entire list. */
|
109
|
-
for (current = collection
|
110
|
-
|
107
|
+
for (current = collection; current != NULL; current = g_list_next(current)) {
|
108
|
+
/* TODO: Find a better workaround than this or Data_Wrap_Struct. */
|
109
|
+
item = rb_class_new_instance_with_data(0, NULL, klass, current->data);
|
111
110
|
rb_ary_store(arguments, 0, item);
|
112
111
|
rb_yield_splat(arguments);
|
113
112
|
}
|
@@ -115,24 +114,28 @@ static VALUE rbpod_collection_each(VALUE self, VALUE argv)
|
|
115
114
|
return self;
|
116
115
|
}
|
117
116
|
|
118
|
-
|
117
|
+
/*
|
118
|
+
* :nodoc:
|
119
|
+
*/
|
120
|
+
static VALUE rbpod_collection_type(VALUE self)
|
119
121
|
{
|
120
|
-
|
121
|
-
|
122
|
-
if (collection->list != NULL) {
|
123
|
-
g_list_free(collection->list);
|
124
|
-
}
|
125
|
-
|
126
|
-
xfree(handle);
|
127
|
-
return;
|
122
|
+
/* We should get an error if we try to create an instance of NilClass. */
|
123
|
+
return Qnil;
|
128
124
|
}
|
129
125
|
|
130
|
-
|
126
|
+
/*
|
127
|
+
* :nodoc:
|
128
|
+
*/
|
129
|
+
static VALUE rbpod_collection_included(VALUE self, VALUE other)
|
131
130
|
{
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
131
|
+
/* Collections should be Enumerable and Comparable. */
|
132
|
+
rb_include_module(other, rb_mEnumerable);
|
133
|
+
rb_include_module(other, rb_mComparable);
|
134
|
+
|
135
|
+
/* Override Enumerable with our methods. */
|
136
|
+
rb_extend_object(other, self);
|
137
|
+
|
138
|
+
return self;
|
136
139
|
}
|
137
140
|
|
138
141
|
void Init_rbpod_collection(void)
|
@@ -140,22 +143,17 @@ void Init_rbpod_collection(void)
|
|
140
143
|
#if RDOC_CAN_PARSE_DOCUMENTATION
|
141
144
|
mRbPod = rb_define_module("RbPod");
|
142
145
|
#endif
|
143
|
-
|
144
|
-
|
145
|
-
rb_define_alloc_func(cRbPodCollection, rbpod_collection_allocate);
|
146
|
-
|
147
|
-
rb_include_module(cRbPodCollection, rb_mEnumerable);
|
148
|
-
rb_include_module(cRbPodCollection, rb_mComparable);
|
146
|
+
mRbPodCollection = rb_define_module_under(mRbPod, "Collection");
|
149
147
|
|
150
|
-
|
148
|
+
rb_define_singleton_method(mRbPodCollection, "included", rbpod_collection_included, 1);
|
151
149
|
|
152
|
-
|
150
|
+
rb_define_private_method(mRbPodCollection, "type", rbpod_collection_type, 0);
|
153
151
|
|
154
|
-
|
155
|
-
|
152
|
+
rb_define_method(mRbPodCollection, "each", rbpod_collection_each, -2);
|
153
|
+
rb_define_method(mRbPodCollection, "size", rbpod_collection_size, 0);
|
156
154
|
|
157
|
-
rb_define_method(
|
158
|
-
rb_define_method(
|
155
|
+
rb_define_method(mRbPodCollection, "first", rbpod_collection_first, 0);
|
156
|
+
rb_define_method(mRbPodCollection, "last", rbpod_collection_last, 0);
|
159
157
|
|
160
|
-
rb_define_method(
|
158
|
+
rb_define_method(mRbPodCollection, "[]", rbpod_collection_get, 1);
|
161
159
|
}
|
data/ext/rbpod/collection.h
CHANGED
@@ -3,10 +3,8 @@
|
|
3
3
|
#ifndef RBPOD_COLLECTION_H
|
4
4
|
#define RBPOD_COLLECTION_H
|
5
5
|
|
6
|
-
RUBY_EXTERN VALUE
|
6
|
+
RUBY_EXTERN VALUE mRbPodCollection;
|
7
7
|
|
8
8
|
void Init_rbpod_collection(void);
|
9
9
|
|
10
|
-
inline VALUE rbpod_collection_create(GList *list, VALUE type);
|
11
|
-
|
12
10
|
#endif /* RBPOD_COLLECTION_H */
|
data/ext/rbpod/database.c
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
/* database.c */
|
2
2
|
|
3
3
|
#include "rbpod.h"
|
4
|
+
#include "error.h"
|
4
5
|
#include "device.h"
|
5
6
|
#include "database.h"
|
7
|
+
#include "playlist.h"
|
6
8
|
#include "track_collection.h"
|
7
9
|
#include "playlist_collection.h"
|
8
10
|
|
@@ -39,22 +41,26 @@ static VALUE rbpod_database_synchronized_p(VALUE self)
|
|
39
41
|
|
40
42
|
/*
|
41
43
|
* call-seq:
|
42
|
-
* playlists() -> RbPod::
|
44
|
+
* playlists() -> RbPod::PlaylistCollection
|
43
45
|
*
|
44
46
|
* Returns a collection of all playlists added to this database.
|
45
47
|
*/
|
46
48
|
static VALUE rbpod_database_playlists_get(VALUE self)
|
47
49
|
{
|
48
|
-
|
49
|
-
return rbpod_playlist_collection_create(self, database->playlists);
|
50
|
+
return rb_class_new_instance(1, &self, cRbPodPlaylistCollection);
|
50
51
|
}
|
51
52
|
|
53
|
+
/*
|
54
|
+
* call-seq:
|
55
|
+
* tracks() -> RbPod::TrackCollection
|
56
|
+
*
|
57
|
+
* Returns a collection of all tracks added to this database.
|
58
|
+
*/
|
52
59
|
static VALUE rbpod_database_tracks_get(VALUE self)
|
53
60
|
{
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
return rbpod_track_collection_create(parent, database->tracks);
|
61
|
+
VALUE playlists = rbpod_database_playlists_get(self);
|
62
|
+
VALUE master = rb_funcall(playlists, rb_intern("master"), 0);
|
63
|
+
return rb_class_new_instance(1, &master, cRbPodTrackCollection);
|
58
64
|
}
|
59
65
|
|
60
66
|
/*
|
@@ -93,6 +99,9 @@ static VALUE rbpod_database_version_get(VALUE self)
|
|
93
99
|
return INT2NUM(database->version);
|
94
100
|
}
|
95
101
|
|
102
|
+
/*
|
103
|
+
* :nodoc:
|
104
|
+
*/
|
96
105
|
static VALUE rbpod_database_id_get(VALUE self)
|
97
106
|
{
|
98
107
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
@@ -112,6 +121,9 @@ static VALUE rbpod_database_mountpoint_get(VALUE self)
|
|
112
121
|
return rb_class_new_instance(1, &mount_point, rb_cPathname);
|
113
122
|
}
|
114
123
|
|
124
|
+
/*
|
125
|
+
* :nodoc:
|
126
|
+
*/
|
115
127
|
static VALUE rbpod_database_mountpoint_set(VALUE self, VALUE path)
|
116
128
|
{
|
117
129
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
@@ -137,6 +149,12 @@ static VALUE rbpod_database_initialize(VALUE self, VALUE mount_point)
|
|
137
149
|
Itdb_iTunesDB *previous = database;
|
138
150
|
GError *error = NULL;
|
139
151
|
|
152
|
+
/* Check if the mount point is a directory. */
|
153
|
+
if (rb_file_directory_p(rb_cFile, mount_point) != Qtrue) {
|
154
|
+
rb_raise(eRbPodError, "The mount point must be a directory!");
|
155
|
+
return Qnil;
|
156
|
+
}
|
157
|
+
|
140
158
|
/* Try to parse the database from the given mount point. */
|
141
159
|
database = itdb_parse(StringValueCStr(mount_point), &error);
|
142
160
|
|
@@ -170,6 +188,7 @@ static VALUE rbpod_database_allocate(VALUE self)
|
|
170
188
|
static VALUE rbpod_database_create(int argc, VALUE *argv, VALUE self)
|
171
189
|
{
|
172
190
|
gchar *_mount_point, *_device_name, *_model_number;
|
191
|
+
VALUE model_matcher, model_regexp, ignorecase;
|
173
192
|
VALUE mount_point, device_name, model_number;
|
174
193
|
GError *error = NULL;
|
175
194
|
|
@@ -185,19 +204,30 @@ static VALUE rbpod_database_create(int argc, VALUE *argv, VALUE self)
|
|
185
204
|
}
|
186
205
|
|
187
206
|
/* If we didn't specify a device name, default to 'iPod'. */
|
188
|
-
if (RTEST(device_name)
|
189
|
-
rb_raise(eRbPodError, "Device name should be a string of at least three characters.");
|
190
|
-
return Qnil;
|
191
|
-
} else {
|
207
|
+
if (RTEST(device_name) == FALSE) {
|
192
208
|
device_name = rb_str_new2("iPod");
|
193
209
|
}
|
194
210
|
|
195
|
-
/*
|
196
|
-
if (
|
197
|
-
rb_raise(eRbPodError, "
|
211
|
+
/* Ensure it's a valid device name, if it was given. */
|
212
|
+
if (TYPE(device_name) == T_STRING && RSTRING_LEN(device_name) == 0) {
|
213
|
+
rb_raise(eRbPodError, "Device name must not be an empty string.");
|
198
214
|
return Qnil;
|
199
215
|
}
|
200
216
|
|
217
|
+
/* If a model number was given, ensure it's a string. */
|
218
|
+
if (RTEST(model_number)) {
|
219
|
+
Check_Type(device_name, T_STRING);
|
220
|
+
|
221
|
+
model_matcher = rb_str_new2("/x?[A-Z][0-9]{3}/");
|
222
|
+
ignorecase = rb_const_get(rb_cRegexp, rb_intern("IGNORECASE"));
|
223
|
+
model_regexp = rb_reg_new_str(model_matcher, ignorecase);
|
224
|
+
|
225
|
+
if (RTEST(rb_reg_match(model_regexp, model_number)) == FALSE) {
|
226
|
+
rb_raise(eRbPodError, "Model number must be a string matching: /x?[A-Z][0-9]{3}/i");
|
227
|
+
return Qnil;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
201
231
|
/* Extract pointers for glib use. */
|
202
232
|
_mount_point = StringValueCStr(mount_point);
|
203
233
|
_device_name = StringValueCStr(device_name);
|
@@ -228,7 +258,6 @@ void Init_rbpod_database(void)
|
|
228
258
|
rb_define_singleton_method(cRbPodDatabase, "create!", rbpod_database_create, -1);
|
229
259
|
|
230
260
|
rb_define_private_method(cRbPodDatabase, "id", rbpod_database_id_get, 0);
|
231
|
-
rb_define_private_method(cRbPodDatabase, "tracks", rbpod_database_tracks_get, 0);
|
232
261
|
rb_define_private_method(cRbPodDatabase, "mountpoint=", rbpod_database_mountpoint_set, 1);
|
233
262
|
|
234
263
|
rb_define_method(cRbPodDatabase, "mountpoint", rbpod_database_mountpoint_get, 0);
|
@@ -237,6 +266,8 @@ void Init_rbpod_database(void)
|
|
237
266
|
rb_define_method(cRbPodDatabase, "filename", rbpod_database_filename_get, 0);
|
238
267
|
|
239
268
|
rb_define_method(cRbPodDatabase, "device", rbpod_database_device_get, 0);
|
269
|
+
|
270
|
+
rb_define_method(cRbPodDatabase, "tracks", rbpod_database_tracks_get, 0);
|
240
271
|
rb_define_method(cRbPodDatabase, "playlists", rbpod_database_playlists_get, 0);
|
241
272
|
|
242
273
|
rb_define_method(cRbPodDatabase, "synchronized?", rbpod_database_synchronized_p, 0);
|
data/ext/rbpod/device.c
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
/* device.c */
|
2
2
|
|
3
3
|
#include "rbpod.h"
|
4
|
+
#include "error.h"
|
4
5
|
#include "device.h"
|
5
6
|
#include "database.h"
|
6
7
|
|
@@ -197,7 +198,7 @@ static VALUE rbpod_device_initialize(VALUE self, VALUE database)
|
|
197
198
|
Itdb_iTunesDB *_database = TYPED_DATA_PTR(database, Itdb_iTunesDB);
|
198
199
|
|
199
200
|
/* Make sure we were given an instance of a RbPod::Database. */
|
200
|
-
if (
|
201
|
+
if (rb_obj_is_instance_of(database, cRbPodDatabase) == FALSE) {
|
201
202
|
rb_raise(eRbPodError, "Given database must be an instance of RbPod::Database: %s", StringValueCStr(database));
|
202
203
|
return Qnil;
|
203
204
|
}
|
data/ext/rbpod/error.c
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
/* error.c */
|
2
|
+
|
3
|
+
#include "rbpod.h"
|
4
|
+
#include "error.h"
|
5
|
+
|
6
|
+
inline VALUE rbpod_raise_error(GError *error)
|
7
|
+
{
|
8
|
+
VALUE error_message;
|
9
|
+
|
10
|
+
if (error != NULL) {
|
11
|
+
error_message = rb_str_new2(error->message);
|
12
|
+
g_error_free(error);
|
13
|
+
rb_raise(eRbPodError, "%s", StringValueCStr(error_message));
|
14
|
+
}
|
15
|
+
|
16
|
+
return Qnil;
|
17
|
+
}
|
18
|
+
|
19
|
+
void Init_rbpod_error(void)
|
20
|
+
{
|
21
|
+
#if RDOC_CAN_PARSE_DOCUMENTATION
|
22
|
+
mRbPod = rb_define_module("RbPod");
|
23
|
+
#endif
|
24
|
+
/* This is a generic subclass of RuntimeError for RbPod-specific errors.*/
|
25
|
+
eRbPodError = rb_define_class_under(mRbPod, "Error", rb_eRuntimeError);
|
26
|
+
}
|
27
|
+
|
data/ext/rbpod/error.h
ADDED
data/ext/rbpod/playlist.c
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
/*
|
8
8
|
* call-seq:
|
9
|
-
*
|
9
|
+
* podcast?() -> Boolean
|
10
10
|
*
|
11
11
|
* Returns true or false if this playlist is the podcast-only playlist.
|
12
12
|
*/
|
@@ -18,7 +18,7 @@ static VALUE rbpod_playlist_podcast_p(VALUE self)
|
|
18
18
|
|
19
19
|
/*
|
20
20
|
* call-seq:
|
21
|
-
*
|
21
|
+
* master?() -> Boolean
|
22
22
|
*
|
23
23
|
* Returns true or false if this playlist is the master playlist.
|
24
24
|
*/
|
@@ -30,7 +30,7 @@ static VALUE rbpod_playlist_master_p(VALUE self)
|
|
30
30
|
|
31
31
|
/*
|
32
32
|
* call-seq:
|
33
|
-
*
|
33
|
+
* smart?() -> Boolean
|
34
34
|
*
|
35
35
|
* Returns true or false if this playlist is a smart playlist.
|
36
36
|
*/
|
@@ -74,8 +74,7 @@ static VALUE rbpod_playlist_shuffle_bang(VALUE self)
|
|
74
74
|
*/
|
75
75
|
static VALUE rbpod_playlist_tracks_get(VALUE self)
|
76
76
|
{
|
77
|
-
|
78
|
-
return rbpod_track_collection_create(self, playlist->members);
|
77
|
+
return rb_class_new_instance(1, &self, cRbPodTrackCollection);
|
79
78
|
}
|
80
79
|
|
81
80
|
/*
|
@@ -137,21 +136,13 @@ static VALUE rbpod_playlist_id_get(VALUE self)
|
|
137
136
|
|
138
137
|
/*
|
139
138
|
* call-seq:
|
140
|
-
* initialize(
|
139
|
+
* initialize() -> RbPod::Playlist
|
141
140
|
*
|
142
141
|
* Creates a detached playlist. (Not managed by the database.)
|
143
142
|
*/
|
144
|
-
static VALUE rbpod_playlist_initialize(VALUE self
|
143
|
+
static VALUE rbpod_playlist_initialize(VALUE self)
|
145
144
|
{
|
146
|
-
|
147
|
-
gchar *_playlist_name = StringValueCStr(playlist_name);
|
148
|
-
|
149
|
-
itdb_playlist_free(playlist);
|
150
|
-
|
151
|
-
playlist = itdb_playlist_new(_playlist_name, (smart_playlist == Qtrue) ? TRUE : FALSE);
|
152
|
-
|
153
|
-
DATA_PTR(self) = playlist;
|
154
|
-
|
145
|
+
/* Nothing to see here. */
|
155
146
|
return self;
|
156
147
|
}
|
157
148
|
|
@@ -160,7 +151,7 @@ static void rbpod_playlist_deallocate(void *handle)
|
|
160
151
|
Itdb_Playlist *playlist = (Itdb_Playlist *) handle;
|
161
152
|
|
162
153
|
/* This playlist was unmanaged, so free it manually. */
|
163
|
-
if (playlist->itdb == NULL
|
154
|
+
if (playlist->itdb == NULL) {
|
164
155
|
itdb_playlist_free(playlist);
|
165
156
|
}
|
166
157
|
|
@@ -169,7 +160,7 @@ static void rbpod_playlist_deallocate(void *handle)
|
|
169
160
|
|
170
161
|
static VALUE rbpod_playlist_allocate(VALUE self)
|
171
162
|
{
|
172
|
-
Itdb_Playlist *playlist = itdb_playlist_new("
|
163
|
+
Itdb_Playlist *playlist = itdb_playlist_new("New Playlist", FALSE);
|
173
164
|
return Data_Wrap_Struct(cRbPodPlaylist, NULL, rbpod_playlist_deallocate, (void *) playlist);
|
174
165
|
}
|
175
166
|
|
@@ -182,7 +173,7 @@ void Init_rbpod_playlist(void)
|
|
182
173
|
|
183
174
|
rb_define_alloc_func(cRbPodPlaylist, rbpod_playlist_allocate);
|
184
175
|
|
185
|
-
rb_define_method(cRbPodPlaylist, "initialize", rbpod_playlist_initialize,
|
176
|
+
rb_define_method(cRbPodPlaylist, "initialize", rbpod_playlist_initialize, 0);
|
186
177
|
|
187
178
|
rb_define_private_method(cRbPodPlaylist, "id", rbpod_playlist_id_get, 0);
|
188
179
|
|
@@ -194,11 +185,12 @@ void Init_rbpod_playlist(void)
|
|
194
185
|
rb_define_method(cRbPodPlaylist, "shuffle!", rbpod_playlist_shuffle_bang, 0);
|
195
186
|
rb_define_method(cRbPodPlaylist, "timestamp", rbpod_playlist_timestamp_get, 0);
|
196
187
|
|
188
|
+
/* :nodoc */
|
197
189
|
rb_define_alias(cRbPodPlaylist, "created_on", "timestamp");
|
198
190
|
|
199
|
-
rb_define_method(cRbPodPlaylist, "
|
200
|
-
rb_define_method(cRbPodPlaylist, "
|
201
|
-
rb_define_method(cRbPodPlaylist, "
|
191
|
+
rb_define_method(cRbPodPlaylist, "smart?", rbpod_playlist_smart_p, 0);
|
192
|
+
rb_define_method(cRbPodPlaylist, "master?", rbpod_playlist_master_p, 0);
|
193
|
+
rb_define_method(cRbPodPlaylist, "podcast?", rbpod_playlist_podcast_p, 0);
|
202
194
|
|
203
195
|
return;
|
204
196
|
}
|