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.
- 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
data/README
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Information
|
2
|
+
-----------
|
3
|
+
|
4
|
+
This is a project to create make it possible to control enable iTunes to be operated
|
5
|
+
on a headless server without the GUI. It provides a TCP server which can be connected
|
6
|
+
to locally or remote by other applications to control iTunes.
|
7
|
+
|
8
|
+
The server only currently runs on Mac OSX It's written in such a way that if someone
|
9
|
+
knows how to script iTunes from ruby on windows, then windows support could be added.
|
10
|
+
|
11
|
+
Requirments
|
12
|
+
-----------
|
13
|
+
|
14
|
+
* iTunes (latest)
|
15
|
+
* MacOS X (tested on snow leopard)
|
16
|
+
* Mac Ruby
|
17
|
+
|
18
|
+
Installation
|
19
|
+
------------
|
20
|
+
|
21
|
+
Building
|
22
|
+
--------
|
23
|
+
|
24
|
+
If you need to rebuild gem and run all the tests, then just change to the project directory and type:
|
25
|
+
|
26
|
+
rake
|
27
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'yard'
|
4
|
+
|
5
|
+
task :default => :all
|
6
|
+
|
7
|
+
Rake::TestTask.new do |t|
|
8
|
+
t.libs << 'test'
|
9
|
+
end
|
10
|
+
|
11
|
+
YARD::Rake::YardocTask.new do |t|
|
12
|
+
# t.files = ['lib/**/*.rb','bin/**/*.rb','LICENSE','README']
|
13
|
+
t.files = ['lib/**/*.rb','bin/**/*.rb']
|
14
|
+
end
|
15
|
+
|
16
|
+
task :gem do
|
17
|
+
sh "gem build itunes-controller.gemspec"
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Execute all the build tasks"
|
21
|
+
task :all do
|
22
|
+
Rake::Task['yard'].invoke
|
23
|
+
Rake::Task['test'].invoke
|
24
|
+
Rake::Task['gem'].invoke
|
25
|
+
end
|
26
|
+
|
27
|
+
|
data/TODO
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Add support for windows iTunes
|
2
|
+
Speed up removing files
|
3
|
+
- Is their a way of finding the track associated with a file path, without search though the whole library
|
4
|
+
Replace apple script usage with ruby script bridge
|
5
|
+
Add server command to update files in the library with new details in the file
|
6
|
+
- Make sure it keeps the play counts intact
|
7
|
+
|
8
|
+
Add --version command line option
|
data/bin/addFiles.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/ruby -I../lib
|
2
|
+
#
|
3
|
+
# A command line util used to add tracks to the iTunes library
|
4
|
+
#
|
5
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
6
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
7
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'itunesController/cachedcontroller'
|
11
|
+
require 'itunesController/application'
|
12
|
+
require 'itunesController/sqlite_creator'
|
13
|
+
|
14
|
+
class App < ItunesController::Application
|
15
|
+
|
16
|
+
def displayUsage()
|
17
|
+
puts("Usage: "+@appName+" [options] files...")
|
18
|
+
puts("")
|
19
|
+
puts(genericOptionDescription())
|
20
|
+
end
|
21
|
+
|
22
|
+
def createController
|
23
|
+
return ItunesController::SQLLiteControllerCreator.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def execApp(controllerCreator)
|
27
|
+
controller = controllerCreator.createController()
|
28
|
+
ARGV.each do | path |
|
29
|
+
controller.addTrack(path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
app=App.new("addFiles.rb")
|
35
|
+
app.exec()
|
@@ -0,0 +1,109 @@
|
|
1
|
+
#!/usr/bin/ruby -I../lib
|
2
|
+
#
|
3
|
+
# Copyright (C) 2011-2012 John-Paul.Stanford <dev@stanwood.org.uk>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
19
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
20
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'tempfile'
|
24
|
+
|
25
|
+
require 'itunesController/controller_creator'
|
26
|
+
require 'itunesController/config'
|
27
|
+
require 'itunesController/controllserver'
|
28
|
+
require 'itunesController/dummy_itunescontroller'
|
29
|
+
require 'itunesController/debug'
|
30
|
+
require 'itunesController/logging'
|
31
|
+
require 'itunesController/cachedcontroller'
|
32
|
+
require 'itunesController/application'
|
33
|
+
require 'itunesController/database/sqlite3_backend'
|
34
|
+
|
35
|
+
class DummyControllerCreator < ItunesController::ControllerCreator
|
36
|
+
|
37
|
+
def initialize(controller)
|
38
|
+
@controller = controller
|
39
|
+
end
|
40
|
+
|
41
|
+
def createController()
|
42
|
+
return @controller
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class App < ItunesController::Application
|
47
|
+
|
48
|
+
DEFAULT_PORT=7000
|
49
|
+
|
50
|
+
def initialize(appName,dbPath)
|
51
|
+
super(appName)
|
52
|
+
@dbPath=dbPath
|
53
|
+
end
|
54
|
+
|
55
|
+
# Used to display the command line useage
|
56
|
+
def displayUsage()
|
57
|
+
puts("Usage: "+@appName+" [options]")
|
58
|
+
puts("")
|
59
|
+
puts(genericOptionDescription())
|
60
|
+
puts(" -p, --port PORT The port number to start the server on. Defaults to #{DEFAULT_PORT}")
|
61
|
+
puts(" -c, --config FILE The configuration file")
|
62
|
+
end
|
63
|
+
|
64
|
+
def checkAppOptions()
|
65
|
+
if (@options[:config]==nil)
|
66
|
+
usageError("No config file specified. Use --config option.")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def parseAppOptions(opts)
|
71
|
+
opts.on('-p','--port PORT','The port number to start the server on. Defaults to 7000') do |port|
|
72
|
+
@options[:port] = port;
|
73
|
+
end
|
74
|
+
opts.on('-c','--config FILE','The configuration file') do |value|
|
75
|
+
@options[:config] = value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def createController()
|
80
|
+
ItunesController::DummyITunesController::resetCommandLog()
|
81
|
+
ItunesController::DummyITunesController::resetTracks()
|
82
|
+
itunes=ItunesController::DummyITunesController.new()
|
83
|
+
dbBackend = ItunesController::SQLite3DatabaseBackend.new(@dbPath)
|
84
|
+
return DummyControllerCreator.new(ItunesController::CachedController.new(itunes,dbBackend))
|
85
|
+
end
|
86
|
+
|
87
|
+
def execApp(controllerCreator)
|
88
|
+
port=DEFAULT_PORT
|
89
|
+
config=ItunesController::ServerConfig.readConfig(@options[:config])
|
90
|
+
if (config.port!=nil)
|
91
|
+
port = config.port
|
92
|
+
end
|
93
|
+
if (@options[:port]!=nil)
|
94
|
+
port = @options[:port]
|
95
|
+
end
|
96
|
+
server=ItunesController::ITunesControlServer.new(config,port,controllerCreator)
|
97
|
+
server.join
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
dbFile = Tempfile.new('dummyDatabase.db')
|
102
|
+
begin
|
103
|
+
ItunesController::ItunesControllerLogging::info("Started dummy itunes controller with db path #{dbFile.path}")
|
104
|
+
app=App.new("itunesController.rb",dbFile.path)
|
105
|
+
app.exec()
|
106
|
+
ensure
|
107
|
+
dbFile.unlink
|
108
|
+
end
|
109
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/ruby -I../lib
|
2
|
+
#
|
3
|
+
# Copyright (C) 2011-2012 John-Paul.Stanford <dev@stanwood.org.uk>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
19
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
20
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'itunesController/config'
|
24
|
+
require 'itunesController/controllserver'
|
25
|
+
require 'itunesController/debug'
|
26
|
+
require 'itunesController/logging'
|
27
|
+
require 'itunesController/cachedcontroller'
|
28
|
+
require 'itunesController/application'
|
29
|
+
require 'itunesController/sqlite_creator'
|
30
|
+
|
31
|
+
class App < ItunesController::Application
|
32
|
+
|
33
|
+
DEFAULT_PORT=7000
|
34
|
+
|
35
|
+
# Used to display the command line useage
|
36
|
+
def displayUsage()
|
37
|
+
puts("Usage: "+@appName+" [options]")
|
38
|
+
puts("")
|
39
|
+
puts(genericOptionDescription())
|
40
|
+
puts(" -p, --port PORT The port number to start the server on. Defaults to #{DEFAULT_PORT}")
|
41
|
+
puts(" -c, --config FILE The configuration file")
|
42
|
+
end
|
43
|
+
|
44
|
+
def checkAppOptions()
|
45
|
+
if (@options[:config]==nil)
|
46
|
+
usageError("No config file specified. Use --config option.")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def parseAppOptions(opts)
|
51
|
+
opts.on('-p','--port PORT','The port number to start the server on. Defaults to 7000') do |port|
|
52
|
+
@options[:port] = port;
|
53
|
+
end
|
54
|
+
opts.on('-c','--config FILE','The configuration file') do |value|
|
55
|
+
@options[:config] = value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def createController
|
60
|
+
return ItunesController::SQLLiteControllerCreator.new
|
61
|
+
end
|
62
|
+
|
63
|
+
def execApp(controllerCreator)
|
64
|
+
port=DEFAULT_PORT
|
65
|
+
config=ItunesController::ServerConfig.readConfig(@options[:config])
|
66
|
+
if (config.port!=nil)
|
67
|
+
port = config.port
|
68
|
+
end
|
69
|
+
if (@options[:port]!=nil)
|
70
|
+
port = @options[:port]
|
71
|
+
end
|
72
|
+
server=ItunesController::ITunesControlServer.new(config,port,controllerCreator)
|
73
|
+
server.join
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
app=App.new("itunesController.rb")
|
78
|
+
app.exec()
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/ruby -I../lib
|
2
|
+
#
|
3
|
+
# A command line util used to list tracks in the iTunes library when their files can't be found.
|
4
|
+
#
|
5
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
6
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
7
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'itunesController/cachedcontroller'
|
11
|
+
require 'itunesController/debug'
|
12
|
+
require 'itunesController/logging'
|
13
|
+
require 'itunesController/application'
|
14
|
+
require 'itunesController/sqlite_creator'
|
15
|
+
|
16
|
+
class App < ItunesController::Application
|
17
|
+
|
18
|
+
def createController
|
19
|
+
return ItunesController::SQLLiteControllerCreator.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def execApp(controllerCreator)
|
23
|
+
controller = controllerCreator.createController()
|
24
|
+
deadTracks=controller.findDeadTracks
|
25
|
+
count=0
|
26
|
+
deadTracks.each do | deadTrack |
|
27
|
+
result=[]
|
28
|
+
result.push("Name: "+deadTrack.title)
|
29
|
+
result.push("Database ID: "+deadTrack.databaseId.to_s)
|
30
|
+
if (deadTrack.location==nil)
|
31
|
+
result.push("Location: Unknown")
|
32
|
+
else
|
33
|
+
result.push("Location: "+deadTrack.location)
|
34
|
+
end
|
35
|
+
ItunesController::ItunesControllerLogging::info(result.join("\n"))
|
36
|
+
ItunesController::ItunesControllerLogging::info("")
|
37
|
+
count+=1
|
38
|
+
end
|
39
|
+
ItunesController::ItunesControllerLogging::info("Found #{count} dead tracks")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
app=App.new("listDeadTracks.rb")
|
44
|
+
app.exec()
|
45
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#!/usr/bin/ruby -I../lib
|
2
|
+
#
|
3
|
+
# Copyright (C) 2011-2012 John-Paul.Stanford <dev@stanwood.org.uk>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
19
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
20
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'itunesController/application'
|
24
|
+
require 'itunesController/logging'
|
25
|
+
require 'itunesController/sqlite_creator'
|
26
|
+
|
27
|
+
require 'rubygems'
|
28
|
+
require 'fileutils'
|
29
|
+
|
30
|
+
class App < ItunesController::Application
|
31
|
+
|
32
|
+
MEDIA_TYPES = [".m4v","mp3",".mp4"]
|
33
|
+
|
34
|
+
# Used to display the command line useage
|
35
|
+
def displayUsage()
|
36
|
+
puts("Usage: "+@appName+" [options] directories...")
|
37
|
+
puts("")
|
38
|
+
puts(genericOptionDescription())
|
39
|
+
end
|
40
|
+
|
41
|
+
def checkAppOptions()
|
42
|
+
if ARGV.length == 0
|
43
|
+
usageError("No directories given.")
|
44
|
+
end
|
45
|
+
ARGV.each do | path |
|
46
|
+
errors = false
|
47
|
+
if (!File.exists?(path) || !File.directory?(path))
|
48
|
+
ItunesController::ItunesControllerLogging::error("#{path} is not a directory or cannot be found")
|
49
|
+
errors = true
|
50
|
+
end
|
51
|
+
if (errors)
|
52
|
+
exit(1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def processMediaFiles ( controller,dir )
|
58
|
+
(Dir.entries(dir)- %w[ . .. ]).each { |name|
|
59
|
+
file=dir+"/"+name
|
60
|
+
if (!File.directory?(file))
|
61
|
+
ext=File.extname(file)
|
62
|
+
name=File.basename(file)
|
63
|
+
if (MEDIA_TYPES.index(ext)!=nil)
|
64
|
+
if (!controller.trackInLibrary?(file))
|
65
|
+
ItunesController::ItunesControllerLogging::info("#{file}")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
else
|
69
|
+
processMediaFiles(controller,file)
|
70
|
+
end
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def createController
|
75
|
+
return ItunesController::SQLLiteControllerCreator.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def execApp(controllerCreator)
|
79
|
+
controller = controllerCreator.createController()
|
80
|
+
ARGV.each do | path |
|
81
|
+
ItunesController::ItunesControllerLogging::info("Checking for new files in '#{path}'")
|
82
|
+
processMediaFiles(controller,path)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
app=App.new("listNewTracks.rb")
|
88
|
+
app.exec()
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/ruby -I../lib
|
2
|
+
#
|
3
|
+
# A command line util used to remove tracks to the iTunes library
|
4
|
+
#
|
5
|
+
# Author:: John-Paul Stanford <dev@stanwood.org.uk>
|
6
|
+
# Copyright:: Copyright (C) 2011 John-Paul.Stanford <dev@stanwood.org.uk>
|
7
|
+
# License:: GNU General Public License v3 <http://www.gnu.org/licenses/>
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'itunesController/cachedcontroller'
|
11
|
+
require 'itunesController/sqlite_creator'
|
12
|
+
require 'itunesController/debug'
|
13
|
+
require 'itunesController/logging'
|
14
|
+
require 'itunesController/application'
|
15
|
+
|
16
|
+
class App < ItunesController::Application
|
17
|
+
|
18
|
+
def createController
|
19
|
+
return ItunesController::SQLLiteControllerCreator.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def execApp(controllerCreator)
|
23
|
+
controller = controllerCreator.createController()
|
24
|
+
if (!controller.getCachedTracksOnCreate())
|
25
|
+
controller.cacheTracks(true)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
app=App.new("regenerateTrackCache.rb")
|
31
|
+
app.exec()
|