itunes-controller 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.buildpath +5 -0
- data/.gitignore +3 -0
- data/.project +17 -0
- data/.rvmrc +81 -0
- data/LICENSE +674 -0
- data/README +27 -0
- data/Rakefile +27 -0
- data/TODO +8 -0
- data/bin/addFiles.rb +35 -0
- data/bin/dummyiTunesController.rb +109 -0
- data/bin/itunesController.rb +78 -0
- data/bin/listDeadTracks.rb +45 -0
- data/bin/listNewTracks.rb +88 -0
- data/bin/recreateTrackCache.rb +31 -0
- data/bin/refreshFiles.rb +42 -0
- data/bin/removeDeadTracks.rb +31 -0
- data/bin/removeFiles.rb +42 -0
- data/bin/trackInfo.rb +50 -0
- data/itunes-controller.gemspec +24 -0
- data/jar-stuff.sh +24 -0
- data/lib/itunesController/application.rb +127 -0
- data/lib/itunesController/cachedcontroller.rb +188 -0
- data/lib/itunesController/config.rb +95 -0
- data/lib/itunesController/controller_creator.rb +29 -0
- data/lib/itunesController/controllserver.rb +583 -0
- data/lib/itunesController/database/backend.rb +41 -0
- data/lib/itunesController/database/database.rb +166 -0
- data/lib/itunesController/database/sqlite3_backend.rb +67 -0
- data/lib/itunesController/debug.rb +124 -0
- data/lib/itunesController/dummy_itunes_track.rb +40 -0
- data/lib/itunesController/dummy_itunescontroller.rb +142 -0
- data/lib/itunesController/itunescontroller.rb +90 -0
- data/lib/itunesController/itunescontroller_factory.rb +51 -0
- data/lib/itunesController/kinds.rb +138 -0
- data/lib/itunesController/logging.rb +119 -0
- data/lib/itunesController/macosx_itunescontroller.rb +204 -0
- data/lib/itunesController/platform.rb +53 -0
- data/lib/itunesController/sqlite_creator.rb +35 -0
- data/lib/itunesController/track.rb +39 -0
- data/lib/itunesController/version.rb +25 -0
- data/lib/itunesController/windows_itunescontroller.rb +145 -0
- data/test/base_server_test_case.rb +125 -0
- data/test/dummy_client.rb +44 -0
- data/test/test_server.rb +312 -0
- metadata +185 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2011-2012 John-Paul.Stanford <dev@stanwood.org.uk>
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
#
|
17
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
18
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
19
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
module ItunesController
|
23
|
+
|
24
|
+
# This is the base class of all itunes controller.
|
25
|
+
# @abstract This class should be overridden to implement the class that talks to iTunes.
|
26
|
+
class BaseITunesController
|
27
|
+
|
28
|
+
# The constructor
|
29
|
+
def initialize()
|
30
|
+
end
|
31
|
+
|
32
|
+
# Used to get the iTunes version
|
33
|
+
# @abstract Must be overridden
|
34
|
+
# @return [String] The itunes version
|
35
|
+
def version
|
36
|
+
raise "ERROR: Your trying to instantiate an abstract class"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Used to remove tracks from the libaray
|
40
|
+
# @abstract Must be overridden
|
41
|
+
# @param [Array] tracks A list of tracks to remove from the itunes libaray
|
42
|
+
def removeTracksFromLibrary(tracks)
|
43
|
+
raise "ERROR: Your trying to instantiate an abstract class"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Used to add a list of files to the itunes library
|
47
|
+
# @abstract Must be overridden
|
48
|
+
# @param [Array[String]] A list of files to add to the itunes library
|
49
|
+
# @return [Array[ItunesController::Track]] List of ids of the new tracks once they are in the database
|
50
|
+
def addFilesToLibrary(files)
|
51
|
+
raise "ERROR: Your trying to instantiate an abstract class"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Used to tell iTunes to refresh a list of tracks data from the info stored in the files
|
55
|
+
# @abstract Must be overridden
|
56
|
+
# @param [Array] tracks A list of tracks to fresh
|
57
|
+
def refreshTracks(tracks)
|
58
|
+
raise "ERROR: Your trying to instantiate an abstract class"
|
59
|
+
end
|
60
|
+
|
61
|
+
# @abstract Must be overridden
|
62
|
+
def getTracks(&b)
|
63
|
+
raise "ERROR: Your trying to instantiate an abstract class"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Used to search the itunes library
|
67
|
+
# @param term The search term
|
68
|
+
# @return [Array] a list of iTunes track that match the search term
|
69
|
+
# @abstract Must be overridden
|
70
|
+
def searchLibrary(term)
|
71
|
+
raise "ERROR: Your trying to instantiate an abstract class"
|
72
|
+
end
|
73
|
+
|
74
|
+
# Used to find the number of tracks in the library
|
75
|
+
# @abstract Must be overridden
|
76
|
+
# @return [Number] The number of tracks
|
77
|
+
def getTrackCount()
|
78
|
+
raise "ERROR: Your trying to instantiate an abstract class"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Used to get the database of a itunes track
|
82
|
+
# @abstract Must be overridden
|
83
|
+
# @param track the track
|
84
|
+
# @return The database id
|
85
|
+
def getTrackDatabaseId(track)
|
86
|
+
raise "ERROR: Your trying to instantiate an abstract class"
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2011-2012 John-Paul.Stanford <dev@stanwood.org.uk>
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
#
|
17
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
18
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
19
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
require 'itunesController/platform'
|
23
|
+
if ItunesController::Platform::isWindows()
|
24
|
+
require 'itunesController/windows_itunescontroller.rb'
|
25
|
+
elsif ItunesController::Platform::isMacOSX()
|
26
|
+
require 'itunesController/macosx_itunescontroller.rb'
|
27
|
+
else
|
28
|
+
raise("Unsupported operating system #{RUBY_PLATFORM}.")
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'itunesController/database/database'
|
32
|
+
|
33
|
+
module ItunesController
|
34
|
+
|
35
|
+
# This is a factory class used to create a iTunes controller for the current platform
|
36
|
+
class ITunesControllerFactory
|
37
|
+
|
38
|
+
# Used to create the iTunes controller for different platforms
|
39
|
+
# @return [ItunesController::BaseITunesController] The itunes controller
|
40
|
+
# @raise If the platform is unsupported
|
41
|
+
def self.createController()
|
42
|
+
if ItunesController::Platform::isWindows()
|
43
|
+
return ItunesController::WindowsITunesController.new()
|
44
|
+
elsif ItunesController::Platform::isMacOSX()
|
45
|
+
return ItunesController::MacOSXITunesController.new()
|
46
|
+
else
|
47
|
+
raise("Unsupported operating system #{RUBY_PLATFORM}.")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2011-2012 John-Paul.Stanford <dev@stanwood.org.uk>
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
#
|
17
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
18
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
19
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
module ItunesController
|
23
|
+
|
24
|
+
# A enum of special kinds
|
25
|
+
# @attr [Number] kind The Source kind ID
|
26
|
+
# @attr [String] String the source display name
|
27
|
+
class SpecialKind
|
28
|
+
attr_accessor :kind, :displayName
|
29
|
+
def initialize(kind,displayName)
|
30
|
+
@kind = kind
|
31
|
+
@displayName = displayName
|
32
|
+
end
|
33
|
+
|
34
|
+
# The Audio Book kind
|
35
|
+
Audiobooks=SpecialKind.new(1800630337,"Audiobooks")
|
36
|
+
# The folder kind
|
37
|
+
Folder=SpecialKind.new(1800630342,"Folder")
|
38
|
+
# The movie kind
|
39
|
+
Movies=SpecialKind.new(1800630345,"Movies")
|
40
|
+
# The music kind
|
41
|
+
Music=SpecialKind.new(1800630362,"Music")
|
42
|
+
# The none kind
|
43
|
+
None=SpecialKind.new(1800302446,"None")
|
44
|
+
# The party shuffle kind
|
45
|
+
PartyShuffle=SpecialKind.new(1800630355,"Party Shuffle")
|
46
|
+
# The pod cast kind
|
47
|
+
Podcasts=SpecialKind.new(1800630352,"Podcasts")
|
48
|
+
# The purchased music kind
|
49
|
+
PurchasedMusic=SpecialKind.new(1800630349,"Purchased Music")
|
50
|
+
# The TV show kind
|
51
|
+
TVShows=SpecialKind.new(1800630356,"TV Shows")
|
52
|
+
# The video kind
|
53
|
+
Videos=SpecialKind.new(1800630358,"Videos")
|
54
|
+
# The genius kind
|
55
|
+
Genius=SpecialKind.new(1800630343,"Genius")
|
56
|
+
# The iTunesU kind
|
57
|
+
ITunesU=SpecialKind.new(1800630357,"iTunes U")
|
58
|
+
# The library kind
|
59
|
+
Library=SpecialKind.new(1800630348,"Library")
|
60
|
+
# The unknown kind
|
61
|
+
Unknown=SpecialKind.new(-1,"Unknown")
|
62
|
+
|
63
|
+
@@values=[Audiobooks,Folder,Movies,Music,
|
64
|
+
None,PartyShuffle,Podcasts,PurchasedMusic,
|
65
|
+
TVShows, Videos,Genius,ITunesU,Library,Unknown]
|
66
|
+
|
67
|
+
# A class scoped method used to get the kind associated with the kind ID
|
68
|
+
# @param kind The kind ID
|
69
|
+
# @return [ItunesController::SourceKind] The source kind object
|
70
|
+
def self.fromKind(kind)
|
71
|
+
@@values.each { | v1 |
|
72
|
+
if (v1.kind==kind)
|
73
|
+
return v1
|
74
|
+
end
|
75
|
+
}
|
76
|
+
return SpecialKind.new(v1,"Unknown")
|
77
|
+
end
|
78
|
+
|
79
|
+
# Used pretty print the kind to a string
|
80
|
+
# @return A string containing the kind display name and ID
|
81
|
+
def to_s
|
82
|
+
return "#{displayName} (#{kind})"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Enum of source kinds
|
87
|
+
# @attr [Number] kind The Source kind ID
|
88
|
+
# @attr [String] String the source display name
|
89
|
+
class SourceKind
|
90
|
+
|
91
|
+
attr_accessor :kind, :displayName
|
92
|
+
|
93
|
+
# The constructor
|
94
|
+
# @param [Number] kind The kind ID
|
95
|
+
# @param [String] displayName The kind display name
|
96
|
+
def initialize(kind,displayName)
|
97
|
+
@kind = kind
|
98
|
+
@displayName = displayName
|
99
|
+
end
|
100
|
+
|
101
|
+
# The Audio CD Source Kind
|
102
|
+
AudioCD=SourceKind.new(1799439172,"Audio CD")
|
103
|
+
# The Device Source Kind
|
104
|
+
Device=SourceKind.new(1799644534,"Device")
|
105
|
+
# The iPod Source Kind
|
106
|
+
IPod=SourceKind.new(1800433508,"iPod")
|
107
|
+
# The Library Source Kind
|
108
|
+
Library=SourceKind.new(1800169826,"Library")
|
109
|
+
# The MP3 CD Source Kind
|
110
|
+
MP3CD=SourceKind.new(1800225604,"MP3 CD")
|
111
|
+
# The Radio Tuner Source Kind
|
112
|
+
RadioTuner=SourceKind.new(1800697198,"Radio Tuner")
|
113
|
+
# The Shared Libarary Source Kind
|
114
|
+
SharedLibrary=SourceKind.new(1800628324,"Shared Library")
|
115
|
+
# The Unknown Source Kind
|
116
|
+
Unknown=SourceKind.new(1800760938,"Unknown")
|
117
|
+
|
118
|
+
@@values=[AudioCD,Device,IPod,Library,MP3CD,RadioTuner,SharedLibrary,Unknown]
|
119
|
+
|
120
|
+
# A class scoped method used to get the kind associated with the kind ID
|
121
|
+
# @param kind The kind ID
|
122
|
+
# @return [ItunesController::SourceKind] The source kind object
|
123
|
+
def self.fromKind(kind)
|
124
|
+
@@values.each { | v1 |
|
125
|
+
if (v1.kind==kind)
|
126
|
+
return v1
|
127
|
+
end
|
128
|
+
}
|
129
|
+
return SourceKind.new(v1,"Unknown")
|
130
|
+
end
|
131
|
+
|
132
|
+
# Used pretty print the kind to a string
|
133
|
+
# @return A string containing the kind display name and ID
|
134
|
+
def to_s
|
135
|
+
return "#{displayName} (#{kind})"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2011-2012 John-Paul.Stanford <dev@stanwood.org.uk>
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
#
|
17
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
18
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
19
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
module ItunesController
|
23
|
+
|
24
|
+
class ItunesControllerLogging
|
25
|
+
DEBUG=1
|
26
|
+
INFO=2
|
27
|
+
WARN=3
|
28
|
+
ERROR=4
|
29
|
+
|
30
|
+
# The log file, if defined then logging opertions will be sent to this file
|
31
|
+
@@logFile = nil
|
32
|
+
@@logLevel = INFO
|
33
|
+
|
34
|
+
# Used to set the location of the log file
|
35
|
+
# @param [String] file The log file location
|
36
|
+
def self.setLogFile(file)
|
37
|
+
@@logFile = file
|
38
|
+
end
|
39
|
+
|
40
|
+
# Use to set the loggin level
|
41
|
+
# @param [Number] level The logging level
|
42
|
+
def self.setLogLevel(level)
|
43
|
+
@@logLevel = level
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.setLogLevelFromString(level)
|
47
|
+
if (level=="DEBUG")
|
48
|
+
@@logLevel = DEBUG
|
49
|
+
elsif (level=="INFO")
|
50
|
+
@@logLevel = INFO
|
51
|
+
elsif (level=="WARN")
|
52
|
+
@@logLevel = WARN
|
53
|
+
elsif (level=="ERROR")
|
54
|
+
@@logLevel = ERROR
|
55
|
+
else
|
56
|
+
error("Unkown log configuration '#{level}'")
|
57
|
+
exit(1)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Used to print logging information at info level
|
62
|
+
# @param [String] msg The message to print
|
63
|
+
def self.info(msg)
|
64
|
+
if @@logLevel <= INFO
|
65
|
+
printMsg(msg)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Used to print logging information at warn level
|
70
|
+
# @param [String] msg The message to print
|
71
|
+
def self.warn(msg)
|
72
|
+
if @@logLevel <= WARN
|
73
|
+
printMsg(msg)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Used to print logging information at debug level
|
78
|
+
# @param [String] msg The message to print
|
79
|
+
def self.debug(msg)
|
80
|
+
if @@logLevel <= DEBUG
|
81
|
+
msg="DEBUG:"+msg
|
82
|
+
printMsg(msg)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Used to print logging information at debug level
|
87
|
+
# @param [String] msg The message to print
|
88
|
+
# @param exception If not nil then this exception detials will be printed
|
89
|
+
def self.error(msg,exception=nil)
|
90
|
+
if @@logLevel <= ERROR
|
91
|
+
msg="ERROR:"+msg
|
92
|
+
printMsg(msg,true)
|
93
|
+
if (exception!=nil)
|
94
|
+
printMsg(" - #{exception.message}",true)
|
95
|
+
exception.backtrace.each do | line |
|
96
|
+
printMsg(" * #{line}",true)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def self.printMsg(msg,error=false)
|
105
|
+
if (@@logFile!=nil)
|
106
|
+
out_file = File.open(@@logFile,"a") do | f |
|
107
|
+
f.puts(msg)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
if (error)
|
111
|
+
$stderr.puts(msg)
|
112
|
+
else
|
113
|
+
$stdout.puts(msg)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2011-2012 John-Paul.Stanford <dev@stanwood.org.uk>
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
#
|
17
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
18
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
19
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
# References:
|
23
|
+
# - http://code.google.com/p/itunes-rem-dupes/source/browse/trunk/itunes_update_library.rb?r=22
|
24
|
+
# - http://guides.macrumors.com/Deleting_Songs_From_iTunes
|
25
|
+
# - http://macscripter.net/viewtopic.php?id=22726
|
26
|
+
|
27
|
+
require 'itunesController/itunescontroller'
|
28
|
+
require 'itunesController/kinds'
|
29
|
+
require 'itunesController/debug'
|
30
|
+
require 'itunesController/logging'
|
31
|
+
require 'itunesController/track'
|
32
|
+
require 'rubygems'
|
33
|
+
require 'escape'
|
34
|
+
require 'open3'
|
35
|
+
require 'osx/cocoa'
|
36
|
+
|
37
|
+
include OSX
|
38
|
+
OSX.require_framework 'ScriptingBridge'
|
39
|
+
|
40
|
+
module ItunesController
|
41
|
+
|
42
|
+
# This is a iTunes controller class used to talk to itunes. This runs on macosx and makes
|
43
|
+
# use of the OSC ruby bindings. It also uses application "osascript" to execute apple scripts.
|
44
|
+
class MacOSXITunesController < ItunesController::BaseITunesController
|
45
|
+
|
46
|
+
# The constructor
|
47
|
+
def initialize()
|
48
|
+
@iTunes = SBApplication.applicationWithBundleIdentifier:'com.apple.iTunes'
|
49
|
+
library=getSourceLibrary()
|
50
|
+
@libraryPlaylists=library.libraryPlaylists
|
51
|
+
end
|
52
|
+
|
53
|
+
# Used to get the iTunes version
|
54
|
+
# @return [String] The itunes version
|
55
|
+
def version
|
56
|
+
return @iTunes.version.to_s+" (Mac OSX)"
|
57
|
+
end
|
58
|
+
|
59
|
+
# Used to tell iTunes to refresh a list of tracks data from the info stored in the files
|
60
|
+
# @param [Array] tracks A list of tracks to fresh
|
61
|
+
def refreshTracks(tracks)
|
62
|
+
ItunesController::ItunesControllerLogging::debug("refreshing tracks...")
|
63
|
+
tracks.reverse.each do | track |
|
64
|
+
track.refresh
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Used to remove tracks from the libaray
|
69
|
+
# @param [Array] tracks A list of tracks to remove from the itunes libaray
|
70
|
+
def removeTracksFromLibrary(tracks)
|
71
|
+
ItunesController::ItunesControllerLogging::debug("removing tracks...")
|
72
|
+
tracks.reverse.each do | track |
|
73
|
+
track.delete
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Used to add a list of files to the itunes library
|
78
|
+
# @param [Array[String]] A list of files to add to the itunes library
|
79
|
+
# @return [Array[ItunesController::Track]] List of ids of the new tracks once they are in the database
|
80
|
+
def addFilesToLibrary(files)
|
81
|
+
tracks=[]
|
82
|
+
files.each do | file |
|
83
|
+
script="tell application \"iTunes\"\n"
|
84
|
+
script=script+" set theTrack to (add POSIX file \"#{file}\")\n"
|
85
|
+
script=script+" return (database ID of theTrack & name of theTrack)\n"
|
86
|
+
script=script+"end tell\n"
|
87
|
+
output=executeScript(script)
|
88
|
+
if (output =~ /(\d+), (.*)/)
|
89
|
+
track=ItunesController::Track.new(file,$1.to_i,$2)
|
90
|
+
tracks.push(track)
|
91
|
+
else
|
92
|
+
ItunesController::ItunesControllerLogging::error("Unable to add file '#{file}': " + output)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
return tracks;
|
97
|
+
end
|
98
|
+
|
99
|
+
# Used to get the database of a itunes track
|
100
|
+
# @param track the track
|
101
|
+
# @return The database id
|
102
|
+
def getTrackDatabaseId(track)
|
103
|
+
return track.databaseID
|
104
|
+
end
|
105
|
+
|
106
|
+
def getTracks(&b)
|
107
|
+
ItunesController::ItunesControllerLogging::debug("Retriving track information...")
|
108
|
+
playlist=@libraryPlaylists[0]
|
109
|
+
fileTracks = playlist.fileTracks
|
110
|
+
size = fileTracks.length()
|
111
|
+
count = 1
|
112
|
+
fileTracks.each do | track |
|
113
|
+
location=track.location
|
114
|
+
path=nil
|
115
|
+
dead=false
|
116
|
+
if (location!=nil && location.isFileURL)
|
117
|
+
path=location.path
|
118
|
+
if (!File.exist?(location.path))
|
119
|
+
dead = true
|
120
|
+
end
|
121
|
+
else
|
122
|
+
dead = true
|
123
|
+
end
|
124
|
+
|
125
|
+
if (count % 1000 == 0)
|
126
|
+
ItunesController::ItunesControllerLogging::debug("Found tracks #{count} of #{size}")
|
127
|
+
end
|
128
|
+
if (track.name!=nil)
|
129
|
+
b.call(ItunesController::Track.new(path,track.databaseID,track.name),count,size,dead)
|
130
|
+
end
|
131
|
+
count=count+1
|
132
|
+
end
|
133
|
+
ItunesController::ItunesControllerLogging::debug("Found tracks #{count-1} of #{size}")
|
134
|
+
return size
|
135
|
+
end
|
136
|
+
|
137
|
+
# Used to find the number of tracks in the library
|
138
|
+
# @return [Number] The number of tracks
|
139
|
+
def getTrackCount()
|
140
|
+
playlist=@libraryPlaylists[0]
|
141
|
+
return playlist.fileTracks.length()
|
142
|
+
end
|
143
|
+
|
144
|
+
# Used to search the itunes library
|
145
|
+
# @param term The search term
|
146
|
+
# @return [Array] a list of iTunes track that match the search term
|
147
|
+
def searchLibrary(term)
|
148
|
+
tracks=[]
|
149
|
+
@libraryPlaylists.each do | playlist |
|
150
|
+
#foundTracks = playlist.searchFor(term,'kSrS')
|
151
|
+
foundTracks = playlist.searchFor_only_(term,1799449708)
|
152
|
+
if (foundTracks!=nil)
|
153
|
+
foundTracks.each do | t |
|
154
|
+
tracks.push(t)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
return tracks
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
# Used to get the libaray iTunes source
|
164
|
+
# @return The iTunes source for the library
|
165
|
+
def getSourceLibrary()
|
166
|
+
@iTunes.sources.each do |source|
|
167
|
+
if (source.kind == SourceKind::Library.kind)
|
168
|
+
return source
|
169
|
+
end
|
170
|
+
end
|
171
|
+
return nil
|
172
|
+
end
|
173
|
+
|
174
|
+
# Used to find playlists of a given media kind
|
175
|
+
# @param types The types
|
176
|
+
# @return [Array] A list of playlists
|
177
|
+
def findPlaylists(types)
|
178
|
+
playlists=[]
|
179
|
+
library=getSourceLibrary()
|
180
|
+
if (library==nil)
|
181
|
+
raise("Unable to find iTunes library")
|
182
|
+
end
|
183
|
+
|
184
|
+
library.userPlaylists.each do |pl|
|
185
|
+
kind=SpecialKind::fromKind(pl.specialKind)
|
186
|
+
types.each do |type|
|
187
|
+
if (kind.kind == type.kind)
|
188
|
+
playlists.push(pl)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
return playlists
|
194
|
+
end
|
195
|
+
|
196
|
+
# Used to execute a apple script using the system "osascript" command.
|
197
|
+
# @private
|
198
|
+
# @param script the Script contents
|
199
|
+
def executeScript(script)
|
200
|
+
stdin, stdout, stderr = Open3.popen3(Escape.shell_command(["osascript","-e",script]))
|
201
|
+
return stdout.readlines.join('\n').strip
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|