itunes-controller 0.1.0

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.
Files changed (45) hide show
  1. data/.buildpath +5 -0
  2. data/.gitignore +3 -0
  3. data/.project +17 -0
  4. data/.rvmrc +81 -0
  5. data/LICENSE +674 -0
  6. data/README +27 -0
  7. data/Rakefile +27 -0
  8. data/TODO +8 -0
  9. data/bin/addFiles.rb +35 -0
  10. data/bin/dummyiTunesController.rb +109 -0
  11. data/bin/itunesController.rb +78 -0
  12. data/bin/listDeadTracks.rb +45 -0
  13. data/bin/listNewTracks.rb +88 -0
  14. data/bin/recreateTrackCache.rb +31 -0
  15. data/bin/refreshFiles.rb +42 -0
  16. data/bin/removeDeadTracks.rb +31 -0
  17. data/bin/removeFiles.rb +42 -0
  18. data/bin/trackInfo.rb +50 -0
  19. data/itunes-controller.gemspec +24 -0
  20. data/jar-stuff.sh +24 -0
  21. data/lib/itunesController/application.rb +127 -0
  22. data/lib/itunesController/cachedcontroller.rb +188 -0
  23. data/lib/itunesController/config.rb +95 -0
  24. data/lib/itunesController/controller_creator.rb +29 -0
  25. data/lib/itunesController/controllserver.rb +583 -0
  26. data/lib/itunesController/database/backend.rb +41 -0
  27. data/lib/itunesController/database/database.rb +166 -0
  28. data/lib/itunesController/database/sqlite3_backend.rb +67 -0
  29. data/lib/itunesController/debug.rb +124 -0
  30. data/lib/itunesController/dummy_itunes_track.rb +40 -0
  31. data/lib/itunesController/dummy_itunescontroller.rb +142 -0
  32. data/lib/itunesController/itunescontroller.rb +90 -0
  33. data/lib/itunesController/itunescontroller_factory.rb +51 -0
  34. data/lib/itunesController/kinds.rb +138 -0
  35. data/lib/itunesController/logging.rb +119 -0
  36. data/lib/itunesController/macosx_itunescontroller.rb +204 -0
  37. data/lib/itunesController/platform.rb +53 -0
  38. data/lib/itunesController/sqlite_creator.rb +35 -0
  39. data/lib/itunesController/track.rb +39 -0
  40. data/lib/itunesController/version.rb +25 -0
  41. data/lib/itunesController/windows_itunescontroller.rb +145 -0
  42. data/test/base_server_test_case.rb +125 -0
  43. data/test/dummy_client.rb +44 -0
  44. data/test/test_server.rb +312 -0
  45. 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