rbpod 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rbpod.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Joshua M. Keyes
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # RbPod
2
+
3
+ A Ruby interface to the libgpod library.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rbpod'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rbpod
18
+
19
+ ## Usage
20
+
21
+ Functional for most read-only purposes.
22
+
23
+ #!/usr/bin/env ruby
24
+
25
+ require 'rbpod'
26
+
27
+ # Explicitly load a database from the filesystem -- can be a mount point to an iPod.
28
+ database = RbPod::Database.new('/mnt/ipod/') # => #<RbPod::Database:0x8733fa4>
29
+
30
+ database.version # => 42
31
+ database.mountpoint # => "/mnt/ipod/"
32
+ database.filename # => "/mnt/ipod/iPod_Control/iTunes/iTunesDB"
33
+ database.synchronized? # => true
34
+
35
+ # Device information, including model name, number, and capacity.
36
+ database.device.capacity # => 4.0
37
+ database.device.generation # => "Nano Video (3rd Gen.)"
38
+ database.device.model_name # => "Nano (Silver)"
39
+ database.device.model_number # => "A978"
40
+
41
+ # Device feature support detection.
42
+ database.device.supports_photos? # => true
43
+ database.device.supports_videos? # => true
44
+ database.device.supports_artwork? # => true
45
+ database.device.supports_podcasts? # => true
46
+ database.device.supports_chapter_images? # => true
47
+
48
+ # Device SysInfo read/write.
49
+ database.device['ModelNumStr'] # => "xA978"
50
+ database.device['PotsdamConf45'] = "Kilroy Was Here"
51
+ database.device.save!
52
+
53
+ # Playlists (includes enumerable)
54
+ database.playlists.map(&:name) # => ["iPod", "Podcasts", "Recently Added"]
55
+
56
+ # Track Listing (also enumerable)
57
+ database.tracks.count # => 400
58
+ database.tracks.first.artist # => "Steppenwolf"
59
+ database.tracks.first.title # => "Born To Be Wild"
60
+
61
+ It's alpha quality -- many pieces still need to be implemented. Patches welcome.
62
+
63
+ ## Contributing
64
+
65
+ 1. Fork it
66
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
67
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
68
+ 4. Push to the branch (`git push origin my-new-feature`)
69
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/rbpod ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rbpod'
@@ -0,0 +1,104 @@
1
+ /* collection.c */
2
+
3
+ #include "rbpod.h"
4
+ #include "collection.h"
5
+
6
+ VALUE cRbPodCollection;
7
+
8
+ struct collection { VALUE klass; GList *list; };
9
+
10
+ static inline struct collection *rbpod_collection_unwrap(VALUE self) {
11
+ struct collection *collection = NULL;
12
+ Data_Get_Struct(self, struct collection, collection);
13
+ return collection;
14
+ }
15
+
16
+ static VALUE rbpod_collection_get(VALUE self, VALUE key) {
17
+ struct collection *collection = rbpod_collection_unwrap(self);
18
+ GList *current = NULL;
19
+
20
+ if (FIXNUM_P(key) == FALSE)
21
+ return Qnil;
22
+
23
+ current = g_list_nth(collection->list, FIX2INT(key));
24
+
25
+ return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);;
26
+ }
27
+
28
+ static VALUE rbpod_collection_last(VALUE self) {
29
+ struct collection *collection = rbpod_collection_unwrap(self);
30
+ GList *current = g_list_last(collection->list);
31
+ return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
32
+ }
33
+
34
+ static VALUE rbpod_collection_first(VALUE self) {
35
+ struct collection *collection = rbpod_collection_unwrap(self);
36
+ GList *current = g_list_first(collection->list);
37
+ return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
38
+ }
39
+
40
+ static VALUE rbpod_collection_count(VALUE self) {
41
+ struct collection *collection = rbpod_collection_unwrap(self);
42
+ return INT2NUM(g_list_length(collection->list));
43
+ }
44
+
45
+ static VALUE rbpod_collection_each(VALUE self) {
46
+ struct collection *collection = rbpod_collection_unwrap(self);
47
+ GList *current = NULL;
48
+ VALUE item;
49
+
50
+ if (rb_block_given_p() == TRUE) {
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. */
59
+ return rb_funcall(self, rb_intern("enum_for"), 1, ID2SYM(rb_intern("each")));
60
+ }
61
+ }
62
+
63
+ static VALUE rbpod_collection_initialize(VALUE self) {
64
+ return self;
65
+ }
66
+
67
+ static void rbpod_collection_deallocate(void *handle) {
68
+ struct collection *collection = (struct collection *) handle;
69
+
70
+ if (collection->list != NULL)
71
+ g_list_free(collection->list);
72
+
73
+ xfree(handle);
74
+ return;
75
+ }
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
+ static VALUE rbpod_collection_allocate(VALUE self) {
85
+ return rbpod_collection_wrap(g_list_alloc(), Qnil, TRUE);
86
+ }
87
+
88
+ void Init_rbpod_collection(void) {
89
+ cRbPodCollection = rb_define_class_under(mRbPod, "Collection", rb_cObject);
90
+
91
+ rb_define_alloc_func(cRbPodCollection, rbpod_collection_allocate);
92
+
93
+ rb_include_module(cRbPodCollection, rb_mEnumerable);
94
+
95
+ rb_define_method(cRbPodCollection, "initialize", rbpod_collection_initialize, 0);
96
+
97
+ rb_define_method(cRbPodCollection, "each", rbpod_collection_each, 0);
98
+ rb_define_method(cRbPodCollection, "count", rbpod_collection_count, 0);
99
+
100
+ rb_define_method(cRbPodCollection, "first", rbpod_collection_first, 0);
101
+ rb_define_method(cRbPodCollection, "last", rbpod_collection_last, 0);
102
+
103
+ rb_define_method(cRbPodCollection, "[]", rbpod_collection_get, 1);
104
+ }
@@ -0,0 +1,12 @@
1
+ /* collection.h */
2
+
3
+ #ifndef RBPOD_COLLECTION_H
4
+ #define RBPOD_COLLECTION_H
5
+
6
+ extern VALUE cRbPodCollection;
7
+
8
+ void Init_rbpod_collection(void);
9
+
10
+ inline VALUE rbpod_collection_wrap(GList *list, VALUE type, gboolean freeable);
11
+
12
+ #endif /* RBPOD_COLLECTION_H */
@@ -0,0 +1,173 @@
1
+ /* database.c */
2
+
3
+ #include "rbpod.h"
4
+ #include "track.h"
5
+ #include "device.h"
6
+ #include "playlist.h"
7
+ #include "database.h"
8
+ #include "collection.h"
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
+ VALUE cRbPodDatabase;
18
+
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
+ static VALUE rbpod_database_write(VALUE self) {
26
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
27
+ gboolean success = itdb_write(database, NULL); /* TODO: Improve error handling. */
28
+ return BooleanValue(success);
29
+ }
30
+
31
+ static VALUE rbpod_database_is_synchronized(VALUE self) {
32
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
33
+ guint32 nontransferred = itdb_tracks_number_nontransferred(database);
34
+ return BooleanValue(nontransferred == 0);
35
+ }
36
+
37
+ static VALUE rbpod_database_playlists_get(VALUE self) {
38
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
39
+ return rbpod_collection_wrap(database->playlists, cRbPodPlaylist, FALSE);
40
+ }
41
+
42
+ static VALUE rbpod_database_tracks_get(VALUE self) {
43
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
44
+ return rbpod_collection_wrap(database->tracks, cRbPodTrack, FALSE);
45
+ }
46
+
47
+ static VALUE rbpod_database_device_get(VALUE self) {
48
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
49
+ return rbpod_device_wrap(database->device, FALSE);
50
+ }
51
+
52
+ static VALUE rbpod_database_filename_get(VALUE self) {
53
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
54
+ return rb_str_new2(database->filename);
55
+ }
56
+
57
+ static VALUE rbpod_database_version_get(VALUE self) {
58
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
59
+ return INT2NUM(database->version);
60
+ }
61
+
62
+ static VALUE rbpod_database_id_get(VALUE self) {
63
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
64
+ return INT2NUM(database->id);
65
+ }
66
+
67
+ static VALUE rbpod_database_mountpoint_get(VALUE self) {
68
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
69
+ return rb_str_new2(itdb_get_mountpoint(database));
70
+ }
71
+
72
+ static VALUE rbpod_database_mountpoint_set(VALUE self, VALUE path) {
73
+ Itdb_iTunesDB *database = rbpod_database_unwrap(self);
74
+ itdb_set_mountpoint(database, StringValueCStr(path));
75
+ return rbpod_database_mountpoint_get(self);
76
+ }
77
+
78
+ static void rbpod_database_deallocate(void *handle) {
79
+ Itdb_iTunesDB **database = (Itdb_iTunesDB **) handle;
80
+ itdb_free(*database);
81
+ xfree(handle);
82
+ return;
83
+ }
84
+
85
+ static VALUE rbpod_database_create(VALUE self, VALUE device_name, VALUE mount_point, VALUE model_number) {
86
+ Itdb_iTunesDB **database = ALLOC(Itdb_iTunesDB *);
87
+ gchar *_mount_point, *_model_number, *_device_name;
88
+
89
+ _device_name = StringValueCStr(device_name);
90
+ _mount_point = StringValueCStr(mount_point);
91
+
92
+ /* GPod can function with a NULL model number, however, artwork will not function. */
93
+ _model_number = !NIL_P(model_number) ? StringValueCStr(model_number) : NULL;
94
+
95
+ /* Initialize the iPod at this mount point, with this device name and model number. */
96
+ /* TODO: Improve error handling. */
97
+ if (itdb_init_ipod(_mount_point, _model_number, _device_name, NULL) == FALSE) {
98
+ free(database);
99
+ rb_raise(rb_eRuntimeError, "Unable to format this iPod.");
100
+ return Qfalse;
101
+ }
102
+
103
+ /* Parse the newly created database. */
104
+ /* TODO: Improve error handling. */
105
+ *database = itdb_parse(_mount_point, NULL);
106
+
107
+ if (*database == NULL) {
108
+ free(database);
109
+ rb_raise(rb_eRuntimeError, "Not an iPod mount point.");
110
+ return Qnil;
111
+ }
112
+
113
+ /* Return an instance of this class using the newly created database. */
114
+ return Data_Wrap_Struct(self, NULL, rbpod_database_deallocate, (void *) database);
115
+ }
116
+
117
+ static VALUE rbpod_database_initialize(VALUE self, VALUE mount_point) {
118
+ Itdb_iTunesDB **database;
119
+
120
+ /* Extract the wrapper from the class itself. */
121
+ Data_Get_Struct(self, Itdb_iTunesDB *, database);
122
+
123
+ /* Try to parse the database from the given mount point. */
124
+ /* TODO: Improve error handling. */
125
+ *database = itdb_parse(StringValueCStr(mount_point), NULL);
126
+
127
+ /* The given mount point was not an iPod mount point. */
128
+ if (*database == NULL) {
129
+ rb_raise(rb_eRuntimeError, "Not an iPod mount point.");
130
+ return Qnil;
131
+ }
132
+
133
+ return self;
134
+ }
135
+
136
+ inline VALUE rbpod_database_wrap(Itdb_iTunesDB **database, gboolean freeable) {
137
+ return Data_Wrap_Struct(cRbPodDatabase, NULL, freeable ? rbpod_database_deallocate : NULL, (void *) database);
138
+ }
139
+
140
+ static VALUE rbpod_database_allocate(VALUE self) {
141
+ Itdb_iTunesDB **database = ALLOC(Itdb_iTunesDB *);
142
+
143
+ /* Initialize a new, empty database. */
144
+ *database = itdb_new();
145
+
146
+ return rbpod_database_wrap(database, TRUE);
147
+ }
148
+
149
+ void Init_rbpod_database(void) {
150
+ cRbPodDatabase = rb_define_class_under(mRbPod, "Database", rb_cObject);
151
+
152
+ rb_define_alloc_func(cRbPodDatabase, rbpod_database_allocate);
153
+
154
+ rb_define_method(cRbPodDatabase, "initialize", rbpod_database_initialize, 1);
155
+
156
+ rb_define_singleton_method(cRbPodDatabase, "create!", rbpod_database_create, 3);
157
+
158
+ rb_define_method(cRbPodDatabase, "mountpoint", rbpod_database_mountpoint_get, 0);
159
+ rb_define_method(cRbPodDatabase, "mountpoint=", rbpod_database_mountpoint_set, 1);
160
+
161
+ rb_define_method(cRbPodDatabase, "id", rbpod_database_id_get, 0);
162
+ rb_define_method(cRbPodDatabase, "version", rbpod_database_version_get, 0);
163
+ rb_define_method(cRbPodDatabase, "filename", rbpod_database_filename_get, 0);
164
+
165
+ rb_define_method(cRbPodDatabase, "device", rbpod_database_device_get, 0);
166
+ rb_define_method(cRbPodDatabase, "tracks", rbpod_database_tracks_get, 0);
167
+ rb_define_method(cRbPodDatabase, "playlists", rbpod_database_playlists_get, 0);
168
+
169
+ rb_define_method(cRbPodDatabase, "synchronized?", rbpod_database_is_synchronized, 0);
170
+
171
+ rb_define_method(cRbPodDatabase, "write!", rbpod_database_write, 0);
172
+ }
173
+
@@ -0,0 +1,12 @@
1
+ /* database.h */
2
+
3
+ #ifndef RBPOD_DATABASE_H
4
+ #define RBPOD_DATABASE_H
5
+
6
+ extern VALUE cRbPodDatabase;
7
+
8
+ void Init_rbpod_database(void);
9
+
10
+ inline VALUE rbpod_database_wrap(Itdb_iTunesDB **database, gboolean freeable);
11
+
12
+ #endif /* RBPOD_DATABASE_H */
@@ -0,0 +1,136 @@
1
+ /* device.c */
2
+
3
+ #include "rbpod.h"
4
+ #include "device.h"
5
+
6
+ VALUE cRbPodDevice;
7
+
8
+ static inline Itdb_Device *rbpod_device_unwrap(VALUE self) {
9
+ Itdb_Device *device = NULL;
10
+ Data_Get_Struct(self, Itdb_Device, device);
11
+ return device;
12
+ }
13
+
14
+ static VALUE rbpod_device_has_chapter_image_support(VALUE self) {
15
+ Itdb_Device *device = rbpod_device_unwrap(self);
16
+ return BooleanValue(itdb_device_supports_chapter_image(device));
17
+ }
18
+
19
+ static VALUE rbpod_device_has_podcast_support(VALUE self) {
20
+ Itdb_Device *device = rbpod_device_unwrap(self);
21
+ return BooleanValue(itdb_device_supports_podcast(device));
22
+ }
23
+
24
+ static VALUE rbpod_device_has_artwork_support(VALUE self) {
25
+ Itdb_Device *device = rbpod_device_unwrap(self);
26
+ return BooleanValue(itdb_device_supports_artwork(device));
27
+ }
28
+
29
+ static VALUE rbpod_device_has_video_support(VALUE self) {
30
+ Itdb_Device *device = rbpod_device_unwrap(self);
31
+ return BooleanValue(itdb_device_supports_video(device));
32
+ }
33
+
34
+ static VALUE rbpod_device_has_photo_support(VALUE self) {
35
+ Itdb_Device *device = rbpod_device_unwrap(self);
36
+ return BooleanValue(itdb_device_supports_photo(device));
37
+ }
38
+
39
+ static VALUE rbpod_device_model_name_get(VALUE self) {
40
+ Itdb_Device *device = rbpod_device_unwrap(self);
41
+ Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
42
+ return rb_str_new2(itdb_info_get_ipod_model_name_string(info->ipod_model));
43
+ }
44
+
45
+ static VALUE rbpod_device_model_number_get(VALUE self) {
46
+ Itdb_Device *device = rbpod_device_unwrap(self);
47
+ Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
48
+ return rb_str_new2(info->model_number);
49
+ }
50
+
51
+ static VALUE rbpod_device_generation_get(VALUE self) {
52
+ Itdb_Device *device = rbpod_device_unwrap(self);
53
+ const Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
54
+ return rb_str_new2(itdb_info_get_ipod_generation_string(info->ipod_generation));
55
+ }
56
+
57
+ static VALUE rbpod_device_capacity_get(VALUE self) {
58
+ Itdb_Device *device = rbpod_device_unwrap(self);
59
+ const Itdb_IpodInfo *info = itdb_device_get_ipod_info(device);
60
+ return DBL2NUM(info->capacity);
61
+ }
62
+
63
+ static VALUE rbpod_device_sysinfo_get(VALUE self, VALUE key) {
64
+ Itdb_Device *device = rbpod_device_unwrap(self);
65
+ gchar *value = NULL;
66
+ VALUE result;
67
+
68
+ value = itdb_device_get_sysinfo(device, StringValueCStr(key));
69
+ result = (value == NULL) ? Qnil : rb_str_new2(value);
70
+
71
+ g_free(value);
72
+ return result;
73
+
74
+ }
75
+
76
+ static VALUE rbpod_device_sysinfo_set(VALUE self, VALUE key, VALUE value) {
77
+ Itdb_Device *device = rbpod_device_unwrap(self);
78
+ gchar *_value, *_key;
79
+
80
+ _key = StringValueCStr(key);
81
+ _value = !NIL_P(value) ? StringValueCStr(value) : NULL;
82
+
83
+ itdb_device_set_sysinfo(device, _key, _value);
84
+
85
+ return rbpod_device_sysinfo_get(self, _key);
86
+ }
87
+
88
+ static VALUE rbpod_device_sysinfo_write(VALUE self) {
89
+ Itdb_Device *device = rbpod_device_unwrap(self);
90
+ /* TODO: Improve error handling. */
91
+ return BooleanValue(itdb_device_write_sysinfo(device, NULL));
92
+ }
93
+
94
+ static VALUE rbpod_device_initialize(VALUE self) {
95
+ /* Private. */
96
+ return self;
97
+ }
98
+
99
+ static void rbpod_device_deallocate(void *handle) {
100
+ itdb_device_free((Itdb_Device *) handle);
101
+ }
102
+
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
+ static VALUE rbpod_device_allocate(VALUE self) {
108
+ return rbpod_device_wrap(itdb_device_new(), TRUE);
109
+ }
110
+
111
+ void Init_rbpod_device(void) {
112
+ cRbPodDevice = rb_define_class_under(mRbPod, "Device", rb_cObject);
113
+
114
+ rb_define_alloc_func(cRbPodDevice, rbpod_device_allocate);
115
+
116
+ /* We don't want to explicitly create these, so mark the constructor as private. */
117
+ rb_define_private_method(cRbPodDevice, "initialize", rbpod_device_initialize, 0);
118
+
119
+ rb_define_method(cRbPodDevice, "[]", rbpod_device_sysinfo_get, 1);
120
+ rb_define_method(cRbPodDevice, "[]=", rbpod_device_sysinfo_set, 2);
121
+ rb_define_method(cRbPodDevice, "save!", rbpod_device_sysinfo_write, 0);
122
+
123
+ rb_define_method(cRbPodDevice, "capacity", rbpod_device_capacity_get, 0);
124
+ rb_define_method(cRbPodDevice, "generation", rbpod_device_generation_get, 0);
125
+ rb_define_method(cRbPodDevice, "model_name", rbpod_device_model_name_get, 0);
126
+ rb_define_method(cRbPodDevice, "model_number", rbpod_device_model_number_get, 0);
127
+
128
+ rb_define_method(cRbPodDevice, "supports_photos?", rbpod_device_has_photo_support, 0);
129
+ rb_define_method(cRbPodDevice, "supports_videos?", rbpod_device_has_video_support, 0);
130
+ rb_define_method(cRbPodDevice, "supports_artwork?", rbpod_device_has_artwork_support, 0);
131
+ rb_define_method(cRbPodDevice, "supports_podcasts?", rbpod_device_has_podcast_support, 0);
132
+ rb_define_method(cRbPodDevice, "supports_chapter_images?", rbpod_device_has_chapter_image_support, 0);
133
+
134
+ return;
135
+ }
136
+
@@ -0,0 +1,12 @@
1
+ /* device.h */
2
+
3
+ #ifndef RBPOD_DEVICE_H
4
+ #define RBPOD_DEVICE_H
5
+
6
+ extern VALUE cRbPodDevice;
7
+
8
+ void Init_rbpod_device(void);
9
+
10
+ inline VALUE rbpod_device_wrap(Itdb_Device *device, gboolean freeable);
11
+
12
+ #endif /* RBPOD_DEVICE_H */
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mkmf'
4
+
5
+ abort "Please install libgpod-1.0" unless pkg_config('libgpod-1.0')
6
+
7
+ create_makefile('rbpod/rbpod')
@@ -0,0 +1,85 @@
1
+ /* playlist.c */
2
+
3
+ #include "rbpod.h"
4
+ #include "track.h"
5
+ #include "playlist.h"
6
+
7
+ VALUE cRbPodPlaylist;
8
+
9
+ static inline Itdb_Playlist *rbpod_playlist_unwrap(VALUE self) {
10
+ Itdb_Playlist *playlist = NULL;
11
+ Data_Get_Struct(self, Itdb_Playlist, playlist);
12
+ return playlist;
13
+ }
14
+
15
+ static VALUE rbpod_playlist_is_podcast(VALUE self) {
16
+ Itdb_Playlist *playlist = rbpod_playlist_unwrap(self);
17
+ return BooleanValue(itdb_playlist_is_podcasts(playlist));
18
+ }
19
+
20
+ static VALUE rbpod_playlist_is_master(VALUE self) {
21
+ Itdb_Playlist *playlist = rbpod_playlist_unwrap(self);
22
+ return BooleanValue(itdb_playlist_is_mpl(playlist));
23
+ }
24
+
25
+ static VALUE rbpod_playlist_is_smart(VALUE self) {
26
+ Itdb_Playlist *playlist = rbpod_playlist_unwrap(self);
27
+ return BooleanValue(playlist->is_spl);
28
+ }
29
+
30
+ static VALUE rbpod_playlist_tracks_get(VALUE self) {
31
+ Itdb_Playlist *playlist = rbpod_playlist_unwrap(self);
32
+ return rbpod_collection_wrap(playlist->members, cRbPodTrack, FALSE);
33
+ }
34
+
35
+ static VALUE rbpod_playlist_length_get(VALUE self) {
36
+ Itdb_Playlist *playlist = rbpod_playlist_unwrap(self);
37
+ return INT2NUM(playlist->num);
38
+ }
39
+
40
+ static VALUE rbpod_playlist_name_get(VALUE self) {
41
+ Itdb_Playlist *playlist = rbpod_playlist_unwrap(self);
42
+ return rb_str_new2(playlist->name);
43
+ }
44
+
45
+ static VALUE rbpod_playlist_id_get(VALUE self) {
46
+ Itdb_Playlist *playlist = rbpod_playlist_unwrap(self);
47
+ return INT2FIX(playlist->id);
48
+ }
49
+
50
+ static VALUE rbpod_playlist_initialize(VALUE self) {
51
+ return self;
52
+ }
53
+
54
+ static void rbpod_playlist_deallocate(void *handle) {
55
+ itdb_playlist_free((Itdb_Playlist *) handle);
56
+ }
57
+
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
+ static VALUE rbpod_playlist_allocate(VALUE self) {
63
+ Itdb_Playlist *playlist = itdb_playlist_new("Untitled Playlist", FALSE);
64
+ return rbpod_playlist_wrap(playlist, TRUE);
65
+ }
66
+
67
+ void Init_rbpod_playlist(void) {
68
+ cRbPodPlaylist = rb_define_class_under(mRbPod, "Playlist", rb_cObject);
69
+
70
+ rb_define_alloc_func(cRbPodPlaylist, rbpod_playlist_allocate);
71
+
72
+ rb_define_method(cRbPodPlaylist, "initialize", rbpod_playlist_initialize, 0);
73
+
74
+ rb_define_method(cRbPodPlaylist, "id", rbpod_playlist_id_get, 0);
75
+ rb_define_method(cRbPodPlaylist, "name", rbpod_playlist_name_get, 0);
76
+ rb_define_method(cRbPodPlaylist, "length", rbpod_playlist_length_get, 0);
77
+ rb_define_method(cRbPodPlaylist, "tracks", rbpod_playlist_tracks_get, 0);
78
+
79
+ rb_define_method(cRbPodPlaylist, "smart_playlist?", rbpod_playlist_is_smart, 0);
80
+ rb_define_method(cRbPodPlaylist, "master_playlist?", rbpod_playlist_is_master, 0);
81
+ rb_define_method(cRbPodPlaylist, "podcast_playlist?", rbpod_playlist_is_podcast, 0);
82
+
83
+ return;
84
+ }
85
+
@@ -0,0 +1,12 @@
1
+ /* playlist.h */
2
+
3
+ #ifndef RBPOD_PLAYLIST_H
4
+ #define RBPOD_PLAYLIST_H
5
+
6
+ extern VALUE cRbPodPlaylist;
7
+
8
+ void Init_rbpod_playlist(void);
9
+
10
+ inline VALUE rbpod_playlist_wrap(Itdb_Playlist *playlist, gboolean freeable);
11
+
12
+ #endif /* RBPOD_PLAYLIST_H */
data/ext/rbpod/rbpod.c ADDED
@@ -0,0 +1,34 @@
1
+ /* rbpod.c */
2
+
3
+ #include "rbpod.h"
4
+ #include "track.h"
5
+ #include "device.h"
6
+ #include "playlist.h"
7
+ #include "database.h"
8
+ #include "collection.h"
9
+
10
+ VALUE mRbPod;
11
+
12
+ void Init_rbpod(void) {
13
+ /* Set up the top-level RbPod module. */
14
+ mRbPod = rb_define_module("RbPod");
15
+
16
+ /* Set up the RbPod::Database class. */
17
+ Init_rbpod_database();
18
+
19
+ /* Set up the RbPod::Device class. */
20
+ Init_rbpod_device();
21
+
22
+ /* Set up the RbPod::Collection class. */
23
+ Init_rbpod_collection();
24
+
25
+ /* Set up the RbPod::Playlist class. */
26
+ Init_rbpod_playlist();
27
+
28
+ /* Set up the RbPod::Track class. */
29
+ Init_rbpod_track();
30
+
31
+ return;
32
+ }
33
+
34
+
data/ext/rbpod/rbpod.h ADDED
@@ -0,0 +1,13 @@
1
+ /* rbpod.h */
2
+
3
+ #ifndef RBPOD_H
4
+ #define RBPOD_H
5
+
6
+ #include <ruby.h>
7
+ #include <gpod/itdb.h>
8
+
9
+ #define BooleanValue(value) (value) ? Qtrue : Qfalse
10
+
11
+ extern VALUE mRbPod;
12
+
13
+ #endif /* RBPOD_H */
data/ext/rbpod/track.c ADDED
@@ -0,0 +1,84 @@
1
+ /* track.c */
2
+
3
+ #include "rbpod.h"
4
+ #include "track.h"
5
+
6
+ VALUE cRbPodTrack;
7
+
8
+ static inline Itdb_Track *rbpod_track_unwrap(VALUE self) {
9
+ Itdb_Track *track = NULL;
10
+ Data_Get_Struct(self, Itdb_Track, track);
11
+ return track;
12
+ }
13
+
14
+ static VALUE rbpod_track_is_transferred(VALUE self) {
15
+ Itdb_Track *track = rbpod_track_unwrap(self);
16
+ return BooleanValue(track->transferred);
17
+ }
18
+
19
+ static VALUE rbpod_track_ipod_path_get(VALUE self) {
20
+ Itdb_Track *track = rbpod_track_unwrap(self);
21
+ return rb_str_new2(track->ipod_path);
22
+ }
23
+
24
+ static VALUE rbpod_track_file_type_get(VALUE self) {
25
+ Itdb_Track *track = rbpod_track_unwrap(self);
26
+ return rb_str_new2(track->filetype);
27
+ }
28
+
29
+ static VALUE rbpod_track_artist_get(VALUE self) {
30
+ Itdb_Track *track = rbpod_track_unwrap(self);
31
+ return rb_str_new2(track->artist);
32
+ }
33
+
34
+ static VALUE rbpod_track_album_get(VALUE self) {
35
+ Itdb_Track *track = rbpod_track_unwrap(self);
36
+ return rb_str_new2(track->album);
37
+ }
38
+
39
+ static VALUE rbpod_track_title_get(VALUE self) {
40
+ Itdb_Track *track = rbpod_track_unwrap(self);
41
+ return rb_str_new2(track->title);
42
+ }
43
+
44
+ static VALUE rbpod_track_id_get(VALUE self) {
45
+ Itdb_Track *track = rbpod_track_unwrap(self);
46
+ return rb_str_new2(track->filetype);
47
+ }
48
+
49
+ static VALUE rbpod_track_initialize(VALUE self) {
50
+ return self;
51
+ }
52
+
53
+ static void rbpod_track_deallocate(void *handle) {
54
+ itdb_track_free((Itdb_Track *) handle);
55
+ return;
56
+ }
57
+
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
+ static VALUE rbpod_track_allocate(VALUE self) {
63
+ return rbpod_track_wrap(itdb_track_new(), TRUE);
64
+ }
65
+
66
+ void Init_rbpod_track(void) {
67
+ cRbPodTrack = rb_define_class_under(mRbPod, "Track", rb_cObject);
68
+
69
+ rb_define_alloc_func(cRbPodTrack, rbpod_track_allocate);
70
+
71
+ rb_define_method(cRbPodTrack, "initialize", rbpod_track_initialize, 0);
72
+
73
+ rb_define_method(cRbPodTrack, "id", rbpod_track_id_get, 0);
74
+ rb_define_method(cRbPodTrack, "title", rbpod_track_title_get, 0);
75
+ rb_define_method(cRbPodTrack, "album", rbpod_track_album_get, 0);
76
+ rb_define_method(cRbPodTrack, "artist", rbpod_track_artist_get, 0);
77
+ rb_define_method(cRbPodTrack, "file_type", rbpod_track_file_type_get, 0);
78
+ rb_define_method(cRbPodTrack, "ipod_path", rbpod_track_ipod_path_get, 0);
79
+
80
+ rb_define_method(cRbPodTrack, "transferred?", rbpod_track_is_transferred, 0);
81
+
82
+ return;
83
+ }
84
+
data/ext/rbpod/track.h ADDED
@@ -0,0 +1,12 @@
1
+ /* track.h */
2
+
3
+ #ifndef RBPOD_TRACK_H
4
+ #define RBPOD_TRACK_H
5
+
6
+ extern VALUE cRbPodTrack;
7
+
8
+ void Init_rbpod_track(void);
9
+
10
+ inline VALUE rbpod_track_wrap(Itdb_Track *track, gboolean freeable);
11
+
12
+ #endif /* RBPOD_TRACK_H */
@@ -0,0 +1,3 @@
1
+ module RbPod
2
+ VERSION = "0.0.1"
3
+ end
data/lib/rbpod.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'rbpod/version'
2
+ require 'rbpod/rbpod'
data/rbpod.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rbpod/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rbpod"
8
+ spec.version = RbPod::VERSION
9
+
10
+ spec.authors = ["Joshua M. Keyes"]
11
+ spec.email = ["joshua.michael.keyes@gmail.com"]
12
+
13
+ spec.summary = %q{Ruby bindings to the libgpod library.}
14
+ spec.description = %q{Lightweight native bindings to the libgpod library.}
15
+ spec.homepage = "https://github.com/jmkeyes/rbpod"
16
+ spec.requirements << 'libgpod-1.0'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files`.split($/)
20
+ spec.extensions = ["ext/rbpod/extconf.rb"]
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.3'
26
+ spec.add_development_dependency 'rake'
27
+
28
+ spec.add_dependency 'trollop', '~> 2.0'
29
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbpod
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joshua M. Keyes
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
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: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: trollop
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ description: Lightweight native bindings to the libgpod library.
63
+ email:
64
+ - joshua.michael.keyes@gmail.com
65
+ executables:
66
+ - rbpod
67
+ extensions:
68
+ - ext/rbpod/extconf.rb
69
+ extra_rdoc_files: []
70
+ files:
71
+ - .gitignore
72
+ - Gemfile
73
+ - LICENSE.txt
74
+ - README.md
75
+ - Rakefile
76
+ - bin/rbpod
77
+ - ext/rbpod/collection.c
78
+ - ext/rbpod/collection.h
79
+ - ext/rbpod/database.c
80
+ - ext/rbpod/database.h
81
+ - ext/rbpod/device.c
82
+ - ext/rbpod/device.h
83
+ - ext/rbpod/extconf.rb
84
+ - ext/rbpod/playlist.c
85
+ - ext/rbpod/playlist.h
86
+ - ext/rbpod/rbpod.c
87
+ - ext/rbpod/rbpod.h
88
+ - ext/rbpod/track.c
89
+ - ext/rbpod/track.h
90
+ - lib/rbpod.rb
91
+ - lib/rbpod/version.rb
92
+ - rbpod.gemspec
93
+ homepage: https://github.com/jmkeyes/rbpod
94
+ licenses:
95
+ - MIT
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements:
113
+ - libgpod-1.0
114
+ rubyforge_project:
115
+ rubygems_version: 1.8.23
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: Ruby bindings to the libgpod library.
119
+ test_files: []