one-k-rmov 0.1.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.
- data/CHANGELOG +38 -0
- data/LICENSE +20 -0
- data/Manifest +24 -0
- data/README.rdoc +73 -0
- data/Rakefile +16 -0
- data/TODO +15 -0
- data/ext/exporter.c +195 -0
- data/ext/extconf.rb +4 -0
- data/ext/movie.c +457 -0
- data/ext/rmov_ext.c +16 -0
- data/ext/rmov_ext.h +45 -0
- data/ext/track.c +391 -0
- data/lib/quicktime/exporter.rb +10 -0
- data/lib/quicktime/movie.rb +102 -0
- data/lib/quicktime/track.rb +31 -0
- data/lib/rmov.rb +12 -0
- data/rmov.gemspec +32 -0
- data/spec/fixtures/settings.st +0 -0
- data/spec/quicktime/exporter_spec.rb +29 -0
- data/spec/quicktime/movie_spec.rb +189 -0
- data/spec/quicktime/track_spec.rb +86 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +7 -0
- data/tasks/setup.rake +7 -0
- data/tasks/spec.rake +9 -0
- metadata +98 -0
data/ext/track.c
ADDED
@@ -0,0 +1,391 @@
|
|
1
|
+
#include "rmov_ext.h"
|
2
|
+
|
3
|
+
VALUE cTrack;
|
4
|
+
|
5
|
+
static void track_free(struct RTrack *rTrack)
|
6
|
+
{
|
7
|
+
}
|
8
|
+
|
9
|
+
static void track_mark(struct RTrack *rTrack)
|
10
|
+
{
|
11
|
+
}
|
12
|
+
|
13
|
+
/*
|
14
|
+
call-seq: new() -> track
|
15
|
+
|
16
|
+
Creates a new track instance. Generally you will do this through
|
17
|
+
movie.tracks to fetch the Track instances for a given movie.
|
18
|
+
*/
|
19
|
+
static VALUE track_new(VALUE klass)
|
20
|
+
{
|
21
|
+
struct RTrack *rTrack;
|
22
|
+
return Data_Make_Struct(klass, struct RTrack, track_mark, track_free, rTrack);
|
23
|
+
}
|
24
|
+
|
25
|
+
/*
|
26
|
+
call-seq: load(movie, index)
|
27
|
+
|
28
|
+
Loads a QuickTime track from a given movie. This is done automatically
|
29
|
+
when calling movie.tracks.
|
30
|
+
*/
|
31
|
+
static VALUE track_load(VALUE obj, VALUE movie_obj, VALUE index_obj)
|
32
|
+
{
|
33
|
+
RTRACK(obj)->track = GetMovieIndTrack(MOVIE(movie_obj), NUM2INT(index_obj));
|
34
|
+
if (!RTRACK(obj)->track)
|
35
|
+
rb_raise(eQuickTime, "Unable to fetch track for movie at index %d", NUM2INT(index_obj));
|
36
|
+
|
37
|
+
return obj;
|
38
|
+
}
|
39
|
+
|
40
|
+
/*
|
41
|
+
call-seq: raw_duration() -> duration_int
|
42
|
+
|
43
|
+
Returns the raw duration of the track. Combine this with time_scale to
|
44
|
+
reach the duration in seconds.
|
45
|
+
*/
|
46
|
+
static VALUE track_raw_duration(VALUE obj)
|
47
|
+
{
|
48
|
+
return INT2NUM(GetMediaDuration(TRACK_MEDIA(obj)));
|
49
|
+
}
|
50
|
+
|
51
|
+
/*
|
52
|
+
call-seq: time_scale() -> scale_int
|
53
|
+
|
54
|
+
Returns the time scale of the track. Usually only needed when working
|
55
|
+
with raw_duration.
|
56
|
+
*/
|
57
|
+
static VALUE track_time_scale(VALUE obj)
|
58
|
+
{
|
59
|
+
return INT2NUM(GetMediaTimeScale(TRACK_MEDIA(obj)));
|
60
|
+
}
|
61
|
+
|
62
|
+
/*
|
63
|
+
call-seq: frame_count() -> count
|
64
|
+
|
65
|
+
Returns the number of frames in the track.
|
66
|
+
*/
|
67
|
+
static VALUE track_frame_count(VALUE obj)
|
68
|
+
{
|
69
|
+
return INT2NUM(GetMediaSampleCount(TRACK_MEDIA(obj)));
|
70
|
+
}
|
71
|
+
|
72
|
+
/*
|
73
|
+
call-seq: media_type() -> media_type_sym
|
74
|
+
|
75
|
+
Returns either :audio or :video depending on the type of track this is.
|
76
|
+
*/
|
77
|
+
static VALUE track_media_type(VALUE obj)
|
78
|
+
{
|
79
|
+
OSType media_type;
|
80
|
+
|
81
|
+
GetMediaHandlerDescription(TRACK_MEDIA(obj), &media_type, 0, 0);
|
82
|
+
if (media_type == SoundMediaType) {
|
83
|
+
return ID2SYM(rb_intern("audio"));
|
84
|
+
} else if (media_type == VideoMediaType) {
|
85
|
+
return ID2SYM(rb_intern("video"));
|
86
|
+
} else if (media_type == TextMediaType) {
|
87
|
+
return ID2SYM(rb_intern("text"));
|
88
|
+
} else {
|
89
|
+
return Qnil;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
/* returns the ImageDescriptionHandle for the track.
|
94
|
+
If it's not a video track, return NULL
|
95
|
+
*/
|
96
|
+
static ImageDescriptionHandle track_image_description(VALUE obj)
|
97
|
+
{
|
98
|
+
Media track_media = TRACK_MEDIA(obj);
|
99
|
+
OSType media_type;
|
100
|
+
OSErr osErr = noErr;
|
101
|
+
|
102
|
+
/* restrict reporting to video track */
|
103
|
+
GetMediaHandlerDescription(track_media, &media_type, 0, 0);
|
104
|
+
if (media_type != VideoMediaType)
|
105
|
+
return NULL;
|
106
|
+
|
107
|
+
SampleDescriptionHandle sample_description = NULL;
|
108
|
+
sample_description = (SampleDescriptionHandle)NewHandle(sizeof(SampleDescription));
|
109
|
+
if (LMGetMemErr() != noErr) {
|
110
|
+
rb_raise(eQuickTime, "Memory Error %d when determining image description", LMGetMemErr());
|
111
|
+
return NULL;
|
112
|
+
}
|
113
|
+
|
114
|
+
GetMediaSampleDescription(track_media, 1, sample_description);
|
115
|
+
osErr = GetMoviesError();
|
116
|
+
if (osErr != noErr) {
|
117
|
+
rb_raise(eQuickTime, "Movie Error %d when determining image description", osErr);
|
118
|
+
DisposeHandle((Handle)sample_description);
|
119
|
+
return NULL;
|
120
|
+
}
|
121
|
+
|
122
|
+
return (ImageDescriptionHandle)sample_description;
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
/*
|
127
|
+
call-seq: track_codec() -> codec_string
|
128
|
+
|
129
|
+
Returns the name of the codec. Only valid for video tracks. Others return nil.
|
130
|
+
*/
|
131
|
+
static VALUE track_codec(VALUE obj)
|
132
|
+
{
|
133
|
+
ImageDescriptionHandle image_description = track_image_description(obj);
|
134
|
+
|
135
|
+
if (image_description == NULL)
|
136
|
+
return Qnil;
|
137
|
+
|
138
|
+
UInt8 *codecStr = (*image_description)->name;
|
139
|
+
|
140
|
+
VALUE out_str = rb_str_new( (char*)codecStr+1, (UInt8)codecStr[0] );
|
141
|
+
|
142
|
+
DisposeHandle((Handle)image_description);
|
143
|
+
|
144
|
+
return out_str;
|
145
|
+
}
|
146
|
+
|
147
|
+
|
148
|
+
/*
|
149
|
+
call-seq: track_width() -> width_in_pixels
|
150
|
+
|
151
|
+
Returns the width of track data. Only valid for video tracks. Others return nil.
|
152
|
+
*/
|
153
|
+
static VALUE track_width(VALUE obj)
|
154
|
+
{
|
155
|
+
ImageDescriptionHandle image_description = track_image_description(obj);
|
156
|
+
|
157
|
+
if (image_description == NULL)
|
158
|
+
return Qnil;
|
159
|
+
|
160
|
+
short width = (*image_description)->width;
|
161
|
+
|
162
|
+
DisposeHandle((Handle)image_description);
|
163
|
+
|
164
|
+
return INT2NUM(width);
|
165
|
+
}
|
166
|
+
|
167
|
+
/*
|
168
|
+
call-seq: track_height() -> height_in_pixels
|
169
|
+
|
170
|
+
Returns the height of track data. Only valid for video tracks. Others return nil.
|
171
|
+
*/
|
172
|
+
static VALUE track_height(VALUE obj)
|
173
|
+
{
|
174
|
+
ImageDescriptionHandle image_description = track_image_description(obj);
|
175
|
+
|
176
|
+
if (image_description == NULL)
|
177
|
+
return Qnil;
|
178
|
+
|
179
|
+
short height = (*image_description)->height;
|
180
|
+
|
181
|
+
DisposeHandle((Handle)image_description);
|
182
|
+
|
183
|
+
return INT2NUM(height);
|
184
|
+
}
|
185
|
+
|
186
|
+
|
187
|
+
/*
|
188
|
+
call-seq: id() -> quicktime_track_id_int
|
189
|
+
|
190
|
+
Returns either id number QuickTime uses to reference this track.
|
191
|
+
Usually only used internally.
|
192
|
+
*/
|
193
|
+
static VALUE track_id(VALUE obj)
|
194
|
+
{
|
195
|
+
return INT2NUM(GetTrackID(TRACK(obj)));
|
196
|
+
}
|
197
|
+
|
198
|
+
/*
|
199
|
+
call-seq: delete()
|
200
|
+
|
201
|
+
Removes the track from its movie and deletes it from memory.
|
202
|
+
*/
|
203
|
+
static VALUE track_delete(VALUE obj)
|
204
|
+
{
|
205
|
+
DisposeMovieTrack(TRACK(obj));
|
206
|
+
return Qnil;
|
207
|
+
}
|
208
|
+
|
209
|
+
/*
|
210
|
+
call-seq: disable()
|
211
|
+
|
212
|
+
Disables the track. See enabled? to determine if it's disabled already.
|
213
|
+
*/
|
214
|
+
static VALUE track_disable(VALUE obj, VALUE boolean)
|
215
|
+
{
|
216
|
+
SetTrackEnabled(TRACK(obj), FALSE);
|
217
|
+
return obj;
|
218
|
+
}
|
219
|
+
|
220
|
+
/*
|
221
|
+
call-seq: enable()
|
222
|
+
|
223
|
+
Enables the track. See enabled? to determine if it's enabled already.
|
224
|
+
*/
|
225
|
+
static VALUE track_enable(VALUE obj, VALUE boolean)
|
226
|
+
{
|
227
|
+
SetTrackEnabled(TRACK(obj), TRUE);
|
228
|
+
return obj;
|
229
|
+
}
|
230
|
+
|
231
|
+
/*
|
232
|
+
call-seq: enabled?() -> bool
|
233
|
+
|
234
|
+
Returns true/false depending on if the track is enabled.
|
235
|
+
*/
|
236
|
+
static VALUE track_enabled(VALUE obj, VALUE boolean)
|
237
|
+
{
|
238
|
+
if (GetTrackEnabled(TRACK(obj)) == TRUE) {
|
239
|
+
return Qtrue;
|
240
|
+
} else {
|
241
|
+
return Qfalse;
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
/*
|
246
|
+
call-seq: volume() -> volume_float
|
247
|
+
|
248
|
+
Returns the volume of the audio from 0.0 to 1.0.
|
249
|
+
*/
|
250
|
+
static VALUE track_get_volume(VALUE obj)
|
251
|
+
{
|
252
|
+
return rb_float_new((double)GetTrackVolume(TRACK(obj))/0x0100);
|
253
|
+
}
|
254
|
+
|
255
|
+
/*
|
256
|
+
call-seq: volume=(volume_float)
|
257
|
+
|
258
|
+
Sets the volume to the given value (0.0 to 1.0)
|
259
|
+
*/
|
260
|
+
static VALUE track_set_volume(VALUE obj, VALUE volume_obj)
|
261
|
+
{
|
262
|
+
SetTrackVolume(TRACK(obj), (short)(0x0100*NUM2DBL(volume_obj)));
|
263
|
+
return Qnil;
|
264
|
+
}
|
265
|
+
|
266
|
+
|
267
|
+
/* returns the AudioStreamBasicDescription for the track.
|
268
|
+
If it's not an audio track, return NULL
|
269
|
+
*/
|
270
|
+
static SoundDescriptionHandle track_audio_description(VALUE obj)
|
271
|
+
{
|
272
|
+
Media track_media = TRACK_MEDIA(obj);
|
273
|
+
OSType media_type;
|
274
|
+
OSErr osErr = noErr;
|
275
|
+
|
276
|
+
/* restrict reporting to audio track */
|
277
|
+
GetMediaHandlerDescription(track_media, &media_type, 0, 0);
|
278
|
+
if (media_type != SoundMediaType)
|
279
|
+
return NULL;
|
280
|
+
|
281
|
+
SoundDescriptionHandle sample_description = NULL;
|
282
|
+
sample_description = (SoundDescriptionHandle)NewHandle(sizeof(SampleDescription));
|
283
|
+
if (LMGetMemErr() != noErr) {
|
284
|
+
rb_raise(eQuickTime, "Memory Error %d when determining audio description", LMGetMemErr());
|
285
|
+
return NULL;
|
286
|
+
}
|
287
|
+
|
288
|
+
GetMediaSampleDescription(track_media, 1, (SampleDescriptionHandle)sample_description);
|
289
|
+
osErr = GetMoviesError();
|
290
|
+
if (osErr != noErr) {
|
291
|
+
rb_raise(eQuickTime, "GetMediaSampleDescription Error %d when determining audio description", osErr);
|
292
|
+
DisposeHandle((Handle)sample_description);
|
293
|
+
return NULL;
|
294
|
+
}
|
295
|
+
|
296
|
+
return sample_description;
|
297
|
+
}
|
298
|
+
|
299
|
+
/*
|
300
|
+
call-seq: offset() -> seconds
|
301
|
+
|
302
|
+
Returns the offset of the track from the beginning of the movie (in seconds).
|
303
|
+
*/
|
304
|
+
static VALUE track_get_offset(VALUE obj)
|
305
|
+
{
|
306
|
+
return rb_float_new((double)GetTrackOffset(TRACK(obj))/GetMediaTimeScale(TRACK_MEDIA(obj)));
|
307
|
+
}
|
308
|
+
|
309
|
+
/*
|
310
|
+
call-seq: offset=(seconds)
|
311
|
+
|
312
|
+
Sets the offset of the track from the start of the movie (in seconds).
|
313
|
+
*/
|
314
|
+
static VALUE track_set_offset(VALUE obj, VALUE seconds)
|
315
|
+
{
|
316
|
+
SetTrackOffset(TRACK(obj), TRACK_TIME(obj, seconds));
|
317
|
+
return Qnil;
|
318
|
+
}
|
319
|
+
|
320
|
+
/*
|
321
|
+
call-seq: new_video_media
|
322
|
+
|
323
|
+
Creates a new video media for this track.
|
324
|
+
|
325
|
+
Generally this method is not called directly, instead you can make a
|
326
|
+
new video track using Movie#new_video_track.
|
327
|
+
*/
|
328
|
+
static VALUE track_new_video_media(VALUE obj)
|
329
|
+
{
|
330
|
+
NewTrackMedia(TRACK(obj), VideoMediaType, 600, 0, 0);
|
331
|
+
return obj;
|
332
|
+
}
|
333
|
+
|
334
|
+
/*
|
335
|
+
call-seq: new_audio_media
|
336
|
+
|
337
|
+
Creates a new audio media for this track.
|
338
|
+
|
339
|
+
Generally this method is not called directly, instead you can make a
|
340
|
+
new audio track using Movie#new_audio_track.
|
341
|
+
*/
|
342
|
+
static VALUE track_new_audio_media(VALUE obj)
|
343
|
+
{
|
344
|
+
NewTrackMedia(TRACK(obj), SoundMediaType, 44100, 0, 0);
|
345
|
+
return obj;
|
346
|
+
}
|
347
|
+
|
348
|
+
/*
|
349
|
+
call-seq: new_text_media
|
350
|
+
|
351
|
+
Creates a new text media for this track.
|
352
|
+
|
353
|
+
Generally this method is not called directly, instead you can make a
|
354
|
+
new text track using Movie#new_text_track.
|
355
|
+
*/
|
356
|
+
static VALUE track_new_text_media(VALUE obj)
|
357
|
+
{
|
358
|
+
NewTrackMedia(TRACK(obj), TextMediaType, 600, 0, 0);
|
359
|
+
return obj;
|
360
|
+
}
|
361
|
+
|
362
|
+
|
363
|
+
void Init_quicktime_track()
|
364
|
+
{
|
365
|
+
VALUE mQuickTime;
|
366
|
+
mQuickTime = rb_define_module("QuickTime");
|
367
|
+
cTrack = rb_define_class_under(mQuickTime, "Track", rb_cObject);
|
368
|
+
rb_define_alloc_func(cTrack, track_new);
|
369
|
+
rb_define_method(cTrack, "load_from_movie", track_load, 2);
|
370
|
+
rb_define_method(cTrack, "raw_duration", track_raw_duration, 0);
|
371
|
+
rb_define_method(cTrack, "time_scale", track_time_scale, 0);
|
372
|
+
rb_define_method(cTrack, "frame_count", track_frame_count, 0);
|
373
|
+
rb_define_method(cTrack, "media_type", track_media_type, 0);
|
374
|
+
|
375
|
+
rb_define_method(cTrack, "codec", track_codec, 0);
|
376
|
+
rb_define_method(cTrack, "width", track_width, 0);
|
377
|
+
rb_define_method(cTrack, "height", track_height, 0);
|
378
|
+
|
379
|
+
rb_define_method(cTrack, "id", track_id, 0);
|
380
|
+
rb_define_method(cTrack, "delete", track_delete, 0);
|
381
|
+
rb_define_method(cTrack, "enabled?", track_enabled, 0);
|
382
|
+
rb_define_method(cTrack, "enable", track_enable, 0);
|
383
|
+
rb_define_method(cTrack, "disable", track_disable, 0);
|
384
|
+
rb_define_method(cTrack, "volume", track_get_volume, 0);
|
385
|
+
rb_define_method(cTrack, "volume=", track_set_volume, 1);
|
386
|
+
rb_define_method(cTrack, "offset", track_get_offset, 0);
|
387
|
+
rb_define_method(cTrack, "offset=", track_set_offset, 1);
|
388
|
+
rb_define_method(cTrack, "new_video_media", track_new_video_media, 0);
|
389
|
+
rb_define_method(cTrack, "new_audio_media", track_new_audio_media, 0);
|
390
|
+
rb_define_method(cTrack, "new_text_media", track_new_text_media, 0);
|
391
|
+
}
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module QuickTime
|
2
|
+
# see ext/movie.c for additional methods
|
3
|
+
class Movie
|
4
|
+
# Opens a movie at filepath.
|
5
|
+
def self.open(filepath)
|
6
|
+
new.load_from_file(filepath)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns a new, empty movie.
|
10
|
+
def self.empty
|
11
|
+
new.load_empty
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the length of this movie in seconds
|
15
|
+
# using raw_duration and time_scale.
|
16
|
+
def duration
|
17
|
+
raw_duration.to_f/time_scale
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the bounding width of this movie in number of pixels.
|
21
|
+
def width
|
22
|
+
bounds[:right] - bounds[:left]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the bounding height of this movie in number of pixels.
|
26
|
+
def height
|
27
|
+
bounds[:bottom] - bounds[:top]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns an array of tracks in this movie.
|
31
|
+
def tracks
|
32
|
+
(1..track_count).map do |i|
|
33
|
+
Track.new.load_from_movie(self, i)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns an array of audio tracks in this movie.
|
38
|
+
def audio_tracks
|
39
|
+
tracks.select { |t| t.audio? }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns an array of video tracks in this movie.
|
43
|
+
def video_tracks
|
44
|
+
tracks.select { |t| t.video? }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns an array of text tracks in this movie.
|
48
|
+
def text_tracks
|
49
|
+
tracks.select { |t| t.text? }
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns an Exporter instance for this movie.
|
53
|
+
def exporter
|
54
|
+
Exporter.new(self)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Convenience method for exporting the movie. See Exporter::export.
|
58
|
+
def export(*args, &block)
|
59
|
+
exporter.export(*args, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Creates a new video track with given width/height on movie and returns it.
|
63
|
+
def new_video_track(width, height)
|
64
|
+
track = new_track(width, height)
|
65
|
+
track.new_video_media
|
66
|
+
track
|
67
|
+
end
|
68
|
+
|
69
|
+
# Creates a new audio track with given width/height on movie and returns it.
|
70
|
+
def new_audio_track(width, height)
|
71
|
+
track = new_track(width, height)
|
72
|
+
track.new_audio_media
|
73
|
+
track
|
74
|
+
end
|
75
|
+
|
76
|
+
# Creates a new text track with given width/height on movie and returns it.
|
77
|
+
def new_text_track(width, height)
|
78
|
+
track = new_track(width, height)
|
79
|
+
track.new_text_media
|
80
|
+
track
|
81
|
+
end
|
82
|
+
|
83
|
+
# Exports a frame of the movie at the given time (in seconds) to the given file.
|
84
|
+
# The image format is automatically determined from the file extension. If this
|
85
|
+
# cannot be determined from the extension then you can use export_image_type to
|
86
|
+
# specify the ostype manually.
|
87
|
+
def export_image(filepath, seconds)
|
88
|
+
# TODO support more file types
|
89
|
+
type = case File.extname(filepath).downcase
|
90
|
+
when '.pct', '.pict' then 'PICT'
|
91
|
+
when '.tif', '.tiff' then 'TIFF'
|
92
|
+
when '.jpg', '.jpeg' then 'JPEG'
|
93
|
+
when '.png' then 'PNGf'
|
94
|
+
when '.tga' then 'TPIC'
|
95
|
+
when '.bmp' then 'BMPf'
|
96
|
+
when '.psd' then '8BPS'
|
97
|
+
else raise QuickTime::Error, "Unable to guess ostype from file extension of #{filepath}"
|
98
|
+
end
|
99
|
+
export_image_type(filepath, seconds, type)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module QuickTime
|
2
|
+
# see ext/track.c for additional methods
|
3
|
+
class Track
|
4
|
+
# Returns the length of this track in seconds
|
5
|
+
# using raw_duration and time_scale.
|
6
|
+
def duration
|
7
|
+
raw_duration.to_f/time_scale
|
8
|
+
end
|
9
|
+
|
10
|
+
# The average frame_rate for this track. May not be exact.
|
11
|
+
def frame_rate # what about odd frame rates such as 29.97?
|
12
|
+
frame_count/duration
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns true/false depending on if track is an audio track.
|
16
|
+
def audio?
|
17
|
+
media_type == :audio
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns true/false depending on if track is a video track.
|
21
|
+
def video?
|
22
|
+
media_type == :video
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns true/false depending on if track is a text track.
|
26
|
+
def text?
|
27
|
+
media_type == :text
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/lib/rmov.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../ext/rmov_ext'
|
4
|
+
|
5
|
+
require 'quicktime/movie'
|
6
|
+
require 'quicktime/track'
|
7
|
+
require 'quicktime/exporter'
|
8
|
+
|
9
|
+
|
10
|
+
# RMov is made up of several parts. To start, see QuickTime::Movie.
|
11
|
+
module QuickTime
|
12
|
+
end
|
data/rmov.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{rmov}
|
5
|
+
s.version = "0.1.4"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Ryan Bates"]
|
9
|
+
s.date = %q{2009-02-24}
|
10
|
+
s.description = %q{Ruby wrapper for the QuickTime C API.}
|
11
|
+
s.email = %q{ryan (at) railscasts (dot) com}
|
12
|
+
s.extensions = ["ext/extconf.rb"]
|
13
|
+
s.extra_rdoc_files = ["CHANGELOG", "ext/exporter.c", "ext/extconf.rb", "ext/movie.c", "ext/rmov_ext.c", "ext/rmov_ext.h", "ext/track.c", "lib/quicktime/exporter.rb", "lib/quicktime/movie.rb", "lib/quicktime/track.rb", "lib/rmov.rb", "LICENSE", "README.rdoc", "tasks/setup.rake", "tasks/spec.rake", "TODO"]
|
14
|
+
s.files = ["CHANGELOG", "ext/exporter.c", "ext/extconf.rb", "ext/movie.c", "ext/rmov_ext.c", "ext/rmov_ext.h", "ext/track.c", "lib/quicktime/exporter.rb", "lib/quicktime/movie.rb", "lib/quicktime/track.rb", "lib/rmov.rb", "LICENSE", "Manifest", "Rakefile", "README.rdoc", "spec/fixtures/settings.st", "spec/quicktime/exporter_spec.rb", "spec/quicktime/movie_spec.rb", "spec/quicktime/track_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/setup.rake", "tasks/spec.rake", "TODO", "rmov.gemspec"]
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.homepage = %q{http://github.com/ryanb/rmov}
|
17
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rmov", "--main", "README.rdoc"]
|
18
|
+
s.require_paths = ["lib", "ext"]
|
19
|
+
s.rubyforge_project = %q{rmov}
|
20
|
+
s.rubygems_version = %q{1.3.1}
|
21
|
+
s.summary = %q{Ruby wrapper for the QuickTime C API.}
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
Binary file
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe QuickTime::Exporter do
|
4
|
+
it "should raise error when saving with no settings" do
|
5
|
+
lambda { QuickTime::Exporter.new(nil).save_settings('foo') }.should raise_error(QuickTime::Error)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should raise error when atempting to load no file" do
|
9
|
+
lambda { QuickTime::Exporter.new(nil).load_settings('foo/bar/baz') }.should raise_error(QuickTime::Error)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "loaded settings.st" do
|
13
|
+
before(:each) do
|
14
|
+
@load_path = File.dirname(__FILE__) + '/../fixtures/settings.st'
|
15
|
+
@exporter = QuickTime::Exporter.new(nil)
|
16
|
+
@exporter.load_settings(@load_path)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be able to save settings to file" do
|
20
|
+
save_path = File.dirname(__FILE__) + '/../output/saved_settings.st'
|
21
|
+
@exporter.save_settings(save_path)
|
22
|
+
File.size(save_path).should == File.size(@load_path)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should complain when attempting to save to an invalid file" do
|
26
|
+
lambda { @exporter.save_settings('foo/bar/baz') }.should raise_error(QuickTime::Error)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|