rbpod 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.md +1 -1
- data/Rakefile +36 -1
- data/bin/rbpod +0 -0
- data/ext/rbpod/collection.c +28 -29
- data/ext/rbpod/collection.h +1 -1
- data/ext/rbpod/database.c +31 -54
- data/ext/rbpod/database.h +0 -2
- data/ext/rbpod/device.c +25 -25
- data/ext/rbpod/device.h +1 -1
- data/ext/rbpod/playlist.c +34 -19
- data/ext/rbpod/playlist.h +2 -1
- data/ext/rbpod/rbpod.c +4 -0
- data/ext/rbpod/rbpod.h +3 -0
- data/ext/rbpod/track.c +18 -16
- data/ext/rbpod/track.h +2 -1
- data/lib/rbpod/version.rb +1 -1
- data/rbpod.gemspec +3 -0
- data/spec/spec_helper.rb +7 -0
- metadata +43 -3
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -54,7 +54,7 @@ Functional for most read-only purposes.
|
|
54
54
|
database.playlists.map(&:name) # => ["iPod", "Podcasts", "Recently Added"]
|
55
55
|
|
56
56
|
# Track Listing (also enumerable)
|
57
|
-
database.tracks.
|
57
|
+
database.tracks.length # => 400
|
58
58
|
database.tracks.first.artist # => "Steppenwolf"
|
59
59
|
database.tracks.first.title # => "Born To Be Wild"
|
60
60
|
|
data/Rakefile
CHANGED
@@ -1 +1,36 @@
|
|
1
|
-
|
1
|
+
# Bring in rake with rake-compiler's support.
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/extensiontask'
|
4
|
+
|
5
|
+
# Bring in bundler and it's gem tasks.
|
6
|
+
require 'bundler/setup'
|
7
|
+
require 'bundler/gem_tasks'
|
8
|
+
|
9
|
+
# Bring in RSpec's built-in rake task.
|
10
|
+
require 'rspec/core/rake_task'
|
11
|
+
|
12
|
+
# By default, clean, compile and then test.
|
13
|
+
task :default => [ :compile, :test ]
|
14
|
+
|
15
|
+
desc "Compile the native extension."
|
16
|
+
Rake::ExtensionTask.new do |extension|
|
17
|
+
# Some basic configuration.
|
18
|
+
extension.name = 'rbpod'
|
19
|
+
extension.ext_dir = 'ext/rbpod'
|
20
|
+
extension.lib_dir = 'lib/rbpod'
|
21
|
+
|
22
|
+
# Monitor sources for change tracking.
|
23
|
+
extension.source_pattern = '*.{c,h}'
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Run all available RSpec tests."
|
27
|
+
RSpec::Core::RakeTask.new(:test) do |task|
|
28
|
+
task.pattern = 'spec/**/*_spec.rb'
|
29
|
+
# Execute ruby with warnings enabled.
|
30
|
+
task.ruby_opts = '-w'
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Open a console with rbpod preloaded."
|
34
|
+
task :console => [ :compile ] do
|
35
|
+
sh 'bundle console'
|
36
|
+
end
|
data/bin/rbpod
CHANGED
File without changes
|
data/ext/rbpod/collection.c
CHANGED
@@ -7,14 +7,15 @@ VALUE cRbPodCollection;
|
|
7
7
|
|
8
8
|
struct collection { VALUE klass; GList *list; };
|
9
9
|
|
10
|
-
|
11
|
-
struct collection *collection =
|
12
|
-
|
13
|
-
|
10
|
+
inline VALUE rbpod_collection_create(GList *list, VALUE type) {
|
11
|
+
struct collection *collection = ALLOC(struct collection);
|
12
|
+
collection->list = list;
|
13
|
+
collection->klass = type;
|
14
|
+
return Data_Wrap_Struct(cRbPodCollection, NULL, NULL, (void *) collection);
|
14
15
|
}
|
15
16
|
|
16
17
|
static VALUE rbpod_collection_get(VALUE self, VALUE key) {
|
17
|
-
struct collection *collection =
|
18
|
+
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
18
19
|
GList *current = NULL;
|
19
20
|
|
20
21
|
if (FIXNUM_P(key) == FALSE)
|
@@ -22,42 +23,41 @@ static VALUE rbpod_collection_get(VALUE self, VALUE key) {
|
|
22
23
|
|
23
24
|
current = g_list_nth(collection->list, FIX2INT(key));
|
24
25
|
|
25
|
-
return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data)
|
26
|
+
return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
|
26
27
|
}
|
27
28
|
|
28
29
|
static VALUE rbpod_collection_last(VALUE self) {
|
29
|
-
struct collection *collection =
|
30
|
+
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
30
31
|
GList *current = g_list_last(collection->list);
|
31
32
|
return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
|
32
33
|
}
|
33
34
|
|
34
35
|
static VALUE rbpod_collection_first(VALUE self) {
|
35
|
-
struct collection *collection =
|
36
|
+
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
36
37
|
GList *current = g_list_first(collection->list);
|
37
38
|
return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
|
38
39
|
}
|
39
40
|
|
40
|
-
static VALUE
|
41
|
-
struct collection *collection =
|
41
|
+
static VALUE rbpod_collection_length(VALUE self) {
|
42
|
+
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
42
43
|
return INT2NUM(g_list_length(collection->list));
|
43
44
|
}
|
44
45
|
|
45
46
|
static VALUE rbpod_collection_each(VALUE self) {
|
46
|
-
struct collection *collection =
|
47
|
+
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
47
48
|
GList *current = NULL;
|
48
49
|
VALUE item;
|
49
50
|
|
50
|
-
if (rb_block_given_p() ==
|
51
|
-
/* If we were supplied a block, enumerate the entire list. */
|
52
|
-
for (current = collection->list; current != NULL; current = current->next) {
|
53
|
-
item = Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
|
54
|
-
rb_yield(item);
|
55
|
-
}
|
56
|
-
return Qnil;
|
57
|
-
} else {
|
58
|
-
/* Otherwise return an enumerator from this method to the caller. */
|
51
|
+
if (rb_block_given_p() == FALSE)
|
59
52
|
return rb_funcall(self, rb_intern("enum_for"), 1, ID2SYM(rb_intern("each")));
|
53
|
+
|
54
|
+
/* If we were supplied a block, enumerate the entire list. */
|
55
|
+
for (current = collection->list; current != NULL; current = current->next) {
|
56
|
+
item = Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
|
57
|
+
rb_yield(item);
|
60
58
|
}
|
59
|
+
|
60
|
+
return Qnil;
|
61
61
|
}
|
62
62
|
|
63
63
|
static VALUE rbpod_collection_initialize(VALUE self) {
|
@@ -74,15 +74,11 @@ static void rbpod_collection_deallocate(void *handle) {
|
|
74
74
|
return;
|
75
75
|
}
|
76
76
|
|
77
|
-
inline VALUE rbpod_collection_wrap(GList *list, VALUE type, gboolean freeable) {
|
78
|
-
struct collection *collection = ALLOC(struct collection);
|
79
|
-
collection->list = list;
|
80
|
-
collection->klass = type;
|
81
|
-
return Data_Wrap_Struct(cRbPodCollection, NULL, freeable ? rbpod_collection_deallocate : NULL, (void *) collection);
|
82
|
-
}
|
83
|
-
|
84
77
|
static VALUE rbpod_collection_allocate(VALUE self) {
|
85
|
-
|
78
|
+
struct collection *collection = ALLOC(struct collection);
|
79
|
+
collection->list = NULL;
|
80
|
+
collection->klass = Qnil;
|
81
|
+
return Data_Wrap_Struct(cRbPodCollection, NULL, rbpod_collection_deallocate, (void *) collection);
|
86
82
|
}
|
87
83
|
|
88
84
|
void Init_rbpod_collection(void) {
|
@@ -95,7 +91,10 @@ void Init_rbpod_collection(void) {
|
|
95
91
|
rb_define_method(cRbPodCollection, "initialize", rbpod_collection_initialize, 0);
|
96
92
|
|
97
93
|
rb_define_method(cRbPodCollection, "each", rbpod_collection_each, 0);
|
98
|
-
|
94
|
+
|
95
|
+
rb_define_method(cRbPodCollection, "length", rbpod_collection_length, 0);
|
96
|
+
|
97
|
+
rb_define_alias(cRbPodCollection, "size", "length");
|
99
98
|
|
100
99
|
rb_define_method(cRbPodCollection, "first", rbpod_collection_first, 0);
|
101
100
|
rb_define_method(cRbPodCollection, "last", rbpod_collection_last, 0);
|
data/ext/rbpod/collection.h
CHANGED
data/ext/rbpod/database.c
CHANGED
@@ -7,84 +7,72 @@
|
|
7
7
|
#include "database.h"
|
8
8
|
#include "collection.h"
|
9
9
|
|
10
|
-
/*
|
11
|
-
* Although libgpod has an itdb_new(), itdb_parse() also returns a pointer to a
|
12
|
-
* newly allocated Itdb_iTunesDB structure. Since overwriting the data pointer from
|
13
|
-
* Data_Get_Struct() at runtime is dangerous, we use a double-pointer to wrap the
|
14
|
-
* Itdb_iTunesDB handle, so as not to confuse the Ruby implementation internals.
|
15
|
-
*/
|
16
|
-
|
17
10
|
VALUE cRbPodDatabase;
|
18
11
|
|
19
|
-
static inline Itdb_iTunesDB *rbpod_database_unwrap(VALUE self) {
|
20
|
-
Itdb_iTunesDB **database = NULL;
|
21
|
-
Data_Get_Struct(self, Itdb_iTunesDB *, database);
|
22
|
-
return *database;
|
23
|
-
}
|
24
|
-
|
25
12
|
static VALUE rbpod_database_write(VALUE self) {
|
26
|
-
Itdb_iTunesDB *database =
|
13
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
27
14
|
gboolean success = itdb_write(database, NULL); /* TODO: Improve error handling. */
|
28
15
|
return BooleanValue(success);
|
29
16
|
}
|
30
17
|
|
31
18
|
static VALUE rbpod_database_is_synchronized(VALUE self) {
|
32
|
-
Itdb_iTunesDB *database =
|
19
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
33
20
|
guint32 nontransferred = itdb_tracks_number_nontransferred(database);
|
34
21
|
return BooleanValue(nontransferred == 0);
|
35
22
|
}
|
36
23
|
|
37
24
|
static VALUE rbpod_database_playlists_get(VALUE self) {
|
38
|
-
Itdb_iTunesDB *database =
|
39
|
-
return
|
25
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
26
|
+
return rbpod_playlist_collection_create(self, database->playlists);
|
40
27
|
}
|
41
28
|
|
42
29
|
static VALUE rbpod_database_tracks_get(VALUE self) {
|
43
|
-
Itdb_iTunesDB *database =
|
44
|
-
|
30
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
31
|
+
Itdb_Playlist *playlist = itdb_playlist_mpl(database);
|
32
|
+
/* Use the master playlist as the parent for the master track list. */
|
33
|
+
VALUE parent = Data_Wrap_Struct(cRbPodPlaylist, NULL, NULL, (void *) playlist);
|
34
|
+
return rbpod_track_collection_create(parent, database->tracks);
|
45
35
|
}
|
46
36
|
|
47
37
|
static VALUE rbpod_database_device_get(VALUE self) {
|
48
|
-
Itdb_iTunesDB *database =
|
49
|
-
return
|
38
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
39
|
+
return rbpod_device_create(database->device);
|
50
40
|
}
|
51
41
|
|
52
42
|
static VALUE rbpod_database_filename_get(VALUE self) {
|
53
|
-
Itdb_iTunesDB *database =
|
43
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
54
44
|
return rb_str_new2(database->filename);
|
55
45
|
}
|
56
46
|
|
57
47
|
static VALUE rbpod_database_version_get(VALUE self) {
|
58
|
-
Itdb_iTunesDB *database =
|
48
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
59
49
|
return INT2NUM(database->version);
|
60
50
|
}
|
61
51
|
|
62
52
|
static VALUE rbpod_database_id_get(VALUE self) {
|
63
|
-
Itdb_iTunesDB *database =
|
53
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
64
54
|
return INT2NUM(database->id);
|
65
55
|
}
|
66
56
|
|
67
57
|
static VALUE rbpod_database_mountpoint_get(VALUE self) {
|
68
|
-
Itdb_iTunesDB *database =
|
58
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
69
59
|
return rb_str_new2(itdb_get_mountpoint(database));
|
70
60
|
}
|
71
61
|
|
72
62
|
static VALUE rbpod_database_mountpoint_set(VALUE self, VALUE path) {
|
73
|
-
Itdb_iTunesDB *database =
|
63
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
74
64
|
itdb_set_mountpoint(database, StringValueCStr(path));
|
75
65
|
return rbpod_database_mountpoint_get(self);
|
76
66
|
}
|
77
67
|
|
78
68
|
static void rbpod_database_deallocate(void *handle) {
|
79
|
-
|
80
|
-
itdb_free(*database);
|
81
|
-
xfree(handle);
|
69
|
+
itdb_free((Itdb_iTunesDB *) handle);
|
82
70
|
return;
|
83
71
|
}
|
84
72
|
|
85
73
|
static VALUE rbpod_database_create(VALUE self, VALUE device_name, VALUE mount_point, VALUE model_number) {
|
86
|
-
Itdb_iTunesDB **database = ALLOC(Itdb_iTunesDB *);
|
87
74
|
gchar *_mount_point, *_model_number, *_device_name;
|
75
|
+
Itdb_iTunesDB *database = NULL;
|
88
76
|
|
89
77
|
_device_name = StringValueCStr(device_name);
|
90
78
|
_mount_point = StringValueCStr(mount_point);
|
@@ -95,55 +83,44 @@ static VALUE rbpod_database_create(VALUE self, VALUE device_name, VALUE mount_po
|
|
95
83
|
/* Initialize the iPod at this mount point, with this device name and model number. */
|
96
84
|
/* TODO: Improve error handling. */
|
97
85
|
if (itdb_init_ipod(_mount_point, _model_number, _device_name, NULL) == FALSE) {
|
98
|
-
|
99
|
-
rb_raise(rb_eRuntimeError, "Unable to format this iPod.");
|
86
|
+
rb_raise(eRbPodError, "Unable to format this iPod.");
|
100
87
|
return Qfalse;
|
101
88
|
}
|
102
89
|
|
103
90
|
/* Parse the newly created database. */
|
104
91
|
/* TODO: Improve error handling. */
|
105
|
-
|
92
|
+
database = itdb_parse(_mount_point, NULL);
|
106
93
|
|
107
|
-
if (
|
108
|
-
|
109
|
-
rb_raise(rb_eRuntimeError, "Not an iPod mount point.");
|
94
|
+
if (database == NULL) {
|
95
|
+
rb_raise(eRbPodError, "Not an iPod mount point.");
|
110
96
|
return Qnil;
|
111
97
|
}
|
112
98
|
|
113
99
|
/* Return an instance of this class using the newly created database. */
|
114
|
-
return Data_Wrap_Struct(
|
100
|
+
return Data_Wrap_Struct(cRbPodDatabase, NULL, rbpod_database_deallocate, (void *) database);
|
115
101
|
}
|
116
102
|
|
117
103
|
static VALUE rbpod_database_initialize(VALUE self, VALUE mount_point) {
|
118
|
-
Itdb_iTunesDB
|
119
|
-
|
120
|
-
/* Extract the wrapper from the class itself. */
|
121
|
-
Data_Get_Struct(self, Itdb_iTunesDB *, database);
|
104
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
122
105
|
|
123
106
|
/* Try to parse the database from the given mount point. */
|
124
107
|
/* TODO: Improve error handling. */
|
125
|
-
|
108
|
+
database = itdb_parse(StringValueCStr(mount_point), NULL);
|
126
109
|
|
127
110
|
/* The given mount point was not an iPod mount point. */
|
128
|
-
if (
|
129
|
-
rb_raise(
|
111
|
+
if (database == NULL) {
|
112
|
+
rb_raise(eRbPodError, "This is not an iPod mount point.");
|
130
113
|
return Qnil;
|
131
114
|
}
|
132
115
|
|
133
|
-
|
134
|
-
}
|
116
|
+
DATA_PTR(self) = database;
|
135
117
|
|
136
|
-
|
137
|
-
return Data_Wrap_Struct(cRbPodDatabase, NULL, freeable ? rbpod_database_deallocate : NULL, (void *) database);
|
118
|
+
return self;
|
138
119
|
}
|
139
120
|
|
140
121
|
static VALUE rbpod_database_allocate(VALUE self) {
|
141
|
-
Itdb_iTunesDB
|
142
|
-
|
143
|
-
/* Initialize a new, empty database. */
|
144
|
-
*database = itdb_new();
|
145
|
-
|
146
|
-
return rbpod_database_wrap(database, TRUE);
|
122
|
+
Itdb_iTunesDB *database = itdb_new();
|
123
|
+
return Data_Wrap_Struct(cRbPodDatabase, NULL, rbpod_database_deallocate, (void *) database);
|
147
124
|
}
|
148
125
|
|
149
126
|
void Init_rbpod_database(void) {
|
data/ext/rbpod/database.h
CHANGED
data/ext/rbpod/device.c
CHANGED
@@ -5,63 +5,66 @@
|
|
5
5
|
|
6
6
|
VALUE cRbPodDevice;
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
Data_Get_Struct(self, Itdb_Device, device);
|
11
|
-
return device;
|
8
|
+
inline VALUE rbpod_device_create(Itdb_Device *device) {
|
9
|
+
return Data_Wrap_Struct(cRbPodDevice, NULL, NULL, (void *) device);
|
12
10
|
}
|
13
11
|
|
14
12
|
static VALUE rbpod_device_has_chapter_image_support(VALUE self) {
|
15
|
-
Itdb_Device *device =
|
13
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
16
14
|
return BooleanValue(itdb_device_supports_chapter_image(device));
|
17
15
|
}
|
18
16
|
|
19
17
|
static VALUE rbpod_device_has_podcast_support(VALUE self) {
|
20
|
-
Itdb_Device *device =
|
18
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
21
19
|
return BooleanValue(itdb_device_supports_podcast(device));
|
22
20
|
}
|
23
21
|
|
24
22
|
static VALUE rbpod_device_has_artwork_support(VALUE self) {
|
25
|
-
Itdb_Device *device =
|
23
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
26
24
|
return BooleanValue(itdb_device_supports_artwork(device));
|
27
25
|
}
|
28
26
|
|
29
27
|
static VALUE rbpod_device_has_video_support(VALUE self) {
|
30
|
-
Itdb_Device *device =
|
28
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
31
29
|
return BooleanValue(itdb_device_supports_video(device));
|
32
30
|
}
|
33
31
|
|
34
32
|
static VALUE rbpod_device_has_photo_support(VALUE self) {
|
35
|
-
Itdb_Device *device =
|
33
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
36
34
|
return BooleanValue(itdb_device_supports_photo(device));
|
37
35
|
}
|
38
36
|
|
39
37
|
static VALUE rbpod_device_model_name_get(VALUE self) {
|
40
|
-
Itdb_Device *device =
|
41
|
-
Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
|
38
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
39
|
+
const Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
|
42
40
|
return rb_str_new2(itdb_info_get_ipod_model_name_string(info->ipod_model));
|
43
41
|
}
|
44
42
|
|
45
43
|
static VALUE rbpod_device_model_number_get(VALUE self) {
|
46
|
-
Itdb_Device *device =
|
47
|
-
Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
|
44
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
45
|
+
const Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
|
48
46
|
return rb_str_new2(info->model_number);
|
49
47
|
}
|
50
48
|
|
51
49
|
static VALUE rbpod_device_generation_get(VALUE self) {
|
52
|
-
Itdb_Device *device =
|
50
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
53
51
|
const Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
|
54
52
|
return rb_str_new2(itdb_info_get_ipod_generation_string(info->ipod_generation));
|
55
53
|
}
|
56
54
|
|
57
55
|
static VALUE rbpod_device_capacity_get(VALUE self) {
|
58
|
-
Itdb_Device *device =
|
56
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
59
57
|
const Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
|
60
58
|
return DBL2NUM(info->capacity);
|
61
59
|
}
|
62
60
|
|
61
|
+
static VALUE rbpod_device_uuid_get(VALUE self) {
|
62
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
63
|
+
return rb_str_new2(itdb_device_get_uuid(device));
|
64
|
+
}
|
65
|
+
|
63
66
|
static VALUE rbpod_device_sysinfo_get(VALUE self, VALUE key) {
|
64
|
-
Itdb_Device *device =
|
67
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
65
68
|
gchar *value = NULL;
|
66
69
|
VALUE result;
|
67
70
|
|
@@ -74,7 +77,7 @@ static VALUE rbpod_device_sysinfo_get(VALUE self, VALUE key) {
|
|
74
77
|
}
|
75
78
|
|
76
79
|
static VALUE rbpod_device_sysinfo_set(VALUE self, VALUE key, VALUE value) {
|
77
|
-
Itdb_Device *device =
|
80
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
78
81
|
gchar *_value, *_key;
|
79
82
|
|
80
83
|
_key = StringValueCStr(key);
|
@@ -82,17 +85,17 @@ static VALUE rbpod_device_sysinfo_set(VALUE self, VALUE key, VALUE value) {
|
|
82
85
|
|
83
86
|
itdb_device_set_sysinfo(device, _key, _value);
|
84
87
|
|
85
|
-
return rbpod_device_sysinfo_get(self,
|
88
|
+
return rbpod_device_sysinfo_get(self, key);
|
86
89
|
}
|
87
90
|
|
88
91
|
static VALUE rbpod_device_sysinfo_write(VALUE self) {
|
89
|
-
Itdb_Device *device =
|
92
|
+
Itdb_Device *device = TYPED_DATA_PTR(self, Itdb_Device);
|
90
93
|
/* TODO: Improve error handling. */
|
91
94
|
return BooleanValue(itdb_device_write_sysinfo(device, NULL));
|
92
95
|
}
|
93
96
|
|
94
97
|
static VALUE rbpod_device_initialize(VALUE self) {
|
95
|
-
/* Private. */
|
98
|
+
/* Private method, no setup required yet. */
|
96
99
|
return self;
|
97
100
|
}
|
98
101
|
|
@@ -100,12 +103,8 @@ static void rbpod_device_deallocate(void *handle) {
|
|
100
103
|
itdb_device_free((Itdb_Device *) handle);
|
101
104
|
}
|
102
105
|
|
103
|
-
inline VALUE rbpod_device_wrap(Itdb_Device *device, gboolean freeable) {
|
104
|
-
return Data_Wrap_Struct(cRbPodDevice, NULL, freeable ? rbpod_device_deallocate : NULL, (void *) device);
|
105
|
-
}
|
106
|
-
|
107
106
|
static VALUE rbpod_device_allocate(VALUE self) {
|
108
|
-
return
|
107
|
+
return Data_Wrap_Struct(cRbPodDevice, NULL, rbpod_device_deallocate, (void *) itdb_device_new());
|
109
108
|
}
|
110
109
|
|
111
110
|
void Init_rbpod_device(void) {
|
@@ -120,6 +119,7 @@ void Init_rbpod_device(void) {
|
|
120
119
|
rb_define_method(cRbPodDevice, "[]=", rbpod_device_sysinfo_set, 2);
|
121
120
|
rb_define_method(cRbPodDevice, "save!", rbpod_device_sysinfo_write, 0);
|
122
121
|
|
122
|
+
rb_define_method(cRbPodDevice, "uuid", rbpod_device_uuid_get, 0);
|
123
123
|
rb_define_method(cRbPodDevice, "capacity", rbpod_device_capacity_get, 0);
|
124
124
|
rb_define_method(cRbPodDevice, "generation", rbpod_device_generation_get, 0);
|
125
125
|
rb_define_method(cRbPodDevice, "model_name", rbpod_device_model_name_get, 0);
|
data/ext/rbpod/device.h
CHANGED
data/ext/rbpod/playlist.c
CHANGED
@@ -3,51 +3,66 @@
|
|
3
3
|
#include "rbpod.h"
|
4
4
|
#include "track.h"
|
5
5
|
#include "playlist.h"
|
6
|
+
#include "collection.h"
|
6
7
|
|
7
8
|
VALUE cRbPodPlaylist;
|
9
|
+
VALUE mRbPodPlaylistCollection;
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
inline VALUE rbpod_playlist_collection_create(VALUE parent, GList *items) {
|
12
|
+
VALUE collection = rbpod_collection_create(items, cRbPodPlaylist);
|
13
|
+
rb_extend_object(collection, mRbPodPlaylistCollection);
|
14
|
+
rb_iv_set(collection, "@parent", parent);
|
15
|
+
return collection;
|
13
16
|
}
|
14
17
|
|
15
18
|
static VALUE rbpod_playlist_is_podcast(VALUE self) {
|
16
|
-
Itdb_Playlist *playlist =
|
19
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
17
20
|
return BooleanValue(itdb_playlist_is_podcasts(playlist));
|
18
21
|
}
|
19
22
|
|
20
23
|
static VALUE rbpod_playlist_is_master(VALUE self) {
|
21
|
-
Itdb_Playlist *playlist =
|
24
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
22
25
|
return BooleanValue(itdb_playlist_is_mpl(playlist));
|
23
26
|
}
|
24
27
|
|
25
28
|
static VALUE rbpod_playlist_is_smart(VALUE self) {
|
26
|
-
Itdb_Playlist *playlist =
|
29
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
27
30
|
return BooleanValue(playlist->is_spl);
|
28
31
|
}
|
29
32
|
|
33
|
+
static VALUE rbpod_playlist_timestamp_get(VALUE self) {
|
34
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
35
|
+
return rb_funcall(rb_cTime, rb_intern("at"), 1, INT2NUM(playlist->timestamp));
|
36
|
+
}
|
37
|
+
|
38
|
+
static VALUE rbpod_playlist_shuffle(VALUE self) {
|
39
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
40
|
+
itdb_playlist_randomize(playlist);
|
41
|
+
return Qnil;
|
42
|
+
}
|
43
|
+
|
30
44
|
static VALUE rbpod_playlist_tracks_get(VALUE self) {
|
31
|
-
Itdb_Playlist *playlist =
|
32
|
-
return
|
45
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
46
|
+
return rbpod_track_collection_create(self, playlist->members);
|
33
47
|
}
|
34
48
|
|
35
49
|
static VALUE rbpod_playlist_length_get(VALUE self) {
|
36
|
-
Itdb_Playlist *playlist =
|
37
|
-
return INT2NUM(playlist
|
50
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
51
|
+
return INT2NUM(itdb_playlist_tracks_number(playlist));
|
38
52
|
}
|
39
53
|
|
40
54
|
static VALUE rbpod_playlist_name_get(VALUE self) {
|
41
|
-
Itdb_Playlist *playlist =
|
55
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
42
56
|
return rb_str_new2(playlist->name);
|
43
57
|
}
|
44
58
|
|
45
59
|
static VALUE rbpod_playlist_id_get(VALUE self) {
|
46
|
-
Itdb_Playlist *playlist =
|
47
|
-
return
|
60
|
+
Itdb_Playlist *playlist = TYPED_DATA_PTR(self, Itdb_Playlist);
|
61
|
+
return INT2NUM(playlist->id);
|
48
62
|
}
|
49
63
|
|
50
64
|
static VALUE rbpod_playlist_initialize(VALUE self) {
|
65
|
+
/* Nothing to intiialize, yet. */
|
51
66
|
return self;
|
52
67
|
}
|
53
68
|
|
@@ -55,13 +70,9 @@ static void rbpod_playlist_deallocate(void *handle) {
|
|
55
70
|
itdb_playlist_free((Itdb_Playlist *) handle);
|
56
71
|
}
|
57
72
|
|
58
|
-
inline VALUE rbpod_playlist_wrap(Itdb_Playlist *playlist, gboolean freeable) {
|
59
|
-
return Data_Wrap_Struct(cRbPodPlaylist, NULL, freeable ? rbpod_playlist_deallocate : NULL, (void *) playlist);
|
60
|
-
}
|
61
|
-
|
62
73
|
static VALUE rbpod_playlist_allocate(VALUE self) {
|
63
74
|
Itdb_Playlist *playlist = itdb_playlist_new("Untitled Playlist", FALSE);
|
64
|
-
return
|
75
|
+
return Data_Wrap_Struct(cRbPodPlaylist, NULL, rbpod_playlist_deallocate, (void *) playlist);
|
65
76
|
}
|
66
77
|
|
67
78
|
void Init_rbpod_playlist(void) {
|
@@ -75,11 +86,15 @@ void Init_rbpod_playlist(void) {
|
|
75
86
|
rb_define_method(cRbPodPlaylist, "name", rbpod_playlist_name_get, 0);
|
76
87
|
rb_define_method(cRbPodPlaylist, "length", rbpod_playlist_length_get, 0);
|
77
88
|
rb_define_method(cRbPodPlaylist, "tracks", rbpod_playlist_tracks_get, 0);
|
89
|
+
rb_define_method(cRbPodPlaylist, "shuffle!", rbpod_playlist_shuffle, 0);
|
90
|
+
rb_define_method(cRbPodPlaylist, "created_on", rbpod_playlist_timestamp_get, 0);
|
78
91
|
|
79
92
|
rb_define_method(cRbPodPlaylist, "smart_playlist?", rbpod_playlist_is_smart, 0);
|
80
93
|
rb_define_method(cRbPodPlaylist, "master_playlist?", rbpod_playlist_is_master, 0);
|
81
94
|
rb_define_method(cRbPodPlaylist, "podcast_playlist?", rbpod_playlist_is_podcast, 0);
|
82
95
|
|
96
|
+
mRbPodPlaylistCollection = rb_define_module_under(cRbPodPlaylist, "Collection");
|
97
|
+
|
83
98
|
return;
|
84
99
|
}
|
85
100
|
|
data/ext/rbpod/playlist.h
CHANGED
@@ -4,9 +4,10 @@
|
|
4
4
|
#define RBPOD_PLAYLIST_H
|
5
5
|
|
6
6
|
extern VALUE cRbPodPlaylist;
|
7
|
+
extern VALUE mRbPodPlaylistCollection;
|
7
8
|
|
8
9
|
void Init_rbpod_playlist(void);
|
9
10
|
|
10
|
-
inline VALUE
|
11
|
+
inline VALUE rbpod_playlist_collection_create(VALUE parent, GList *items);
|
11
12
|
|
12
13
|
#endif /* RBPOD_PLAYLIST_H */
|
data/ext/rbpod/rbpod.c
CHANGED
@@ -8,11 +8,15 @@
|
|
8
8
|
#include "collection.h"
|
9
9
|
|
10
10
|
VALUE mRbPod;
|
11
|
+
VALUE eRbPodError;
|
11
12
|
|
12
13
|
void Init_rbpod(void) {
|
13
14
|
/* Set up the top-level RbPod module. */
|
14
15
|
mRbPod = rb_define_module("RbPod");
|
15
16
|
|
17
|
+
/* Subclass RuntimeError for ourselves. */
|
18
|
+
eRbPodError = rb_define_class_under(mRbPod, "Error", rb_eRuntimeError);
|
19
|
+
|
16
20
|
/* Set up the RbPod::Database class. */
|
17
21
|
Init_rbpod_database();
|
18
22
|
|
data/ext/rbpod/rbpod.h
CHANGED
data/ext/rbpod/track.c
CHANGED
@@ -2,47 +2,50 @@
|
|
2
2
|
|
3
3
|
#include "rbpod.h"
|
4
4
|
#include "track.h"
|
5
|
+
#include "collection.h"
|
5
6
|
|
6
7
|
VALUE cRbPodTrack;
|
8
|
+
VALUE mRbPodTrackCollection;
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
inline VALUE rbpod_track_collection_create(VALUE parent, GList *items) {
|
11
|
+
VALUE collection = rbpod_collection_create(items, cRbPodTrack);
|
12
|
+
rb_extend_object(collection, mRbPodTrackCollection);
|
13
|
+
rb_iv_set(collection, "@parent", parent);
|
14
|
+
return collection;
|
12
15
|
}
|
13
16
|
|
14
17
|
static VALUE rbpod_track_is_transferred(VALUE self) {
|
15
|
-
Itdb_Track *track =
|
18
|
+
Itdb_Track *track = TYPED_DATA_PTR(self, Itdb_Track);
|
16
19
|
return BooleanValue(track->transferred);
|
17
20
|
}
|
18
21
|
|
19
22
|
static VALUE rbpod_track_ipod_path_get(VALUE self) {
|
20
|
-
Itdb_Track *track =
|
23
|
+
Itdb_Track *track = TYPED_DATA_PTR(self, Itdb_Track);
|
21
24
|
return rb_str_new2(track->ipod_path);
|
22
25
|
}
|
23
26
|
|
24
27
|
static VALUE rbpod_track_file_type_get(VALUE self) {
|
25
|
-
Itdb_Track *track =
|
28
|
+
Itdb_Track *track = TYPED_DATA_PTR(self, Itdb_Track);
|
26
29
|
return rb_str_new2(track->filetype);
|
27
30
|
}
|
28
31
|
|
29
32
|
static VALUE rbpod_track_artist_get(VALUE self) {
|
30
|
-
Itdb_Track *track =
|
33
|
+
Itdb_Track *track = TYPED_DATA_PTR(self, Itdb_Track);
|
31
34
|
return rb_str_new2(track->artist);
|
32
35
|
}
|
33
36
|
|
34
37
|
static VALUE rbpod_track_album_get(VALUE self) {
|
35
|
-
Itdb_Track *track =
|
38
|
+
Itdb_Track *track = TYPED_DATA_PTR(self, Itdb_Track);
|
36
39
|
return rb_str_new2(track->album);
|
37
40
|
}
|
38
41
|
|
39
42
|
static VALUE rbpod_track_title_get(VALUE self) {
|
40
|
-
Itdb_Track *track =
|
43
|
+
Itdb_Track *track = TYPED_DATA_PTR(self, Itdb_Track);
|
41
44
|
return rb_str_new2(track->title);
|
42
45
|
}
|
43
46
|
|
44
47
|
static VALUE rbpod_track_id_get(VALUE self) {
|
45
|
-
Itdb_Track *track =
|
48
|
+
Itdb_Track *track = TYPED_DATA_PTR(self, Itdb_Track);
|
46
49
|
return rb_str_new2(track->filetype);
|
47
50
|
}
|
48
51
|
|
@@ -55,12 +58,9 @@ static void rbpod_track_deallocate(void *handle) {
|
|
55
58
|
return;
|
56
59
|
}
|
57
60
|
|
58
|
-
inline VALUE rbpod_track_wrap(Itdb_Track *track, gboolean freeable) {
|
59
|
-
return Data_Wrap_Struct(cRbPodTrack, NULL, freeable ? rbpod_track_deallocate : NULL, (void *) track);
|
60
|
-
}
|
61
|
-
|
62
61
|
static VALUE rbpod_track_allocate(VALUE self) {
|
63
|
-
|
62
|
+
Itdb_Track *track = itdb_track_new();
|
63
|
+
return Data_Wrap_Struct(cRbPodTrack, NULL, rbpod_track_deallocate, (void *) track);
|
64
64
|
}
|
65
65
|
|
66
66
|
void Init_rbpod_track(void) {
|
@@ -79,6 +79,8 @@ void Init_rbpod_track(void) {
|
|
79
79
|
|
80
80
|
rb_define_method(cRbPodTrack, "transferred?", rbpod_track_is_transferred, 0);
|
81
81
|
|
82
|
+
mRbPodTrackCollection = rb_define_module_under(cRbPodTrack, "Collection");
|
83
|
+
|
82
84
|
return;
|
83
85
|
}
|
84
86
|
|
data/ext/rbpod/track.h
CHANGED
@@ -4,9 +4,10 @@
|
|
4
4
|
#define RBPOD_TRACK_H
|
5
5
|
|
6
6
|
extern VALUE cRbPodTrack;
|
7
|
+
extern VALUE mRbPodTrackCollection;
|
7
8
|
|
8
9
|
void Init_rbpod_track(void);
|
9
10
|
|
10
|
-
inline VALUE
|
11
|
+
inline VALUE rbpod_track_collection_create(VALUE parent, GList *items);
|
11
12
|
|
12
13
|
#endif /* RBPOD_TRACK_H */
|
data/lib/rbpod/version.rb
CHANGED
data/rbpod.gemspec
CHANGED
@@ -23,6 +23,9 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.require_paths = ['lib']
|
24
24
|
|
25
25
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
26
|
+
spec.add_development_dependency 'rspec', '~> 2.14'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'rake-compiler', '~> 0.8'
|
26
29
|
spec.add_development_dependency 'rake'
|
27
30
|
|
28
31
|
spec.add_dependency 'trollop', '~> 2.0'
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbpod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-10-
|
12
|
+
date: 2013-10-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -27,6 +27,38 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '2.14'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '2.14'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake-compiler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.8'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.8'
|
30
62
|
- !ruby/object:Gem::Dependency
|
31
63
|
name: rake
|
32
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,6 +122,7 @@ files:
|
|
90
122
|
- lib/rbpod.rb
|
91
123
|
- lib/rbpod/version.rb
|
92
124
|
- rbpod.gemspec
|
125
|
+
- spec/spec_helper.rb
|
93
126
|
homepage: https://github.com/jmkeyes/rbpod
|
94
127
|
licenses:
|
95
128
|
- MIT
|
@@ -103,12 +136,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
136
|
- - ! '>='
|
104
137
|
- !ruby/object:Gem::Version
|
105
138
|
version: '0'
|
139
|
+
segments:
|
140
|
+
- 0
|
141
|
+
hash: 658402081
|
106
142
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
143
|
none: false
|
108
144
|
requirements:
|
109
145
|
- - ! '>='
|
110
146
|
- !ruby/object:Gem::Version
|
111
147
|
version: '0'
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
hash: 658402081
|
112
151
|
requirements:
|
113
152
|
- libgpod-1.0
|
114
153
|
rubyforge_project:
|
@@ -116,4 +155,5 @@ rubygems_version: 1.8.23
|
|
116
155
|
signing_key:
|
117
156
|
specification_version: 3
|
118
157
|
summary: Ruby bindings to the libgpod library.
|
119
|
-
test_files:
|
158
|
+
test_files:
|
159
|
+
- spec/spec_helper.rb
|