one-k-rmov 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|