rbpod 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rspec +1 -0
- data/README.md +75 -29
- data/Rakefile +12 -0
- data/ext/rbpod/collection.c +44 -17
- data/ext/rbpod/collection.h +1 -1
- data/ext/rbpod/database.c +112 -57
- data/ext/rbpod/database.h +1 -1
- data/ext/rbpod/device.c +55 -30
- data/ext/rbpod/device.h +1 -1
- data/ext/rbpod/extconf.rb +3 -0
- data/ext/rbpod/playlist.c +55 -34
- data/ext/rbpod/playlist.h +1 -4
- data/ext/rbpod/playlist_collection.c +77 -0
- data/ext/rbpod/playlist_collection.h +14 -0
- data/ext/rbpod/rbpod.c +31 -12
- data/ext/rbpod/rbpod.h +4 -2
- data/ext/rbpod/track.c +26 -25
- data/ext/rbpod/track.h +1 -4
- data/ext/rbpod/track_collection.c +33 -0
- data/ext/rbpod/track_collection.h +14 -0
- data/lib/rbpod/version.rb +1 -1
- data/rbpod.gemspec +1 -0
- data/spec/collection_spec.rb +39 -0
- data/spec/database_spec.rb +98 -0
- data/spec/device_spec.rb +83 -0
- data/spec/playlist_spec.rb +3 -0
- data/spec/rbpod_spec.rb +3 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/track_spec.rb +3 -0
- metadata +37 -4
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/README.md
CHANGED
@@ -18,47 +18,93 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
Functional for most read-only purposes.
|
21
|
+
Functional for most read-only purposes. To get started, add `require 'rbpod'` to your script.
|
22
22
|
|
23
|
-
|
23
|
+
### RbPod::Database
|
24
24
|
|
25
|
-
|
25
|
+
To load a database from the filesystem:
|
26
26
|
|
27
|
-
|
28
|
-
database = RbPod::Database.new('/mnt/ipod/') # => #<RbPod::Database:0x8733fa4>
|
27
|
+
database = RbPod::Database.new('/mnt/ipod/') # => #<RbPod::Database:0xdeadbeef>
|
29
28
|
|
30
29
|
database.version # => 42
|
31
30
|
database.mountpoint # => "/mnt/ipod/"
|
32
31
|
database.filename # => "/mnt/ipod/iPod_Control/iTunes/iTunesDB"
|
33
32
|
database.synchronized? # => true
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
database.
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
database.device
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
#
|
34
|
+
If you'd like to create a blank database, you can do that too:
|
35
|
+
|
36
|
+
database = RbPod::Database.create!('/tmp/ipod-blank') # => #<RbPod::Database:0xdeadbeef>
|
37
|
+
|
38
|
+
### RbPod::Device
|
39
|
+
|
40
|
+
The device (if any) that backs the database can be interrogated:
|
41
|
+
|
42
|
+
device = database.device # => #<RbPod::Device:0xdeadbeef>
|
43
|
+
|
44
|
+
# Model name, number, and capacity.
|
45
|
+
device.capacity # => 4.0
|
46
|
+
device.generation # => "Nano Video (3rd Gen.)"
|
47
|
+
device.model_name # => "Nano (Silver)"
|
48
|
+
device.model_number # => "A978"
|
49
|
+
|
50
|
+
# Feature support.
|
51
|
+
device.supports_photos? # => true
|
52
|
+
device.supports_videos? # => true
|
53
|
+
device.supports_artwork? # => true
|
54
|
+
device.supports_podcasts? # => true
|
55
|
+
device.supports_chapter_images? # => true
|
56
|
+
|
57
|
+
# Reading/writing SysInfo. Set a key to nil to erase it.
|
58
|
+
device['ModelNumStr'] # => "xA978"
|
59
|
+
device['PotsdamConf45'] = "Kilroy Was Here"
|
60
|
+
device.save!
|
61
|
+
|
62
|
+
### RbPod::Collection
|
63
|
+
|
64
|
+
All methods that return lists return a `Collection` enumerator decorated depending on it's contents:
|
65
|
+
|
66
|
+
database.playlists # => #<RbPod::Collection:0xdeadbeef>
|
67
|
+
|
68
|
+
# For a list of all the names of playlists on the iPod:
|
54
69
|
database.playlists.map(&:name) # => ["iPod", "Podcasts", "Recently Added"]
|
55
70
|
|
56
|
-
#
|
57
|
-
database.
|
58
|
-
|
59
|
-
|
71
|
+
# For direct access to the master playlist:
|
72
|
+
database.playlists.master # => #<RbPod::Playlist:0xdeadbeef>
|
73
|
+
|
74
|
+
# For direct access to the podcasts playlist:
|
75
|
+
database.playlists.podcasts # => #<RbPod::Playlist:0xdeadbeef>
|
76
|
+
|
77
|
+
### RbPod::Playlist
|
78
|
+
|
79
|
+
All playlists support a variety of methods:
|
80
|
+
|
81
|
+
playlist = database.playlists.master
|
82
|
+
|
83
|
+
playlist.name # => "iPod"
|
84
|
+
playlist.length # => 400
|
85
|
+
playlist.created_on # => 2008-04-05 08:47:46 -0700
|
86
|
+
|
87
|
+
playlist.master_playlist? # => true
|
88
|
+
playlist.smart_playlist? # => false
|
89
|
+
playlist.podcast_playlist? # => false
|
90
|
+
|
91
|
+
playlist.tracks # => #<RbPod::Collection:0xdeadbeef>
|
92
|
+
|
93
|
+
### RbPod::Track
|
94
|
+
|
95
|
+
Tracks also can do a lot, but not complete:
|
96
|
+
|
97
|
+
track = database.playlists.master.tracks.first
|
98
|
+
|
99
|
+
track.artist # => "Steppenwolf"
|
100
|
+
track.title # => "Born To Be Wild"
|
101
|
+
track.album # => "All Time Greatest Hits Remastered"
|
102
|
+
track.file_type # => "MPEG audio file"
|
103
|
+
track.transferred? # => true
|
104
|
+
|
105
|
+
### RbPod::Error
|
60
106
|
|
61
|
-
|
107
|
+
If anything goes belly up at run time, an `RbPod::Error` exception should be thrown with a detailed message.
|
62
108
|
|
63
109
|
## Contributing
|
64
110
|
|
data/Rakefile
CHANGED
@@ -9,6 +9,9 @@ require 'bundler/gem_tasks'
|
|
9
9
|
# Bring in RSpec's built-in rake task.
|
10
10
|
require 'rspec/core/rake_task'
|
11
11
|
|
12
|
+
# Bring in RDoc's built-in rake task.
|
13
|
+
require 'rdoc/task'
|
14
|
+
|
12
15
|
# By default, clean, compile and then test.
|
13
16
|
task :default => [ :compile, :test ]
|
14
17
|
|
@@ -30,6 +33,15 @@ RSpec::Core::RakeTask.new(:test) do |task|
|
|
30
33
|
task.ruby_opts = '-w'
|
31
34
|
end
|
32
35
|
|
36
|
+
desc "Build all RDoc documentation."
|
37
|
+
RDoc::Task.new(:rdoc) do |task|
|
38
|
+
task.main = 'README.md'
|
39
|
+
task.markup = 'markdown'
|
40
|
+
task.rdoc_files.include("README.md", 'lib/**/*.rb', 'ext/**/*.[ch]')
|
41
|
+
task.options << "--all"
|
42
|
+
task.rdoc_dir = 'doc'
|
43
|
+
end
|
44
|
+
|
33
45
|
desc "Open a console with rbpod preloaded."
|
34
46
|
task :console => [ :compile ] do
|
35
47
|
sh 'bundle console'
|
data/ext/rbpod/collection.c
CHANGED
@@ -3,53 +3,72 @@
|
|
3
3
|
#include "rbpod.h"
|
4
4
|
#include "collection.h"
|
5
5
|
|
6
|
-
|
6
|
+
struct collection {
|
7
|
+
VALUE klass;
|
8
|
+
GList *list;
|
9
|
+
};
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
inline VALUE rbpod_collection_create(GList *list, VALUE type) {
|
11
|
+
inline VALUE rbpod_collection_create(GList *list, VALUE type)
|
12
|
+
{
|
11
13
|
struct collection *collection = ALLOC(struct collection);
|
12
14
|
collection->list = list;
|
13
15
|
collection->klass = type;
|
14
16
|
return Data_Wrap_Struct(cRbPodCollection, NULL, NULL, (void *) collection);
|
15
17
|
}
|
16
18
|
|
17
|
-
static VALUE rbpod_collection_get(VALUE self, VALUE key)
|
19
|
+
static VALUE rbpod_collection_get(VALUE self, VALUE key)
|
20
|
+
{
|
18
21
|
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
19
22
|
GList *current = NULL;
|
20
23
|
|
21
|
-
if (FIXNUM_P(key) == FALSE)
|
24
|
+
if (FIXNUM_P(key) == FALSE) {
|
22
25
|
return Qnil;
|
26
|
+
}
|
23
27
|
|
24
28
|
current = g_list_nth(collection->list, FIX2INT(key));
|
25
29
|
|
26
30
|
return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
|
27
31
|
}
|
28
32
|
|
29
|
-
static VALUE rbpod_collection_last(VALUE self)
|
33
|
+
static VALUE rbpod_collection_last(VALUE self)
|
34
|
+
{
|
30
35
|
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
31
36
|
GList *current = g_list_last(collection->list);
|
37
|
+
|
38
|
+
if (current == NULL) {
|
39
|
+
return Qnil;
|
40
|
+
}
|
41
|
+
|
32
42
|
return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
|
33
43
|
}
|
34
44
|
|
35
|
-
static VALUE rbpod_collection_first(VALUE self)
|
45
|
+
static VALUE rbpod_collection_first(VALUE self)
|
46
|
+
{
|
36
47
|
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
37
48
|
GList *current = g_list_first(collection->list);
|
49
|
+
|
50
|
+
if (current == NULL) {
|
51
|
+
return Qnil;
|
52
|
+
}
|
53
|
+
|
38
54
|
return Data_Wrap_Struct(collection->klass, NULL, NULL, (void *) current->data);
|
39
55
|
}
|
40
56
|
|
41
|
-
static VALUE rbpod_collection_length(VALUE self)
|
57
|
+
static VALUE rbpod_collection_length(VALUE self)
|
58
|
+
{
|
42
59
|
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
43
60
|
return INT2NUM(g_list_length(collection->list));
|
44
61
|
}
|
45
62
|
|
46
|
-
static VALUE rbpod_collection_each(VALUE self)
|
63
|
+
static VALUE rbpod_collection_each(VALUE self)
|
64
|
+
{
|
47
65
|
struct collection *collection = TYPED_DATA_PTR(self, struct collection);
|
48
66
|
GList *current = NULL;
|
49
67
|
VALUE item;
|
50
68
|
|
51
|
-
if (rb_block_given_p() == FALSE)
|
69
|
+
if (rb_block_given_p() == FALSE) {
|
52
70
|
return rb_funcall(self, rb_intern("enum_for"), 1, ID2SYM(rb_intern("each")));
|
71
|
+
}
|
53
72
|
|
54
73
|
/* If we were supplied a block, enumerate the entire list. */
|
55
74
|
for (current = collection->list; current != NULL; current = current->next) {
|
@@ -60,35 +79,43 @@ static VALUE rbpod_collection_each(VALUE self) {
|
|
60
79
|
return Qnil;
|
61
80
|
}
|
62
81
|
|
63
|
-
static VALUE rbpod_collection_initialize(VALUE self)
|
82
|
+
static VALUE rbpod_collection_initialize(VALUE self)
|
83
|
+
{
|
64
84
|
return self;
|
65
85
|
}
|
66
86
|
|
67
|
-
static void rbpod_collection_deallocate(void *handle)
|
87
|
+
static void rbpod_collection_deallocate(void *handle)
|
88
|
+
{
|
68
89
|
struct collection *collection = (struct collection *) handle;
|
69
90
|
|
70
|
-
if (collection->list != NULL)
|
91
|
+
if (collection->list != NULL) {
|
71
92
|
g_list_free(collection->list);
|
93
|
+
}
|
72
94
|
|
73
95
|
xfree(handle);
|
74
96
|
return;
|
75
97
|
}
|
76
98
|
|
77
|
-
static VALUE rbpod_collection_allocate(VALUE self)
|
99
|
+
static VALUE rbpod_collection_allocate(VALUE self)
|
100
|
+
{
|
78
101
|
struct collection *collection = ALLOC(struct collection);
|
79
102
|
collection->list = NULL;
|
80
103
|
collection->klass = Qnil;
|
81
104
|
return Data_Wrap_Struct(cRbPodCollection, NULL, rbpod_collection_deallocate, (void *) collection);
|
82
105
|
}
|
83
106
|
|
84
|
-
void Init_rbpod_collection(void)
|
107
|
+
void Init_rbpod_collection(void)
|
108
|
+
{
|
109
|
+
#if RDOC_CAN_PARSE_DOCUMENTATION
|
110
|
+
mRbPod = rb_define_module("RbPod");
|
111
|
+
#endif
|
85
112
|
cRbPodCollection = rb_define_class_under(mRbPod, "Collection", rb_cObject);
|
86
113
|
|
87
114
|
rb_define_alloc_func(cRbPodCollection, rbpod_collection_allocate);
|
88
115
|
|
89
116
|
rb_include_module(cRbPodCollection, rb_mEnumerable);
|
90
117
|
|
91
|
-
|
118
|
+
rb_define_private_method(cRbPodCollection, "initialize", rbpod_collection_initialize, 0);
|
92
119
|
|
93
120
|
rb_define_method(cRbPodCollection, "each", rbpod_collection_each, 0);
|
94
121
|
|
data/ext/rbpod/collection.h
CHANGED
data/ext/rbpod/database.c
CHANGED
@@ -1,32 +1,38 @@
|
|
1
1
|
/* database.c */
|
2
2
|
|
3
3
|
#include "rbpod.h"
|
4
|
-
#include "track.h"
|
5
4
|
#include "device.h"
|
6
|
-
#include "playlist.h"
|
7
5
|
#include "database.h"
|
8
|
-
#include "
|
6
|
+
#include "track_collection.h"
|
7
|
+
#include "playlist_collection.h"
|
9
8
|
|
10
|
-
VALUE
|
11
|
-
|
12
|
-
static VALUE rbpod_database_write(VALUE self) {
|
9
|
+
static VALUE rbpod_database_save(VALUE self)
|
10
|
+
{
|
13
11
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
14
|
-
|
15
|
-
|
12
|
+
GError *error = NULL;
|
13
|
+
|
14
|
+
if (itdb_write(database, &error) == FALSE) {
|
15
|
+
return rbpod_raise_error(error);
|
16
|
+
}
|
17
|
+
|
18
|
+
return self;
|
16
19
|
}
|
17
20
|
|
18
|
-
static VALUE
|
21
|
+
static VALUE rbpod_database_synchronized_p(VALUE self)
|
22
|
+
{
|
19
23
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
20
24
|
guint32 nontransferred = itdb_tracks_number_nontransferred(database);
|
21
25
|
return BooleanValue(nontransferred == 0);
|
22
26
|
}
|
23
27
|
|
24
|
-
static VALUE rbpod_database_playlists_get(VALUE self)
|
28
|
+
static VALUE rbpod_database_playlists_get(VALUE self)
|
29
|
+
{
|
25
30
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
26
31
|
return rbpod_playlist_collection_create(self, database->playlists);
|
27
32
|
}
|
28
33
|
|
29
|
-
static VALUE rbpod_database_tracks_get(VALUE self)
|
34
|
+
static VALUE rbpod_database_tracks_get(VALUE self)
|
35
|
+
{
|
30
36
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
31
37
|
Itdb_Playlist *playlist = itdb_playlist_mpl(database);
|
32
38
|
/* Use the master playlist as the parent for the master track list. */
|
@@ -34,103 +40,152 @@ static VALUE rbpod_database_tracks_get(VALUE self) {
|
|
34
40
|
return rbpod_track_collection_create(parent, database->tracks);
|
35
41
|
}
|
36
42
|
|
37
|
-
static VALUE rbpod_database_device_get(VALUE self)
|
43
|
+
static VALUE rbpod_database_device_get(VALUE self)
|
44
|
+
{
|
38
45
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
39
46
|
return rbpod_device_create(database->device);
|
40
47
|
}
|
41
48
|
|
42
|
-
static VALUE rbpod_database_filename_get(VALUE self)
|
49
|
+
static VALUE rbpod_database_filename_get(VALUE self)
|
50
|
+
{
|
43
51
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
44
52
|
return rb_str_new2(database->filename);
|
45
53
|
}
|
46
54
|
|
47
|
-
static VALUE rbpod_database_version_get(VALUE self)
|
55
|
+
static VALUE rbpod_database_version_get(VALUE self)
|
56
|
+
{
|
48
57
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
49
58
|
return INT2NUM(database->version);
|
50
59
|
}
|
51
60
|
|
52
|
-
static VALUE rbpod_database_id_get(VALUE self)
|
61
|
+
static VALUE rbpod_database_id_get(VALUE self)
|
62
|
+
{
|
53
63
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
54
64
|
return INT2NUM(database->id);
|
55
65
|
}
|
56
66
|
|
57
|
-
static VALUE rbpod_database_mountpoint_get(VALUE self)
|
67
|
+
static VALUE rbpod_database_mountpoint_get(VALUE self)
|
68
|
+
{
|
58
69
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
59
70
|
return rb_str_new2(itdb_get_mountpoint(database));
|
60
71
|
}
|
61
72
|
|
62
|
-
static VALUE rbpod_database_mountpoint_set(VALUE self, VALUE path)
|
73
|
+
static VALUE rbpod_database_mountpoint_set(VALUE self, VALUE path)
|
74
|
+
{
|
63
75
|
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
64
76
|
itdb_set_mountpoint(database, StringValueCStr(path));
|
65
77
|
return rbpod_database_mountpoint_get(self);
|
66
78
|
}
|
67
79
|
|
68
|
-
static void rbpod_database_deallocate(void *handle)
|
80
|
+
static void rbpod_database_deallocate(void *handle)
|
81
|
+
{
|
69
82
|
itdb_free((Itdb_iTunesDB *) handle);
|
70
83
|
return;
|
71
84
|
}
|
72
85
|
|
73
|
-
static VALUE
|
74
|
-
|
75
|
-
Itdb_iTunesDB *database =
|
76
|
-
|
77
|
-
|
78
|
-
_mount_point = StringValueCStr(mount_point);
|
86
|
+
static VALUE rbpod_database_initialize(VALUE self, VALUE mount_point)
|
87
|
+
{
|
88
|
+
Itdb_iTunesDB *database = TYPED_DATA_PTR(self, Itdb_iTunesDB);
|
89
|
+
Itdb_iTunesDB *previous = database;
|
90
|
+
GError *error = NULL;
|
79
91
|
|
80
|
-
/*
|
81
|
-
|
92
|
+
/* Try to parse the database from the given mount point. */
|
93
|
+
database = itdb_parse(StringValueCStr(mount_point), &error);
|
82
94
|
|
83
|
-
|
84
|
-
|
85
|
-
if (itdb_init_ipod(_mount_point, _model_number, _device_name, NULL) == FALSE) {
|
86
|
-
rb_raise(eRbPodError, "Unable to format this iPod.");
|
87
|
-
return Qfalse;
|
95
|
+
if (database == NULL) {
|
96
|
+
return rbpod_raise_error(error);
|
88
97
|
}
|
89
98
|
|
90
|
-
/*
|
91
|
-
|
92
|
-
database = itdb_parse(_mount_point, NULL);
|
99
|
+
/* Overwrite our old database with the new one. */
|
100
|
+
DATA_PTR(self) = database;
|
93
101
|
|
94
|
-
|
95
|
-
|
96
|
-
return Qnil;
|
97
|
-
}
|
102
|
+
/* Free the old one. */
|
103
|
+
itdb_free(previous);
|
98
104
|
|
99
|
-
|
105
|
+
return self;
|
106
|
+
}
|
107
|
+
|
108
|
+
static VALUE rbpod_database_allocate(VALUE self)
|
109
|
+
{
|
110
|
+
Itdb_iTunesDB *database = itdb_new();
|
100
111
|
return Data_Wrap_Struct(cRbPodDatabase, NULL, rbpod_database_deallocate, (void *) database);
|
101
112
|
}
|
102
113
|
|
103
|
-
static VALUE
|
104
|
-
|
114
|
+
static VALUE rbpod_database_create(int argc, VALUE *argv, VALUE self)
|
115
|
+
{
|
116
|
+
VALUE mount_point, device_name, model_number, instance;
|
117
|
+
gchar *_mount_point, *_device_name, *_model_number;
|
118
|
+
GDir *directory = NULL;
|
119
|
+
GError *error = NULL;
|
105
120
|
|
106
|
-
|
107
|
-
|
108
|
-
|
121
|
+
if (rb_scan_args(argc, argv, "12", &mount_point, &device_name, &model_number) < 1) {
|
122
|
+
rb_raise(eRbPodError, "Invalid arguments.");
|
123
|
+
return Qnil;
|
124
|
+
}
|
109
125
|
|
110
|
-
/*
|
111
|
-
if (
|
112
|
-
rb_raise(eRbPodError, "
|
126
|
+
/* Reject the mount point immediately if it isn't a string. */
|
127
|
+
if (TYPE(mount_point) != T_STRING && RSTRING_LEN(mount_point) > 0) {
|
128
|
+
rb_raise(eRbPodError, "Mount point must be a non-empty string.");
|
113
129
|
return Qnil;
|
114
130
|
}
|
115
131
|
|
116
|
-
|
132
|
+
/* If we didn't specify a device name, default to 'iPod'. */
|
133
|
+
if (NIL_P(device_name) == TRUE) {
|
134
|
+
device_name = rb_str_new2("iPod");
|
135
|
+
}
|
117
136
|
|
118
|
-
|
119
|
-
|
137
|
+
/* If the specified device name isn't a string of at least three characters, bail now. */
|
138
|
+
if (TYPE(device_name) != T_STRING || RSTRING_LEN(device_name) < 3) {
|
139
|
+
rb_raise(eRbPodError, "Device name should be a string of at least three characters.");
|
140
|
+
return Qnil;
|
141
|
+
}
|
120
142
|
|
121
|
-
|
122
|
-
|
123
|
-
|
143
|
+
/* If the specified model number is specified but isn't a string, bail now. TODO: Use a regexp, stupid. */
|
144
|
+
if (NIL_P(model_number) == FALSE && (TYPE(model_number) != T_STRING || RSTRING_LEN(model_number) < 4)) {
|
145
|
+
rb_raise(eRbPodError, "Model number should be a string of at least four characters.");
|
146
|
+
return Qnil;
|
147
|
+
}
|
148
|
+
|
149
|
+
/* Extract pointers for glib use. */
|
150
|
+
_mount_point = StringValueCStr(mount_point);
|
151
|
+
_device_name = StringValueCStr(device_name);
|
152
|
+
|
153
|
+
/* GPod can function with a NULL model number, however, artwork may not function properly. */
|
154
|
+
_model_number = !NIL_P(model_number) ? StringValueCStr(model_number) : NULL;
|
155
|
+
|
156
|
+
/* Check if the mount point is a directory. */
|
157
|
+
directory = g_dir_open(_mount_point, 0, &error);
|
158
|
+
|
159
|
+
if (directory == NULL) {
|
160
|
+
return rbpod_raise_error(error);
|
161
|
+
}
|
162
|
+
|
163
|
+
/* Glib seems to think so... */
|
164
|
+
g_dir_close(directory);
|
165
|
+
|
166
|
+
/* Initialize the iPod at this mount point, with this device name and model number. */
|
167
|
+
if (itdb_init_ipod(_mount_point, _model_number, _device_name, &error) == FALSE) {
|
168
|
+
return rbpod_raise_error(error);
|
169
|
+
}
|
170
|
+
|
171
|
+
instance = rbpod_database_allocate(cRbPodDatabase);
|
172
|
+
|
173
|
+
/* Return an instance of this class using the newly created database. */
|
174
|
+
return rbpod_database_initialize(instance, mount_point);
|
124
175
|
}
|
125
176
|
|
126
|
-
void Init_rbpod_database(void)
|
177
|
+
void Init_rbpod_database(void)
|
178
|
+
{
|
179
|
+
#if RDOC_CAN_PARSE_DOCUMENTATION
|
180
|
+
mRbPod = rb_define_module("RbPod");
|
181
|
+
#endif
|
127
182
|
cRbPodDatabase = rb_define_class_under(mRbPod, "Database", rb_cObject);
|
128
183
|
|
129
184
|
rb_define_alloc_func(cRbPodDatabase, rbpod_database_allocate);
|
130
185
|
|
131
186
|
rb_define_method(cRbPodDatabase, "initialize", rbpod_database_initialize, 1);
|
132
187
|
|
133
|
-
rb_define_singleton_method(cRbPodDatabase, "create!", rbpod_database_create,
|
188
|
+
rb_define_singleton_method(cRbPodDatabase, "create!", rbpod_database_create, -1);
|
134
189
|
|
135
190
|
rb_define_method(cRbPodDatabase, "mountpoint", rbpod_database_mountpoint_get, 0);
|
136
191
|
rb_define_method(cRbPodDatabase, "mountpoint=", rbpod_database_mountpoint_set, 1);
|
@@ -143,8 +198,8 @@ void Init_rbpod_database(void) {
|
|
143
198
|
rb_define_method(cRbPodDatabase, "tracks", rbpod_database_tracks_get, 0);
|
144
199
|
rb_define_method(cRbPodDatabase, "playlists", rbpod_database_playlists_get, 0);
|
145
200
|
|
146
|
-
rb_define_method(cRbPodDatabase, "synchronized?",
|
201
|
+
rb_define_method(cRbPodDatabase, "synchronized?", rbpod_database_synchronized_p, 0);
|
147
202
|
|
148
|
-
rb_define_method(cRbPodDatabase, "
|
203
|
+
rb_define_method(cRbPodDatabase, "save!", rbpod_database_save, 0);
|
149
204
|
}
|
150
205
|
|