rbpod 0.0.1 → 0.0.2
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/.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
|