rubyosa19 0.5.0 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,18 +29,26 @@ require 'mkmf'
29
29
  $CFLAGS << ' -Wall '
30
30
  $LDFLAGS = '-framework Carbon -framework ApplicationServices'
31
31
 
32
+ if RUBY_VERSION =~ /^1.9/ then
33
+ $CPPFLAGS += " -DRUBY_19"
34
+ end
35
+
32
36
  exit 1 unless have_func('OSACopyScriptingDefinition')
33
37
  exit 1 unless have_func('LSFindApplicationForInfo')
34
38
 
35
39
  # Avoid `ID' and `T_DATA' symbol collisions between Ruby and Carbon.
36
40
  # (adapted code from RubyAEOSA - FUJIMOTO Hisakuni <hisa@fobj.com>)
37
- ruby_h = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby.h"
38
- intern_h = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby/intern.h"
41
+ if RUBY_VERSION =~ /^1.9/ then
42
+ ruby_h = "#{Config::CONFIG['rubyhdrdir']}/ruby.h"
43
+ intern_h = "#{Config::CONFIG['rubyhdrdir']}/ruby/intern.h"
44
+ else
45
+ ruby_h = "#{Config::CONFIG['archdir']}/ruby.h"
46
+ intern_h = "#{Config::CONFIG['archdir']}/intern.h"
47
+ end
39
48
  new_filename_prefix = 'osx_'
40
49
  [ ruby_h, intern_h ].each do |src_path|
41
- dst_fname = File.join('./', new_filename_prefix + File.basename(src_path))
50
+ dst_fname = File.join('./src', new_filename_prefix + File.basename(src_path))
42
51
  $stderr.puts "create #{File.expand_path(dst_fname)} ..."
43
- $stderr.puts "path: #{`pwd`}"
44
52
  File.open(dst_fname, 'w') do |dstfile|
45
53
  IO.foreach(src_path) do |line|
46
54
  line = line.gsub(/\bID\b/, 'RB_ID')
@@ -52,4 +60,9 @@ new_filename_prefix = 'osx_'
52
60
  end
53
61
 
54
62
  # Generate the Makefile
55
- create_makefile('rubyosa/osa')
63
+ create_makefile('osa', 'src')
64
+
65
+ # Tweak the Makefile to add an extra install task.
66
+ text = File.read('Makefile')
67
+ text << "\n\ninstall-extras: post-install.rb\n\t@$(RUBY) post-install.rb\n\n"
68
+ File.open('Makefile', 'w') { |io| io.write(text) }
@@ -0,0 +1,31 @@
1
+ # Print all the contacts your Address Book contains.
2
+ # Thanks to Stefan Saasen.
3
+
4
+ begin require 'rubygems'; rescue LoadError; end
5
+ require 'rbosa'
6
+
7
+ OSA.utf8_strings = true
8
+
9
+ def print_person(pe)
10
+ puts pe.name
11
+ unless pe.emails.size < 1
12
+ puts "\tE-Mail: " + pe.emails.map { |email|
13
+ email.value
14
+ }.join(', ')
15
+ end
16
+ formatted_addresses = pe.addresses.map { |a|
17
+ # Some malformed addresses can't be formatted and the address book
18
+ # will therefore return an application-level error, that we handle there.
19
+ ('(' + a.label + ') ' + a.formatted_address rescue nil)
20
+ }.compact.map { |a|
21
+ "\t\t" + a.gsub(/\n/, ' ').strip.squeeze(' ')
22
+ }
23
+ unless formatted_addresses.size < 1
24
+ puts "\tAddresses:\n" + formatted_addresses.join("\n")
25
+ end
26
+ end
27
+
28
+ ab = OSA.app('Address Book')
29
+ ab.people.each do |pe|
30
+ print_person pe
31
+ end
@@ -0,0 +1,19 @@
1
+ # Ask BBEdit to run the uptime(1) command and get the result.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ puts 'Asking for uptime...'
7
+
8
+ bbedit = OSA.app('BBEdit')
9
+
10
+ bbedit.make(OSA::BBEdit::TextDocument).text = <<EOS
11
+ #!/bin/sh
12
+ uptime
13
+ EOS
14
+
15
+ bbedit.run_unix_script
16
+
17
+ output_doc = bbedit.text_documents.find { |x| x.name == 'Unix Script Output' }
18
+
19
+ puts output_doc.text.get
@@ -0,0 +1,10 @@
1
+ # Lists the content of the Finder desktop.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ ary = OSA.app('Finder').desktop.entire_contents.get
7
+ ary.each do |x|
8
+ next unless x.is_a?(OSA::Finder::Item)
9
+ puts "#{x.class.name.sub(/^.+::/, '').sub(/_/, ' ').ljust(25)} #{x.name}"
10
+ end
@@ -0,0 +1,14 @@
1
+ # Retrieve and show every selected message content in Mail into new TextEdit documents.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ OSA.utf8_strings = true
7
+ textedit = OSA.app('TextEdit')
8
+ mailApp = OSA.app('Mail')
9
+ viewers = mailApp.message_viewers
10
+ viewers.each do |viewer|
11
+ viewer.selected_messages.each do |message|
12
+ textedit.make(OSA::TextEdit::Document).text = message.content
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ # Creates a new Photoshop document with a given title and size.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ app = OSA.app('Adobe Photoshop CS2')
7
+ app.settings.ruler_units = OSA::AdobePhotoshopCS2::E440::PIXEL_UNITS
8
+
9
+ app.make(OSA::AdobePhotoshopCS2::Document, nil, :with_properties => {
10
+ :name => 'Ruby Rocks',
11
+ :width => 500,
12
+ :height => 500
13
+ })
@@ -0,0 +1,34 @@
1
+ # Creates a new Photoshop document with a given title and size, and adds a text
2
+ # layer on it.
3
+
4
+ begin require 'rubygems'; rescue LoadError; end
5
+ require 'rbosa'
6
+
7
+ app = OSA.app('Adobe Photoshop CS2')
8
+ app.settings.ruler_units = OSA::AdobePhotoshopCS2::E440::PIXEL_UNITS
9
+ app.instance_eval do
10
+ def create_document(options = {})
11
+ make(OSA::AdobePhotoshopCS2::Document, nil, :with_properties => {
12
+ :name => 'Ruby Rocks',
13
+ :width => 500,
14
+ :height => 500
15
+ }.merge(options))
16
+ end
17
+
18
+ def add_layer(name, kind)
19
+ kinds = %w(NORMAL GRADIENTFILL PATTERNFILL TEXT SOLIDFILL)
20
+ do_javascript %(
21
+ var doc = app.activeDocument;
22
+ var layer = doc.artLayers.add();
23
+ layer.name = "#{name || ''}";
24
+ layer.kind = LayerKind.#{kinds.detect {|k| k.downcase == kind} || 'NORMAL'};
25
+ )
26
+ current_document.art_layers[0]
27
+ end
28
+ end
29
+
30
+ app.create_document(:name => 'Schweet')
31
+ layer = app.add_layer('A text layer', 'text')
32
+ texto = layer.text_object
33
+ texto.size = 40
34
+ texto.contents = "This is some text"
@@ -0,0 +1,30 @@
1
+ # Opens given movies and in QuickTime and starts playing them indefinitely in fullscreen mode.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ if ARGV.empty?
7
+ STDERR.puts "Usage: #{$0} <movies-files>"
8
+ exit 1
9
+ end
10
+
11
+ app = OSA.app('QuickTime Player')
12
+ ARGV.each { |p| app.open(p) }
13
+ l = app.movies.to_a
14
+ exit if l.length == 0
15
+ last = nil
16
+ loop do
17
+ l2 = []
18
+ l.length.times { l2 << l.slice!(rand(l.length)) }
19
+ l2[0], l2[1] = l2[1], l2[0] if l2[0] == last and l2.length > 1 # not to have the same file playing twice consecutively
20
+ l2.each do |m|
21
+ m.rewind # to be sure that we start at the beginning of the movie
22
+ m.present
23
+ sleep 0.1 while m.playing?
24
+ m.stop # to be sure we are not in presentation mode anymore
25
+ # if we do not end with a stop, and the movie has been stopped by the user,
26
+ # the next present will not play the movie because an other movie is still in presentation mode
27
+ last = m
28
+ end
29
+ l = l2
30
+ end
@@ -0,0 +1,19 @@
1
+ # Create new TextEdit documents with a 'Hello World' text.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ textedit = OSA.app('TextEdit')
7
+
8
+ # Complex way.
9
+ textedit.make(OSA::TextEdit::Document, :with_properties => {:text => 'Hello World #1'})
10
+
11
+ # Easier way.
12
+ textedit.make(OSA::TextEdit::Document).text = 'Hello World #2'
13
+
14
+ =begin
15
+ # Easiest way, not implemented for now.
16
+ document = OSA::TextEdit::Document.new
17
+ document.text = 'Hello World #3'
18
+ textedit << document
19
+ =end
@@ -0,0 +1,18 @@
1
+ # Periodically set your iChat image to one of the default images.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ ichat = OSA.app('iChat')
7
+
8
+ old_image = ichat.image
9
+ trap('INT') { ichat.image = old_image; exit 0 }
10
+
11
+ paths = Dir.glob("/Library/User Pictures/**/*.tif")
12
+
13
+ while true do
14
+ paths.each do |path|
15
+ ichat.image = File.read(path)
16
+ sleep 2
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # Periodically set your iChat status to the output of uptime(1).
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ app = OSA.app('iChat')
7
+ previous_status_message = app.status_message
8
+ trap('INT') { app.status_message = previous_status_message; exit 0 }
9
+ while true
10
+ u = `uptime`
11
+ hours = u.scan(/^\s*(\d+:\d+)\s/).to_s + ' hours'
12
+ days = u.scan(/\d+\sdays/).to_s
13
+ app.status_message = "OSX up #{days} #{hours}"
14
+ sleep 5
15
+ end
@@ -0,0 +1,14 @@
1
+ # Open the artwork of the current iTunes track in Preview.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ artworks = OSA.app('iTunes').current_track.artworks
7
+ if artworks.size == 0
8
+ puts "No artwork for current track."
9
+ exit 1
10
+ end
11
+
12
+ fname = '/tmp/foo.' + artworks[0].format.downcase.strip
13
+ File.open(fname, 'w') { |io| io.write(artworks[0].data) }
14
+ system("open -a Preview #{fname}")
@@ -0,0 +1,66 @@
1
+ # Simple iTunes controller.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+ require 'curses'
6
+ include Curses
7
+
8
+ app = OSA.app('iTunes')
9
+ OSA.utf8_strings = true
10
+
11
+ if app.current_track.nil?
12
+ # We don't support write access now, so...
13
+ puts "Please select a track in iTunes and retry again."
14
+ exit 1
15
+ end
16
+
17
+ init_screen
18
+
19
+ addstr <<EOS
20
+ Keys available:
21
+ SPACE toggle play/pause
22
+ p go to previous song
23
+ n go to next song
24
+ f toggle fast forward
25
+ r toggle rewind
26
+ m toggle mute
27
+ q exit the program
28
+
29
+ On track:
30
+ EOS
31
+
32
+ begin
33
+ noecho
34
+ while true
35
+ setpos(9, 2)
36
+ addstr "#{app.player_state.to_s.capitalize} : #{app.current_track.name}".ljust(cols - 3)
37
+ refresh
38
+ x = getch
39
+ case x.chr
40
+ when ' '
41
+ app.playpause
42
+ when 'p'
43
+ app.previous_track
44
+ when 'n'
45
+ app.next_track
46
+ when 'f'
47
+ if app.player_state == OSA::ITunes::EPLS::FAST_FORWARDING
48
+ app.resume
49
+ else
50
+ app.fast_forward
51
+ end
52
+ when 'r'
53
+ if app.player_state == OSA::ITunes::EPLS::REWINDING
54
+ app.resume
55
+ else
56
+ app.rewind
57
+ end
58
+ when 'm'
59
+ app.mute = !app.mute?
60
+ when 'q'
61
+ break
62
+ end
63
+ end
64
+ ensure
65
+ echo
66
+ end
@@ -0,0 +1,23 @@
1
+ # Start playing, then fade the volume from 0 to the original setting.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ app = OSA.app('iTunes')
7
+
8
+ original_volume = app.sound_volume
9
+
10
+ if original_volume == 0 or app.current_track.nil?
11
+ puts "Please select a track and/or set a higher volume."
12
+ exit 1
13
+ end
14
+
15
+ app.sound_volume = 0
16
+ app.play
17
+
18
+ 0.step(original_volume, original_volume / 8.0) do |volume|
19
+ app.sound_volume = volume
20
+ sleep(0.1)
21
+ end
22
+
23
+ app.sound_volume = original_volume
@@ -0,0 +1,16 @@
1
+ # Quick inspection of iTunes' sources, playlists and tracks.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ app = OSA.app('iTunes')
7
+ OSA.utf8_strings = true
8
+ app.sources.each do |source|
9
+ puts source.name
10
+ source.playlists.each do |playlist|
11
+ puts " -> #{playlist.name}"
12
+ playlist.tracks.each do |track|
13
+ puts " -> #{track.name}" if track.enabled?
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,97 @@
1
+ # Plays a track of your iTunes library at random and asks you to guess the name of the track.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+
6
+ OSA.app('iTunes') # initialize the constants
7
+
8
+ class OSA::ITunes::Application
9
+
10
+ def library_source
11
+ sources.find {|s| s.kind == OSA::ITunes::ESRC::LIBRARY }
12
+ end
13
+
14
+ def library
15
+ library_source.playlists.find {|p| p.name == 'Library' }
16
+ end
17
+
18
+ def party_shuffle
19
+ library_source.playlists.find {|p| p.special_kind == OSA::ITunes::ESPK::PARTY_SHUFFLE }
20
+ end
21
+
22
+ end
23
+
24
+ class OSA::ITunes::Playlist
25
+
26
+ def random_track
27
+ tracks[rand * tracks.size]
28
+ end
29
+
30
+ end
31
+
32
+ class OSA::ITunes::Track
33
+
34
+ def to_s
35
+ "#{artist} - #{name}"
36
+ end
37
+
38
+ end
39
+
40
+
41
+ class NameThatTune
42
+ attr_accessor :score
43
+
44
+ def initialize
45
+ @itunes = OSA.app('iTunes')
46
+ end
47
+
48
+ def finish
49
+ puts "Thanks for playing! Score: #{score}"
50
+ exit
51
+ end
52
+
53
+ def start
54
+ @score = 0
55
+ while true
56
+ @itunes.party_shuffle.play
57
+ @itunes.next_track
58
+
59
+ options = generate_options
60
+ options.each_with_index { |track, i| puts "#{i+1} - #{track}" }
61
+
62
+ selected = gets.to_i
63
+
64
+ finish if selected == 0
65
+
66
+ if correct?(options, selected)
67
+ points = calculate_points_for_correct_choice
68
+ puts "Correct! #{points} points"
69
+ self.score += points
70
+ else
71
+ puts "Sorry! That was #{@itunes.current_track}"
72
+ end
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def correct?(options, selected)
79
+ options[selected-1] == @itunes.current_track
80
+ end
81
+
82
+ def calculate_points_for_correct_choice
83
+ points = (@itunes.player_position > 10 ? 1 : 10 - @itunes.player_position) * 1000
84
+ points += (@itunes.current_track.played_count > 10 ? 1 : 10 - @itunes.current_track.played_count) * 100
85
+ points.to_i
86
+ end
87
+
88
+ def generate_options(count = 5)
89
+ options = []
90
+ options << @itunes.current_track
91
+ (count - 1).times {|i| options << @itunes.library.random_track }
92
+ options = options.sort_by { rand }
93
+ end
94
+
95
+ end
96
+
97
+ NameThatTune.new.start
@@ -0,0 +1,32 @@
1
+ # For each selected track in iTunes, retrieve the genre from Last.fm and accordingly tag the track.
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+ require 'net/http'
6
+ require 'cgi'
7
+ require 'rexml/document'
8
+ include REXML
9
+
10
+ itunes = OSA.app('iTunes')
11
+
12
+ selection = itunes.selection.get
13
+ if selection.empty?
14
+ $stderr.puts "Please select some tracks."
15
+ exit 1
16
+ end
17
+
18
+ first = selection.first.artist
19
+ feed = "http://ws.audioscrobbler.com/1.0/artist/#{CGI::escape(first)}/toptags.xml"
20
+ doc = Document.new(Net::HTTP.get(URI(feed)))
21
+
22
+ selection.each do |track|
23
+ if doc.root.attributes['artist'] == track.artist
24
+ genre = doc.root[1][1].text.capitalize
25
+ else
26
+ puts 'Querying Last.fm again...'
27
+ feed = "http://ws.audioscrobbler.com/1.0/artist/#{CGI::escape(track.artist)}/toptags.xml"
28
+ doc = Document.new(Net::HTTP.get(URI(feed)))
29
+ genre = doc.root[1][1].text.capitalize
30
+ end
31
+ track.genre = genre
32
+ end
@@ -0,0 +1,37 @@
1
+ # Print the given application's sdef(5).
2
+
3
+ begin require 'rubygems'; rescue LoadError; end
4
+ require 'rbosa'
5
+ require 'rexml/document'
6
+
7
+ def usage
8
+ STDERR.puts <<-EOS
9
+ Usage: #{$0} [--name | --path | --bundle_id | --signature] ...
10
+ Examples:
11
+ #{$0} --name iTunes
12
+ #{$0} --path /Applications/iTunes.app
13
+ #{$0} --bundle_id com.apple.iTunes
14
+ #{$0} --signature hook
15
+ EOS
16
+ exit 1
17
+ end
18
+
19
+ usage unless ARGV.length == 2
20
+
21
+ key = case ARGV.first
22
+ when '--name'
23
+ :name
24
+ when '--path'
25
+ :path
26
+ when '--bundle_id'
27
+ :bundle_id
28
+ when '--signature'
29
+ :signature
30
+ else
31
+ usage
32
+ end
33
+
34
+ app = OSA.app(key => ARGV.last)
35
+ doc = REXML::Document.new(app.sdef)
36
+ doc.write(STDOUT, 0)
37
+ puts ""
@@ -24,53 +24,23 @@
24
24
  # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
25
  # POSSIBILITY OF SUCH DAMAGE.
26
26
 
27
+ unless RUBY_VERSION =~ /^1.9/ then
28
+ $KCODE = 'u' # we will use UTF-8 strings
29
+ end
30
+
31
+ require 'osa'
27
32
  require 'date'
28
33
  require 'uri'
29
- # require 'iconv'
30
-
31
- # Try to load RubyGems first, libxml-ruby may have been installed by it.
32
- begin require 'rubygems'; rescue LoadError; end
33
-
34
- # If libxml-ruby is not present, switch to REXML.
35
- USE_LIBXML = begin
36
- require 'xml/libxml'
37
-
38
- # libxml-ruby bug workaround.
39
- class XML::Node
40
- alias_method :old_cmp, :==
41
- def ==(x)
42
- (x != nil and old_cmp(x))
43
- end
44
- end
45
- true
46
- rescue LoadError
47
- require 'rexml/document'
48
-
49
- # REXML -> libxml-ruby compatibility layer.
50
- class REXML::Element
51
- alias_method :old_find, :find
52
- def find(path=nil, &block)
53
- if path.nil? and block
54
- old_find { |*x| block.call(*x) }
55
- else
56
- list = []
57
- ::REXML::XPath.each(self, path) { |e| list << e }
58
- list
59
- end
60
- end
61
- def [](attr)
62
- attributes[attr]
63
- end
64
- def find_first(path)
65
- ::REXML::XPath.first(self, path)
66
- end
67
- end
68
- false
69
- end
34
+ require 'iconv'
35
+ require 'xml'
70
36
 
71
37
  class String
72
38
  def to_4cc
73
- OSA.__four_char_code__(self.encode('MACROMAN').to_s)
39
+ if RUBY_VERSION =~ /^1.9/ then
40
+ OSA.__four_char_code__(Iconv.iconv('MACROMAN', 'UTF-8', self)[0].to_s)
41
+ else
42
+ OSA.__four_char_code__(Iconv.iconv('MACROMAN', 'UTF-8', self).to_s)
43
+ end
74
44
  end
75
45
  end
76
46
 
@@ -463,12 +433,7 @@ module OSA
463
433
 
464
434
  def self.__load_sdef__(sdef, target, app_module, merge_only=false, app_class=nil)
465
435
  # Load the sdef.
466
- doc = if USE_LIBXML
467
- parser = XML::Parser.string(sdef)
468
- parser.parse
469
- else
470
- REXML::Document.new(sdef)
471
- end
436
+ doc = XML::Parser.string(sdef).parse
472
437
 
473
438
  # Retrieves and creates enumerations.
474
439
  enum_group_codes = {}
@@ -652,13 +617,13 @@ module OSA
652
617
  has_result = result != nil
653
618
 
654
619
  code = element['code']
655
- # begin
656
- code = code.encode('MACROMAN').to_s
657
- # rescue Iconv::IllegalSequence
658
- # # We can't do more...
659
- # STDERR.puts "unrecognized command code encoding '#{code}', skipping..." if $DEBUG
660
- # next
661
- # end
620
+ begin
621
+ code = Iconv.iconv('MACROMAN', 'UTF-8', code).to_s
622
+ rescue Iconv::IllegalSequence
623
+ # We can't do more...
624
+ STDERR.puts "unrecognized command code encoding '#{code}', skipping..." if $DEBUG
625
+ next
626
+ end
662
627
 
663
628
  classes_to_define = []
664
629
  forget_direct_parameter = true
@@ -1038,3 +1003,5 @@ OSA.add_conversion_to_osa('color') do |values|
1038
1003
  ary = values.map { |i| OSA::Element.__new__('long', [i].pack('l')) }
1039
1004
  OSA::ElementList.__new__(ary)
1040
1005
  end
1006
+
1007
+ require 'rbosa_properties'
File without changes