rb-scpt 1.0.1 → 1.0.2

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rb-scpt-1.0.1.gem +0 -0
  3. data/extconf.rb +12 -12
  4. data/rb-scpt.gemspec +10 -10
  5. data/sample/AB_export_vcard.rb +16 -16
  6. data/sample/AB_list_people_with_emails.rb +4 -4
  7. data/sample/Add_iCal_event.rb +12 -12
  8. data/sample/Create_daily_iCal_todos.rb +28 -28
  9. data/sample/Export_Address_Book_phone_numbers.rb +52 -52
  10. data/sample/Hello_world.rb +10 -10
  11. data/sample/List_iTunes_playlist_names.rb +3 -3
  12. data/sample/Make_Mail_message.rb +24 -24
  13. data/sample/Open_file_in_TextEdit.rb +5 -5
  14. data/sample/Organize_Mail_messages.rb +46 -46
  15. data/sample/Print_folder_tree.rb +5 -5
  16. data/sample/Select_all_HTML_files.rb +6 -6
  17. data/sample/Set_iChat_status.rb +12 -12
  18. data/sample/Simple_Finder_GUI_Scripting.rb +6 -6
  19. data/sample/Stagger_Finder_windows.rb +9 -9
  20. data/sample/TextEdit_demo.rb +71 -71
  21. data/sample/iTunes_top40_to_html.rb +28 -30
  22. data/src/SendThreadSafe.c +293 -293
  23. data/src/SendThreadSafe.h +108 -108
  24. data/src/lib/_aem/aemreference.rb +997 -998
  25. data/src/lib/_aem/codecs.rb +609 -610
  26. data/src/lib/_aem/connect.rb +197 -197
  27. data/src/lib/_aem/encodingsupport.rb +67 -67
  28. data/src/lib/_aem/findapp.rb +75 -75
  29. data/src/lib/_aem/mactypes.rb +241 -242
  30. data/src/lib/_aem/send.rb +268 -268
  31. data/src/lib/_aem/typewrappers.rb +52 -52
  32. data/src/lib/_appscript/defaultterminology.rb +266 -266
  33. data/src/lib/_appscript/referencerenderer.rb +230 -233
  34. data/src/lib/_appscript/reservedkeywords.rb +106 -106
  35. data/src/lib/_appscript/safeobject.rb +125 -125
  36. data/src/lib/_appscript/terminology.rb +448 -449
  37. data/src/lib/aem.rb +238 -238
  38. data/src/lib/kae.rb +1487 -1487
  39. data/src/lib/osax.rb +647 -647
  40. data/src/lib/rb-scpt.rb +1065 -1065
  41. data/src/rbae.c +595 -595
  42. data/test/test_aemreference.rb +104 -107
  43. data/test/test_appscriptcommands.rb +131 -134
  44. data/test/test_appscriptreference.rb +96 -99
  45. data/test/test_codecs.rb +166 -168
  46. data/test/test_findapp.rb +13 -16
  47. data/test/test_mactypes.rb +70 -72
  48. data/test/test_osax.rb +46 -48
  49. data/test/testall.sh +4 -4
  50. metadata +8 -7
@@ -5,201 +5,201 @@
5
5
  #
6
6
 
7
7
  module Connect
8
- # Creates Apple event descriptor records of typeProcessSerialNumber, typeKernelProcessID and typeApplicationURL, used to specify the target application in Send::Event constructor.
9
-
10
- require "ae"
11
- require "kae"
12
- require "_aem/codecs"
13
- require "_aem/send"
14
- require "_aem/encodingsupport"
15
-
16
- @@encoding_support = AEMEncodingSupport.encoding_support
17
-
18
- LSLaunchDefaults = 0x00000001
19
- LSLaunchAndPrint = 0x00000002
20
- LSLaunchReserved2 = 0x00000004
21
- LSLaunchReserved3 = 0x00000008
22
- LSLaunchReserved4 = 0x00000010
23
- LSLaunchReserved5 = 0x00000020
24
- LSLaunchAndDisplayErrors = 0x00000040
25
- LSLaunchInhibitBGOnly = 0x00000080
26
- LSLaunchDontAddToRecents = 0x00000100
27
- LSLaunchDontSwitch = 0x00000200
28
- LSLaunchNoParams = 0x00000800
29
- LSLaunchAsync = 0x00010000
30
- LSLaunchStartClassic = 0x00020000
31
- LSLaunchInClassic = 0x00040000
32
- LSLaunchNewInstance = 0x00080000
33
- LSLaunchAndHide = 0x00100000
34
- LSLaunchAndHideOthers = 0x00200000
35
- LSLaunchHasUntrustedContents = 0x00400000
36
-
37
- KNoProcess = 0
38
- KCurrentProcess = 2
39
-
40
- def Connect.make_address_desc(psn)
41
- return AE::AEDesc.new(KAE::TypeProcessSerialNumber, psn.pack('LL'))
42
- end
43
-
44
- NullAddress = make_address_desc([0,KNoProcess])
45
- LaunchEvent = Send::Event.new(Connect::NullAddress, 'ascrnoop').AEM_event
46
- RunEvent = Send::Event.new(Connect::NullAddress, 'aevtoapp').AEM_event
47
-
48
- #######
49
- # public
50
-
51
- class CantLaunchApplicationError < RuntimeError
52
-
53
- # Taken from <http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference>:
54
- LSErrors = {
55
- -10660 => "The application cannot be run because it is inside a Trash folder.",
56
- -10810 => "An unknown error has occurred.",
57
- -10811 => "The item to be registered is not an application.",
58
- -10813 => "Data of the desired type is not available (for example, there is no kind string).",
59
- -10814 => "No application in the Launch Services database matches the input criteria.",
60
- -10817 => "Data is structured improperly (for example, an item's information property list is malformed).",
61
- -10818 => "A launch of the application is already in progress.",
62
- -10822 => "There is a problem communicating with the server process that maintains the Launch Services database.",
63
- -10823 => "The filename extension to be hidden cannot be hidden.",
64
- -10825 => "The application to be launched cannot run on the current Mac OS version.",
65
- -10826 => "The user does not have permission to launch the application (on a managed network).",
66
- -10827 => "The executable file is missing or has an unusable format.",
67
- -10828 => "The Classic emulation environment was required but is not available.",
68
- -10829 => "The application to be launched cannot run simultaneously in two different user sessions.",
69
- }
70
-
71
- def initialize(error_number)
72
- @error_number = error_number
73
- super("#{ LSErrors.fetch(@error_number, 'OS error') } (#{ @error_number })")
74
- end
75
-
76
- def to_i
77
- return @error_number
78
- end
79
- end
80
-
81
- ##
82
-
83
- def Connect.launch_application(path, event)
84
- path = @@encoding_support.to_utf8_string(path)
85
- begin
86
- return AE.launch_application(path, event,
87
- LSLaunchNoParams | LSLaunchStartClassic | LSLaunchDontSwitch)
88
- rescue AE::MacOSError => err
89
- raise CantLaunchApplicationError, err.to_i
90
- end
91
- end
92
-
93
- def Connect.launch_app_with_launch_event(path)
94
- # Send a 'launch' event to an application. If application is not already running, it will be launched in background first.
95
- path = @@encoding_support.to_utf8_string(path)
96
- begin
97
- # If app is already running, calling AE.launch_application will send a 'reopen' event, so need to check for this first:
98
- psn = AE.psn_for_application_path(path)
99
- rescue AE::MacOSError => err
100
- if err.to_i == -600 # Application isn't running, so launch it and send it a 'launch' event
101
- sleep(1)
102
- launch_application(path, LaunchEvent)
103
- else
104
- raise
105
- end
106
- else # App is already running, so send it a 'launch' event
107
- Send::Event.new(make_address_desc(psn), 'ascrnoop').send(60, KAE::KAENoReply)
108
- end
109
- end
110
-
111
- ##
112
-
113
- def Connect.process_exists_for_path?(path)
114
- path = @@encoding_support.to_utf8_string(path)
115
- # Does a local process launched from the specified application file exist?
116
- # Note: if path is invalid, an AE::MacOSError is raised.
117
- begin
118
- AE.psn_for_application_path(path)
119
- return true
120
- rescue AE::MacOSError => err
121
- if err.to_i == -600
122
- return false
123
- else
124
- raise
125
- end
126
- end
127
- end
128
-
129
- def Connect.process_exists_for_pid?(pid)
130
- # Is there a local application process with the given unix process id?
131
- begin
132
- AE.psn_for_process_id(pid)
133
- return true
134
- rescue AE::MacOSError => err
135
- if err.to_i == -600
136
- return false
137
- else
138
- raise
139
- end
140
- end
141
- end
142
-
143
- def Connect.process_exists_for_url?(url)
144
- # Does an application process specified by the given eppc:// URL exist?
145
- # Note: this will send a 'launch' Apple event to the target application.
146
- raise ArgumentError, "Invalid url: #{url}" if not url.include?(':') # workaround: process will crash if no colon in URL (OS bug)
147
- return process_exists_for_desc?(AE::AEDesc.new(KAE::TypeApplicationURL, url))
148
- end
149
-
150
- def Connect.process_exists_for_desc?(desc)
151
- # Does an application process specified by the given AEAddressDesc exist?
152
- # Returns false if process doesn't exist OR remote Apple events aren't allowed.
153
- # Note: this will send a 'launch' Apple event to the target application.
154
- begin
155
- # This will usually raise error -1708 if process is running, and various errors
156
- # if the process doesn't exist/can't be reached. If app is running but busy,
157
- # AESendMessage may return a timeout error (this should be -1712, but
158
- # -609 is often returned instead for some reason).
159
- Send::Event.new(desc, 'ascrnoop').send
160
- rescue Send::EventError => err
161
- return (not [-600, -905].include?(err.to_i)) # not running/no network access
162
- end
163
- return true
164
- end
165
-
166
- ##
167
-
168
- CurrentApp = make_address_desc([0, KCurrentProcess])
169
-
170
- def Connect.local_app(path)
171
- # Make an AEAddressDesc identifying a local application. (Application will be launched if not already running.)
172
- # path : string -- full path to application, e.g. '/Applications/TextEdit.app'
173
- # Result : AEAddressDesc
174
- #
175
- # Always creates AEAddressDesc by process serial number; that way there's no confusion if multiple versions of the same app are running.
176
- path = @@encoding_support.to_utf8_string(path)
177
- begin
178
- psn = AE.psn_for_application_path(path)
179
- rescue AE::MacOSError => err
180
- if err.to_i == -600 # Application isn't running, so launch it in background and send it a standard 'run' event.
181
- sleep(1)
182
- psn = launch_application(path, RunEvent)
183
- else
184
- raise
185
- end
186
- end
187
- return make_address_desc(psn)
188
- end
189
-
190
- def Connect.local_app_by_pid(pid)
191
- # Make an AEAddressDesc identifying a running application by Unix process id.
192
- # pid : integer -- unsigned 32-bit integer
193
- # Result : AEAddressDesc
194
- return AE::AEDesc.new(KAE::TypeKernelProcessID, [pid].pack('L'))
195
- end
196
-
197
- def Connect.remote_app(url)
198
- url = @@encoding_support.to_utf8_string(url)
199
- # Make an AEAddressDesc identifying a running application on another machine.
200
- # url : string -- URL for remote application, e.g. 'eppc://user:password@0.0.0.1/TextEdit'
201
- # Result : AEAddressDesc
202
- raise ArgumentError, "Invalid url: #{url}" if not url.include?(':') # workaround: process will crash if no colon in URL (OS bug)
203
- return AE::AEDesc.new(KAE::TypeApplicationURL, url)
204
- end
8
+ # Creates Apple event descriptor records of typeProcessSerialNumber, typeKernelProcessID and typeApplicationURL, used to specify the target application in Send::Event constructor.
9
+
10
+ require "ae"
11
+ require "kae"
12
+ require "_aem/codecs"
13
+ require "_aem/send"
14
+ require "_aem/encodingsupport"
15
+
16
+ @@encoding_support = AEMEncodingSupport.encoding_support
17
+
18
+ LSLaunchDefaults = 0x00000001
19
+ LSLaunchAndPrint = 0x00000002
20
+ LSLaunchReserved2 = 0x00000004
21
+ LSLaunchReserved3 = 0x00000008
22
+ LSLaunchReserved4 = 0x00000010
23
+ LSLaunchReserved5 = 0x00000020
24
+ LSLaunchAndDisplayErrors = 0x00000040
25
+ LSLaunchInhibitBGOnly = 0x00000080
26
+ LSLaunchDontAddToRecents = 0x00000100
27
+ LSLaunchDontSwitch = 0x00000200
28
+ LSLaunchNoParams = 0x00000800
29
+ LSLaunchAsync = 0x00010000
30
+ LSLaunchStartClassic = 0x00020000
31
+ LSLaunchInClassic = 0x00040000
32
+ LSLaunchNewInstance = 0x00080000
33
+ LSLaunchAndHide = 0x00100000
34
+ LSLaunchAndHideOthers = 0x00200000
35
+ LSLaunchHasUntrustedContents = 0x00400000
36
+
37
+ KNoProcess = 0
38
+ KCurrentProcess = 2
39
+
40
+ def Connect.make_address_desc(psn)
41
+ return AE::AEDesc.new(KAE::TypeProcessSerialNumber, psn.pack('LL'))
42
+ end
43
+
44
+ NullAddress = make_address_desc([0,KNoProcess])
45
+ LaunchEvent = Send::Event.new(Connect::NullAddress, 'ascrnoop').AEM_event
46
+ RunEvent = Send::Event.new(Connect::NullAddress, 'aevtoapp').AEM_event
47
+
48
+ #######
49
+ # public
50
+
51
+ class CantLaunchApplicationError < RuntimeError
52
+
53
+ # Taken from <http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference>:
54
+ LSErrors = {
55
+ -10660 => "The application cannot be run because it is inside a Trash folder.",
56
+ -10810 => "An unknown error has occurred.",
57
+ -10811 => "The item to be registered is not an application.",
58
+ -10813 => "Data of the desired type is not available (for example, there is no kind string).",
59
+ -10814 => "No application in the Launch Services database matches the input criteria.",
60
+ -10817 => "Data is structured improperly (for example, an item's information property list is malformed).",
61
+ -10818 => "A launch of the application is already in progress.",
62
+ -10822 => "There is a problem communicating with the server process that maintains the Launch Services database.",
63
+ -10823 => "The filename extension to be hidden cannot be hidden.",
64
+ -10825 => "The application to be launched cannot run on the current Mac OS version.",
65
+ -10826 => "The user does not have permission to launch the application (on a managed network).",
66
+ -10827 => "The executable file is missing or has an unusable format.",
67
+ -10828 => "The Classic emulation environment was required but is not available.",
68
+ -10829 => "The application to be launched cannot run simultaneously in two different user sessions.",
69
+ }
70
+
71
+ def initialize(error_number)
72
+ @error_number = error_number
73
+ super("#{ LSErrors.fetch(@error_number, 'OS error') } (#{ @error_number })")
74
+ end
75
+
76
+ def to_i
77
+ return @error_number
78
+ end
79
+ end
80
+
81
+ ##
82
+
83
+ def Connect.launch_application(path, event)
84
+ path = @@encoding_support.to_utf8_string(path)
85
+ begin
86
+ return AE.launch_application(path, event,
87
+ LSLaunchNoParams | LSLaunchStartClassic | LSLaunchDontSwitch)
88
+ rescue AE::MacOSError => err
89
+ raise CantLaunchApplicationError, err.to_i
90
+ end
91
+ end
92
+
93
+ def Connect.launch_app_with_launch_event(path)
94
+ # Send a 'launch' event to an application. If application is not already running, it will be launched in background first.
95
+ path = @@encoding_support.to_utf8_string(path)
96
+ begin
97
+ # If app is already running, calling AE.launch_application will send a 'reopen' event, so need to check for this first:
98
+ psn = AE.psn_for_application_path(path)
99
+ rescue AE::MacOSError => err
100
+ if err.to_i == -600 # Application isn't running, so launch it and send it a 'launch' event
101
+ sleep(1)
102
+ launch_application(path, LaunchEvent)
103
+ else
104
+ raise
105
+ end
106
+ else # App is already running, so send it a 'launch' event
107
+ Send::Event.new(make_address_desc(psn), 'ascrnoop').send(60, KAE::KAENoReply)
108
+ end
109
+ end
110
+
111
+ ##
112
+
113
+ def Connect.process_exists_for_path?(path)
114
+ path = @@encoding_support.to_utf8_string(path)
115
+ # Does a local process launched from the specified application file exist?
116
+ # Note: if path is invalid, an AE::MacOSError is raised.
117
+ begin
118
+ AE.psn_for_application_path(path)
119
+ return true
120
+ rescue AE::MacOSError => err
121
+ if err.to_i == -600
122
+ return false
123
+ else
124
+ raise
125
+ end
126
+ end
127
+ end
128
+
129
+ def Connect.process_exists_for_pid?(pid)
130
+ # Is there a local application process with the given unix process id?
131
+ begin
132
+ AE.psn_for_process_id(pid)
133
+ return true
134
+ rescue AE::MacOSError => err
135
+ if err.to_i == -600
136
+ return false
137
+ else
138
+ raise
139
+ end
140
+ end
141
+ end
142
+
143
+ def Connect.process_exists_for_url?(url)
144
+ # Does an application process specified by the given eppc:// URL exist?
145
+ # Note: this will send a 'launch' Apple event to the target application.
146
+ raise ArgumentError, "Invalid url: #{url}" if not url.include?(':') # workaround: process will crash if no colon in URL (OS bug)
147
+ return process_exists_for_desc?(AE::AEDesc.new(KAE::TypeApplicationURL, url))
148
+ end
149
+
150
+ def Connect.process_exists_for_desc?(desc)
151
+ # Does an application process specified by the given AEAddressDesc exist?
152
+ # Returns false if process doesn't exist OR remote Apple events aren't allowed.
153
+ # Note: this will send a 'launch' Apple event to the target application.
154
+ begin
155
+ # This will usually raise error -1708 if process is running, and various errors
156
+ # if the process doesn't exist/can't be reached. If app is running but busy,
157
+ # AESendMessage may return a timeout error (this should be -1712, but
158
+ # -609 is often returned instead for some reason).
159
+ Send::Event.new(desc, 'ascrnoop').send
160
+ rescue Send::EventError => err
161
+ return (not [-600, -905].include?(err.to_i)) # not running/no network access
162
+ end
163
+ return true
164
+ end
165
+
166
+ ##
167
+
168
+ CurrentApp = make_address_desc([0, KCurrentProcess])
169
+
170
+ def Connect.local_app(path)
171
+ # Make an AEAddressDesc identifying a local application. (Application will be launched if not already running.)
172
+ # path : string -- full path to application, e.g. '/Applications/TextEdit.app'
173
+ # Result : AEAddressDesc
174
+ #
175
+ # Always creates AEAddressDesc by process serial number; that way there's no confusion if multiple versions of the same app are running.
176
+ path = @@encoding_support.to_utf8_string(path)
177
+ begin
178
+ psn = AE.psn_for_application_path(path)
179
+ rescue AE::MacOSError => err
180
+ if err.to_i == -600 # Application isn't running, so launch it in background and send it a standard 'run' event.
181
+ sleep(1)
182
+ psn = launch_application(path, RunEvent)
183
+ else
184
+ raise
185
+ end
186
+ end
187
+ return make_address_desc(psn)
188
+ end
189
+
190
+ def Connect.local_app_by_pid(pid)
191
+ # Make an AEAddressDesc identifying a running application by Unix process id.
192
+ # pid : integer -- unsigned 32-bit integer
193
+ # Result : AEAddressDesc
194
+ return AE::AEDesc.new(KAE::TypeKernelProcessID, [pid].pack('L'))
195
+ end
196
+
197
+ def Connect.remote_app(url)
198
+ url = @@encoding_support.to_utf8_string(url)
199
+ # Make an AEAddressDesc identifying a running application on another machine.
200
+ # url : string -- URL for remote application, e.g. 'eppc://user:password@0.0.0.1/TextEdit'
201
+ # Result : AEAddressDesc
202
+ raise ArgumentError, "Invalid url: #{url}" if not url.include?(':') # workaround: process will crash if no colon in URL (OS bug)
203
+ return AE::AEDesc.new(KAE::TypeApplicationURL, url)
204
+ end
205
205
  end
@@ -7,71 +7,71 @@
7
7
 
8
8
  module AEMEncodingSupport
9
9
 
10
- module EnableStringEncodings
11
- # AE extension methods consume and return Strings containing UTF-8 encoded data, ignoring
12
- # any attached encoding information. This module provides wrappers for AE interactions that
13
- # take care of any encoding issues in Ruby 1.9+.
14
-
15
- def EnableStringEncodings.to_utf8_string(s)
16
- # Call before passing a string to an AE method that expects it to contain UTF-8 encoded data.
17
- return s if [Encoding::ASCII_8BIT, Encoding::UTF_8].include?(s.encoding)
18
- return s.encode('UTF-8')
19
- end
20
-
21
- def EnableStringEncodings.pack_string(s, as_type)
22
- begin
23
- return AE::AEDesc.new(KAE::TypeUTF8Text, EnableStringEncodings.to_utf8_string(s)).coerce(as_type)
24
- rescue AE::MacOSError => e
25
- if e.to_i == -1700 # couldn't coerce to TypeUnicodeText
26
- raise TypeError, "Not valid UTF8 data or couldn't coerce to type %{as_type}: #{s.inspect}"
27
- else
28
- raise
29
- end
30
- end
31
- end
32
-
33
- def EnableStringEncodings.unpack_string(desc)
34
- # String instances returned by AE methods contain UTF-8 data and ASCII-8BIT encoding,
35
- # so change the encoding to match the data
36
- return desc.coerce(KAE::TypeUTF8Text).data.force_encoding('UTF-8')
37
- end
38
- end
39
-
40
-
41
- module DisableStringEncodings
42
- # Support for Ruby 1.8 Strings, which do not contain encoding information. User is responsible
43
- # for ensuring String instances passed to AE APIs contain UTF-8 encoded data; String instances
44
- # returned by unpack_string will always contain contain UTF-8 encoded data.
45
-
46
- def DisableStringEncodings.to_utf8_string(s)
47
- return s
48
- end
49
-
50
- def DisableStringEncodings.pack_string(s, as_type)
51
- begin
52
- # Note: while the BOM is optional in typeUnicodeText, it's not included by AS
53
- # and some apps, e.g. iTunes 7, will handle it incorrectly, so it's omitted here.)
54
- return AE::AEDesc.new(KAE::TypeUTF8Text, s).coerce(as_type)
55
- rescue AE::MacOSError => e
56
- if e.to_i == -1700 # couldn't coerce to TypeUnicodeText
57
- raise TypeError, "Not valid UTF8 data or couldn't coerce to type %{as_type}: #{s.inspect}"
58
- else
59
- raise
60
- end
61
- end
62
- end
63
-
64
- def DisableStringEncodings.unpack_string(desc)
65
- return desc.coerce(KAE::TypeUTF8Text).data
66
- end
67
-
68
- end
69
-
70
-
71
- def AEMEncodingSupport.encoding_support
72
- # get the appropriate module for the Ruby version used
73
- version, sub_version = RUBY_VERSION.split('.').collect {|n| n.to_i} [0, 2]
74
- return (version >= 1 and sub_version >= 9) ? AEMEncodingSupport::EnableStringEncodings : AEMEncodingSupport::DisableStringEncodings
75
- end
10
+ module EnableStringEncodings
11
+ # AE extension methods consume and return Strings containing UTF-8 encoded data, ignoring
12
+ # any attached encoding information. This module provides wrappers for AE interactions that
13
+ # take care of any encoding issues in Ruby 1.9+.
76
14
 
77
- end
15
+ def EnableStringEncodings.to_utf8_string(s)
16
+ # Call before passing a string to an AE method that expects it to contain UTF-8 encoded data.
17
+ return s if [Encoding::ASCII_8BIT, Encoding::UTF_8].include?(s.encoding)
18
+ return s.encode('UTF-8')
19
+ end
20
+
21
+ def EnableStringEncodings.pack_string(s, as_type)
22
+ begin
23
+ return AE::AEDesc.new(KAE::TypeUTF8Text, EnableStringEncodings.to_utf8_string(s)).coerce(as_type)
24
+ rescue AE::MacOSError => e
25
+ if e.to_i == -1700 # couldn't coerce to TypeUnicodeText
26
+ raise TypeError, "Not valid UTF8 data or couldn't coerce to type %{as_type}: #{s.inspect}"
27
+ else
28
+ raise
29
+ end
30
+ end
31
+ end
32
+
33
+ def EnableStringEncodings.unpack_string(desc)
34
+ # String instances returned by AE methods contain UTF-8 data and ASCII-8BIT encoding,
35
+ # so change the encoding to match the data
36
+ return desc.coerce(KAE::TypeUTF8Text).data.force_encoding('UTF-8')
37
+ end
38
+ end
39
+
40
+
41
+ module DisableStringEncodings
42
+ # Support for Ruby 1.8 Strings, which do not contain encoding information. User is responsible
43
+ # for ensuring String instances passed to AE APIs contain UTF-8 encoded data; String instances
44
+ # returned by unpack_string will always contain contain UTF-8 encoded data.
45
+
46
+ def DisableStringEncodings.to_utf8_string(s)
47
+ return s
48
+ end
49
+
50
+ def DisableStringEncodings.pack_string(s, as_type)
51
+ begin
52
+ # Note: while the BOM is optional in typeUnicodeText, it's not included by AS
53
+ # and some apps, e.g. iTunes 7, will handle it incorrectly, so it's omitted here.)
54
+ return AE::AEDesc.new(KAE::TypeUTF8Text, s).coerce(as_type)
55
+ rescue AE::MacOSError => e
56
+ if e.to_i == -1700 # couldn't coerce to TypeUnicodeText
57
+ raise TypeError, "Not valid UTF8 data or couldn't coerce to type %{as_type}: #{s.inspect}"
58
+ else
59
+ raise
60
+ end
61
+ end
62
+ end
63
+
64
+ def DisableStringEncodings.unpack_string(desc)
65
+ return desc.coerce(KAE::TypeUTF8Text).data
66
+ end
67
+
68
+ end
69
+
70
+
71
+ def AEMEncodingSupport.encoding_support
72
+ # get the appropriate module for the Ruby version used
73
+ version, sub_version = RUBY_VERSION.split('.').collect {|n| n.to_i} [0, 2]
74
+ return (version >= 1 and sub_version >= 9) ? AEMEncodingSupport::EnableStringEncodings : AEMEncodingSupport::DisableStringEncodings
75
+ end
76
+
77
+ end