rubyosa19 0.5.0 → 0.5.4

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.
@@ -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