rmov 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,9 +1,25 @@
1
+ 0.1.5 (July 28, 2009)
2
+
3
+ * fixing saving export settings - closes #8
4
+
5
+ * improving how movie selection process happens providing more flexibility - closes #4 and #5
6
+
7
+ * adding enable_alpha method to enable alpha transparency for compositing - closes #3
8
+
9
+ * adding track transformations (rotation, scaling, and translation) - closes #1 and #2
10
+
11
+ * adding movie.save method to save a movie in place
12
+
13
+ * supporting .pict extension when exporting frame
14
+
15
+
1
16
  0.1.4 (October 3rd, 2008)
2
17
 
3
18
  * adding support for several export_image formats (PNG, JPEG, TIFF, TGA, BMP, PSD)
4
19
 
5
20
  * adding movie.export_image as a generic way to export a frame to multiple formats
6
21
 
22
+
7
23
  0.1.3 (October 3rd, 2008)
8
24
 
9
25
  * some support for text tracks
@@ -12,6 +28,7 @@
12
28
 
13
29
  * changing Quicktime module name to QuickTime to match proper casing
14
30
 
31
+
15
32
  0.1.2 (October 3rd, 2008)
16
33
 
17
34
  * movie.poster_time and movie.poster_time=(seconds) for getting and setting a movie's poster time
@@ -22,12 +39,14 @@
22
39
 
23
40
  * QuickTime settings dialog comes into the forground properly
24
41
 
42
+
25
43
  0.1.1 (October 3rd, 2008)
26
44
 
27
45
  * RubyGems 1.3 compatibility (updated Echoe)
28
46
 
29
47
  * fixing inline RDocs so call sequence is handled properly
30
48
 
49
+
31
50
  0.1.0 (October 2nd, 2008)
32
51
 
33
52
  * initial release
data/Manifest CHANGED
@@ -13,6 +13,7 @@ LICENSE
13
13
  Manifest
14
14
  Rakefile
15
15
  README.rdoc
16
+ spec/fixtures/dot.png
16
17
  spec/fixtures/settings.st
17
18
  spec/quicktime/exporter_spec.rb
18
19
  spec/quicktime/movie_spec.rb
@@ -17,7 +17,9 @@ And then load it in your project:
17
17
 
18
18
  == Usage
19
19
 
20
- Use this gem to open QuickTime movies and edit them to your liking.
20
+ There are many methods for editing, compositing, and exporting movies. Here are some examples.
21
+
22
+ === Editing
21
23
 
22
24
  movie1 = QuickTime::Movie.open("path/to/movie.mov")
23
25
  movie2 = QuickTime::Movie.open("path/to/another_movie.mov")
@@ -32,12 +34,33 @@ Use this gem to open QuickTime movies and edit them to your liking.
32
34
  # You can insert that part back into the movie at 8 seconds in
33
35
  movie1.insert_movie(movie3, 8)
34
36
 
35
- Now you can export the movie. Usually this is done through a user
36
- interface the first time around. The settings can then be saved to
37
- a file. After that you can load these settings without interfering
38
- the user with the dialog again.
37
+ === Compositing
39
38
 
40
- exporter = movie1.exporter
39
+ movie = QuickTime::Movie.open("path/to/movie.mov")
40
+ watermark_movie = QuickTime::Movie.open("path/to/watermark.png")
41
+
42
+ # add watermark track onto the entire length of the movie
43
+ movie.composite_movie(watermark_movie, 0, movie.duration)
44
+
45
+ # grab the watermark track
46
+ watermark = movie.video_tracks.last
47
+
48
+ # enable the alpha transparency of the png
49
+ watermark.enable_alpha
50
+
51
+ # make the watermark half the size
52
+ watermark.scale(0.5, 0.5)
53
+
54
+ # offset into lower left corner
55
+ watermark.translate(10, movie.height - watermark.height - 10)
56
+
57
+ === Exporting
58
+
59
+ Usually exporting is done through a user interface the first time.
60
+ The settings can then be saved to a file. After that you can load
61
+ these settings without interfering the user with the dialog again.
62
+
63
+ exporter = movie.exporter
41
64
 
42
65
  # if we already have saved the settings, load those
43
66
  if File.exist? "settings.st"
@@ -56,7 +79,10 @@ the user with the dialog again.
56
79
  puts "#{percent}% complete"
57
80
  end
58
81
 
59
- See QuickTime::Movie in the RDoc for more information.
82
+
83
+ == Documentation
84
+
85
+ See QuickTime::Movie and QuickTime::Track in the RDoc for more information.
60
86
 
61
87
  http://rmov.rubyforge.org
62
88
 
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('rmov', '0.1.4') do |p|
5
+ Echoe.new('rmov', '0.1.5') do |p|
6
6
  p.summary = "Ruby wrapper for the QuickTime C API."
7
7
  p.description = "Ruby wrapper for the QuickTime C API."
8
8
  p.url = "http://github.com/ryanb/rmov"
@@ -93,7 +93,7 @@ static VALUE exporter_open_settings_dialog(VALUE obj)
93
93
  // Bring this process to the front
94
94
  err = TransformProcessType(&current_process, kProcessTransformToForegroundApplication);
95
95
  if (err != noErr) {
96
- rb_raise(eQuickTime, "Error %d occurred while brining this application to the forground.", err);
96
+ rb_raise(eQuickTime, "Error %d occurred while bringing this application to the forground.", err);
97
97
  }
98
98
  SetFrontProcess(&current_process);
99
99
 
@@ -176,7 +176,7 @@ static VALUE exporter_save_settings(VALUE obj, VALUE filepath)
176
176
  if (!file) {
177
177
  rb_raise(eQuickTime, "Unable to open file for saving at %s.", RSTRING(filepath)->ptr);
178
178
  }
179
- fwrite(&settings, GetHandleSize((Handle)settings), 1, file);
179
+ fwrite(*settings, GetHandleSize((Handle)settings), 1, file);
180
180
  fclose(file);
181
181
 
182
182
  return Qnil;
@@ -64,27 +64,29 @@ static VALUE movie_load_from_file(VALUE obj, VALUE filepath)
64
64
  } else {
65
65
  OSErr err;
66
66
  FSSpec fs;
67
- short frefnum = -1;
68
- short movie_resid = 0;
67
+ short resRefNum = -1;
68
+ short resId = 0;
69
69
  Movie *movie = ALLOC(Movie);
70
70
 
71
71
  err = NativePathNameToFSSpec(RSTRING(filepath)->ptr, &fs, 0);
72
72
  if (err != 0)
73
73
  rb_raise(eQuickTime, "Error %d occurred while reading file at %s", err, RSTRING(filepath)->ptr);
74
74
 
75
- err = OpenMovieFile(&fs, &frefnum, fsRdPerm);
75
+ err = OpenMovieFile(&fs, &resRefNum, fsRdPerm);
76
76
  if (err != 0)
77
77
  rb_raise(eQuickTime, "Error %d occurred while opening movie at %s", err, RSTRING(filepath)->ptr);
78
78
 
79
- err = NewMovieFromFile(movie, frefnum, &movie_resid, 0, newMovieActive, 0);
79
+ err = NewMovieFromFile(movie, resRefNum, &resId, 0, newMovieActive, 0);
80
80
  if (err != 0)
81
81
  rb_raise(eQuickTime, "Error %d occurred while loading movie at %s", err, RSTRING(filepath)->ptr);
82
82
 
83
- err = CloseMovieFile(frefnum);
83
+ err = CloseMovieFile(resRefNum);
84
84
  if (err != 0)
85
85
  rb_raise(eQuickTime, "Error %d occurred while closing movie file at %s", err, RSTRING(filepath)->ptr);
86
86
 
87
87
  RMOVIE(obj)->movie = *movie;
88
+ RMOVIE(obj)->filepath = RSTRING(filepath)->ptr;
89
+ RMOVIE(obj)->resId = resId;
88
90
 
89
91
  return obj;
90
92
  }
@@ -158,44 +160,32 @@ static VALUE movie_track_count(VALUE obj)
158
160
  }
159
161
 
160
162
  /*
161
- call-seq: composite_movie(movie, position)
163
+ call-seq: select(position, duration)
162
164
 
163
- Adds the tracks of given movie into called movie at given position (in seconds).
164
-
165
- You can track the progress of this operation by passing a block to this
166
- method. It will be called regularly during the process and pass the
167
- percentage complete (0.0 to 1.0) as an argument to the block.
165
+ Select a portion of a movie. Both position and duration should be
166
+ floats representing seconds.
168
167
  */
169
- static VALUE movie_composite_movie(VALUE obj, VALUE src, VALUE position)
168
+ static VALUE movie_select(VALUE obj, VALUE position, VALUE duration)
170
169
  {
171
- if (rb_block_given_p())
172
- SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
173
-
174
- SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, position), 0);
175
- AddMovieSelection(MOVIE(obj), MOVIE(src));
176
-
177
- if (rb_block_given_p())
178
- SetMovieProgressProc(MOVIE(obj), 0, 0);
179
-
170
+ SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, position), MOVIE_TIME(obj, duration));
180
171
  return obj;
181
172
  }
182
173
 
183
174
  /*
184
- call-seq: append_movie(movie, position)
175
+ call-seq: add_into_selection(movie)
176
+
177
+ Adds the tracks of given movie into called movie's current selection.
185
178
 
186
- Inserts given movie into called movie at given position (in seconds).
187
-
188
179
  You can track the progress of this operation by passing a block to this
189
180
  method. It will be called regularly during the process and pass the
190
181
  percentage complete (0.0 to 1.0) as an argument to the block.
191
182
  */
192
- static VALUE movie_insert_movie(VALUE obj, VALUE src, VALUE position)
183
+ static VALUE movie_add_into_selection(VALUE obj, VALUE src)
193
184
  {
194
185
  if (rb_block_given_p())
195
186
  SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
196
187
 
197
- SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, position), 0);
198
- PasteMovieSelection(MOVIE(obj), MOVIE(src));
188
+ AddMovieSelection(MOVIE(obj), MOVIE(src));
199
189
 
200
190
  if (rb_block_given_p())
201
191
  SetMovieProgressProc(MOVIE(obj), 0, 0);
@@ -204,20 +194,19 @@ static VALUE movie_insert_movie(VALUE obj, VALUE src, VALUE position)
204
194
  }
205
195
 
206
196
  /*
207
- call-seq: append_movie(movie)
197
+ call-seq: insert_into_selection(movie)
198
+
199
+ Inserts the given movie into called movie, replacing any current selection.
208
200
 
209
- Adds given movie to the end of movie which this method is called on.
210
-
211
201
  You can track the progress of this operation by passing a block to this
212
202
  method. It will be called regularly during the process and pass the
213
203
  percentage complete (0.0 to 1.0) as an argument to the block.
214
204
  */
215
- static VALUE movie_append_movie(VALUE obj, VALUE src)
205
+ static VALUE movie_insert_into_selection(VALUE obj, VALUE src)
216
206
  {
217
207
  if (rb_block_given_p())
218
208
  SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
219
209
 
220
- SetMovieSelection(MOVIE(obj), GetMovieDuration(MOVIE(obj)), 0);
221
210
  PasteMovieSelection(MOVIE(obj), MOVIE(src));
222
211
 
223
212
  if (rb_block_given_p())
@@ -227,37 +216,22 @@ static VALUE movie_append_movie(VALUE obj, VALUE src)
227
216
  }
228
217
 
229
218
  /*
230
- call-seq: delete_section(start_time, duration)
219
+ call-seq: clone_selection()
231
220
 
232
- Deletes given section from movie. Both start_time and duration
233
- should be floats representing seconds.
234
- */
235
- static VALUE movie_delete_section(VALUE obj, VALUE start, VALUE duration)
236
- {
237
- SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, start), MOVIE_TIME(obj, duration));
238
- ClearMovieSelection(MOVIE(obj));
239
- return obj;
240
- }
241
-
242
- /*
243
- call-seq: clone_section(start_time, duration) -> movie
221
+ Returns a new movie from the current selection. Does not modify original
222
+ movie.
244
223
 
245
- Returns a new movie in the given section. Does not modify original
246
- movie. Both start_time and duration should be floats representing
247
- seconds.
248
-
249
224
  You can track the progress of this operation by passing a block to this
250
225
  method. It will be called regularly during the process and pass the
251
226
  percentage complete (0.0 to 1.0) as an argument to the block.
252
227
  */
253
- static VALUE movie_clone_section(VALUE obj, VALUE start, VALUE duration)
228
+ static VALUE movie_clone_selection(VALUE obj)
254
229
  {
255
230
  VALUE new_movie_obj = rb_obj_alloc(cMovie);
256
231
 
257
232
  if (rb_block_given_p())
258
233
  SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
259
234
 
260
- SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, start), MOVIE_TIME(obj, duration));
261
235
  RMOVIE(new_movie_obj)->movie = CopyMovieSelection(MOVIE(obj));
262
236
 
263
237
  if (rb_block_given_p())
@@ -267,24 +241,22 @@ static VALUE movie_clone_section(VALUE obj, VALUE start, VALUE duration)
267
241
  }
268
242
 
269
243
  /*
270
- call-seq: clip_section(start_time, duration) -> movie
244
+ call-seq: clip_selection()
245
+
246
+ Deletes current selection on movie and returns a new movie with that
247
+ content.
271
248
 
272
- Deletes given section on movie and returns a new movie with that
273
- section. Both start_time and duration should be floats representing
274
- seconds.
275
-
276
249
  You can track the progress of this operation by passing a block to this
277
250
  method. It will be called regularly during the process and pass the
278
251
  percentage complete (0.0 to 1.0) as an argument to the block.
279
252
  */
280
- static VALUE movie_clip_section(VALUE obj, VALUE start, VALUE duration)
253
+ static VALUE movie_clip_selection(VALUE obj)
281
254
  {
282
255
  VALUE new_movie_obj = rb_obj_alloc(cMovie);
283
256
 
284
257
  if (rb_block_given_p())
285
258
  SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
286
259
 
287
- SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, start), MOVIE_TIME(obj, duration));
288
260
  RMOVIE(new_movie_obj)->movie = CutMovieSelection(MOVIE(obj));
289
261
 
290
262
  if (rb_block_given_p())
@@ -293,6 +265,17 @@ static VALUE movie_clip_section(VALUE obj, VALUE start, VALUE duration)
293
265
  return new_movie_obj;
294
266
  }
295
267
 
268
+ /*
269
+ call-seq: delete_selection()
270
+
271
+ Removes the portion of the movie which is selected.
272
+ */
273
+ static VALUE movie_delete_selection(VALUE obj)
274
+ {
275
+ ClearMovieSelection(MOVIE(obj));
276
+ return obj;
277
+ }
278
+
296
279
  /*
297
280
  call-seq: changed?() -> bool
298
281
 
@@ -345,6 +328,41 @@ static VALUE movie_flatten(VALUE obj, VALUE filepath)
345
328
  return new_movie_obj;
346
329
  }
347
330
 
331
+
332
+ /*
333
+ call-seq: save()
334
+
335
+ Saves the movie to the current file.
336
+ */
337
+ static VALUE movie_save(VALUE obj)
338
+ {
339
+ OSErr err;
340
+ FSSpec fs;
341
+ short resRefNum = -1;
342
+
343
+ if (!RMOVIE(obj)->filepath || !RMOVIE(obj)->resId) {
344
+ rb_raise(eQuickTime, "Unable to save movie because it does not have an associated file.");
345
+ } else {
346
+ err = NativePathNameToFSSpec(RMOVIE(obj)->filepath, &fs, 0);
347
+ if (err != 0)
348
+ rb_raise(eQuickTime, "Error %d occurred while reading file at %s", err, RMOVIE(obj)->filepath);
349
+
350
+ err = OpenMovieFile(&fs, &resRefNum, fsWrPerm);
351
+ if (err != 0)
352
+ rb_raise(eQuickTime, "Error %d occurred while opening movie at %s", err, RMOVIE(obj)->filepath);
353
+
354
+ err = UpdateMovieResource(MOVIE(obj), resRefNum, RMOVIE(obj)->resId, 0);
355
+ if (err != 0)
356
+ rb_raise(eQuickTime, "Error %d occurred while saving movie file", err);
357
+
358
+ err = CloseMovieFile(resRefNum);
359
+ if (err != 0)
360
+ rb_raise(eQuickTime, "Error %d occurred while closing movie file at %s", err, RMOVIE(obj)->filepath);
361
+
362
+ return Qnil;
363
+ }
364
+ }
365
+
348
366
  /*
349
367
  call-seq: export_image_type(filepath, time, ostype)
350
368
 
@@ -440,12 +458,12 @@ void Init_quicktime_movie()
440
458
  rb_define_method(cMovie, "time_scale", movie_time_scale, 0);
441
459
  rb_define_method(cMovie, "bounds", movie_bounds, 0);
442
460
  rb_define_method(cMovie, "track_count", movie_track_count, 0);
443
- rb_define_method(cMovie, "composite_movie", movie_composite_movie, 2);
444
- rb_define_method(cMovie, "insert_movie", movie_insert_movie, 2);
445
- rb_define_method(cMovie, "append_movie", movie_append_movie, 1);
446
- rb_define_method(cMovie, "delete_section", movie_delete_section, 2);
447
- rb_define_method(cMovie, "clone_section", movie_clone_section, 2);
448
- rb_define_method(cMovie, "clip_section", movie_clip_section, 2);
461
+ rb_define_method(cMovie, "select", movie_select, 2);
462
+ rb_define_method(cMovie, "add_into_selection", movie_add_into_selection, 1);
463
+ rb_define_method(cMovie, "insert_into_selection", movie_insert_into_selection, 1);
464
+ rb_define_method(cMovie, "clone_selection", movie_clone_selection, 0);
465
+ rb_define_method(cMovie, "clip_selection", movie_clip_selection, 0);
466
+ rb_define_method(cMovie, "delete_selection", movie_delete_selection, 0);
449
467
  rb_define_method(cMovie, "changed?", movie_changed, 0);
450
468
  rb_define_method(cMovie, "clear_changed_status", movie_clear_changed_status, 0);
451
469
  rb_define_method(cMovie, "flatten", movie_flatten, 1);
@@ -454,4 +472,5 @@ void Init_quicktime_movie()
454
472
  rb_define_method(cMovie, "poster_time", movie_get_poster_time, 0);
455
473
  rb_define_method(cMovie, "poster_time=", movie_set_poster_time, 1);
456
474
  rb_define_method(cMovie, "new_track", movie_new_track, 2);
475
+ rb_define_method(cMovie, "save", movie_save, 0);
457
476
  }
@@ -17,6 +17,8 @@ OSErr movie_progress_proc(Movie movie, short message, short operation, Fixed per
17
17
 
18
18
  struct RMovie {
19
19
  Movie movie;
20
+ short resId;
21
+ char *filepath;
20
22
  };
21
23
 
22
24
 
@@ -191,7 +191,7 @@ static VALUE track_set_offset(VALUE obj, VALUE seconds)
191
191
  }
192
192
 
193
193
  /*
194
- call-seq: new_video_media
194
+ call-seq: new_video_media()
195
195
 
196
196
  Creates a new video media for this track.
197
197
 
@@ -205,7 +205,7 @@ static VALUE track_new_video_media(VALUE obj)
205
205
  }
206
206
 
207
207
  /*
208
- call-seq: new_audio_media
208
+ call-seq: new_audio_media()
209
209
 
210
210
  Creates a new audio media for this track.
211
211
 
@@ -219,7 +219,7 @@ static VALUE track_new_audio_media(VALUE obj)
219
219
  }
220
220
 
221
221
  /*
222
- call-seq: new_text_media
222
+ call-seq: new_text_media()
223
223
 
224
224
  Creates a new text media for this track.
225
225
 
@@ -232,6 +232,101 @@ static VALUE track_new_text_media(VALUE obj)
232
232
  return obj;
233
233
  }
234
234
 
235
+ /*
236
+ call-seq: enable_alpha()
237
+
238
+ Enable the straight alpha graphic mode for this track.
239
+
240
+ This is best used on an overlayed video track which includes some
241
+ alpha transparency (such as in a PNG image).
242
+ */
243
+ static VALUE track_enable_alpha(VALUE obj)
244
+ {
245
+ MediaSetGraphicsMode(GetMediaHandler(TRACK_MEDIA(obj)), graphicsModeStraightAlpha, 0);
246
+ return obj;
247
+ }
248
+
249
+ /*
250
+ call-seq: scale(width, height)
251
+
252
+ Scale the track's size by width and height respectively.
253
+
254
+ The value passed is a relative float where "1" is the current size.
255
+ */
256
+ static VALUE track_scale(VALUE obj, VALUE width, VALUE height)
257
+ {
258
+ MatrixRecord matrix;
259
+ GetTrackMatrix(TRACK(obj), &matrix);
260
+ ScaleMatrix(&matrix, FloatToFixed(NUM2DBL(width)), FloatToFixed(NUM2DBL(height)), 0, 0);
261
+ SetTrackMatrix(TRACK(obj), &matrix);
262
+ return obj;
263
+ }
264
+
265
+ /*
266
+ call-seq: translate(x, y)
267
+
268
+ Offset a track's position by x and y values respectively.
269
+
270
+ Values should be in pixels.
271
+ */
272
+ static VALUE track_translate(VALUE obj, VALUE x, VALUE y)
273
+ {
274
+ MatrixRecord matrix;
275
+ GetTrackMatrix(TRACK(obj), &matrix);
276
+ TranslateMatrix(&matrix, FloatToFixed(NUM2DBL(x)), FloatToFixed(NUM2DBL(y)));
277
+ SetTrackMatrix(TRACK(obj), &matrix);
278
+ return obj;
279
+ }
280
+
281
+ /*
282
+ call-seq: rotate(degrees)
283
+
284
+ Rotate the track by the given number of degrees.
285
+ */
286
+ static VALUE track_rotate(VALUE obj, VALUE degrees)
287
+ {
288
+ MatrixRecord matrix;
289
+ GetTrackMatrix(TRACK(obj), &matrix);
290
+ RotateMatrix(&matrix, FloatToFixed(NUM2DBL(degrees)), 0, 0);
291
+ SetTrackMatrix(TRACK(obj), &matrix);
292
+ return obj;
293
+ }
294
+
295
+ /*
296
+ call-seq: bounds() -> bounds_hash
297
+
298
+ Returns a hash of boundaries. The hash contains four keys: :left, :top,
299
+ :right, :bottom. Each holds an integer representing the pixel value.
300
+ */
301
+ static VALUE track_bounds(VALUE obj)
302
+ {
303
+ VALUE bounds_hash = rb_hash_new();
304
+ RgnHandle region;
305
+ Rect bounds;
306
+ region = GetTrackDisplayBoundsRgn(TRACK(obj));
307
+ GetRegionBounds(region, &bounds);
308
+ DisposeRgn(region);
309
+ rb_hash_aset(bounds_hash, ID2SYM(rb_intern("left")), INT2NUM(bounds.left));
310
+ rb_hash_aset(bounds_hash, ID2SYM(rb_intern("top")), INT2NUM(bounds.top));
311
+ rb_hash_aset(bounds_hash, ID2SYM(rb_intern("right")), INT2NUM(bounds.right));
312
+ rb_hash_aset(bounds_hash, ID2SYM(rb_intern("bottom")), INT2NUM(bounds.bottom));
313
+ return bounds_hash;
314
+ }
315
+
316
+ /*
317
+ call-seq: reset_transformations()
318
+
319
+ Revert any transformations (scale, translate, rotate) performed on this track.
320
+ */
321
+ static VALUE track_reset_transformations(VALUE obj)
322
+ {
323
+ MatrixRecord matrix;
324
+ GetTrackMatrix(TRACK(obj), &matrix);
325
+ SetIdentityMatrix(&matrix);
326
+ SetTrackMatrix(TRACK(obj), &matrix);
327
+ return obj;
328
+ }
329
+
235
330
  void Init_quicktime_track()
236
331
  {
237
332
  VALUE mQuickTime;
@@ -255,4 +350,10 @@ void Init_quicktime_track()
255
350
  rb_define_method(cTrack, "new_video_media", track_new_video_media, 0);
256
351
  rb_define_method(cTrack, "new_audio_media", track_new_audio_media, 0);
257
352
  rb_define_method(cTrack, "new_text_media", track_new_text_media, 0);
353
+ rb_define_method(cTrack, "enable_alpha", track_enable_alpha, 0);
354
+ rb_define_method(cTrack, "scale", track_scale, 2);
355
+ rb_define_method(cTrack, "translate", track_translate, 2);
356
+ rb_define_method(cTrack, "rotate", track_rotate, 1);
357
+ rb_define_method(cTrack, "bounds", track_bounds, 0);
358
+ rb_define_method(cTrack, "reset_transformations", track_reset_transformations, 0);
258
359
  }
@@ -87,10 +87,10 @@ module QuickTime
87
87
  def export_image(filepath, seconds)
88
88
  # TODO support more file types
89
89
  type = case File.extname(filepath).downcase
90
- when '.pct' then 'PICT'
91
- when '.png' then 'PNGf'
90
+ when '.pct', '.pict' then 'PICT'
92
91
  when '.tif', '.tiff' then 'TIFF'
93
92
  when '.jpg', '.jpeg' then 'JPEG'
93
+ when '.png' then 'PNGf'
94
94
  when '.tga' then 'TPIC'
95
95
  when '.bmp' then 'BMPf'
96
96
  when '.psd' then '8BPS'
@@ -98,5 +98,77 @@ module QuickTime
98
98
  end
99
99
  export_image_type(filepath, seconds, type)
100
100
  end
101
+
102
+ # Reset selection to beginning
103
+ def deselect
104
+ select(0, 0)
105
+ end
106
+
107
+ # Adds the tracks of given movie into called movie. Position will default to
108
+ # beginning of movie. Duration will default to length of given movie.
109
+ #
110
+ # You can track the progress of this operation by passing a block to this
111
+ # method. It will be called regularly during the process and pass the
112
+ # percentage complete (0.0 to 1.0) as an argument to the block.
113
+ def composite_movie(movie, position = 0, duration = 0, &block)
114
+ select(position, duration)
115
+ add_into_selection(movie, &block)
116
+ deselect
117
+ end
118
+
119
+ # Adds given movie to the end of movie which this method is called on.
120
+ #
121
+ # You can track the progress of this operation by passing a block to this
122
+ # method. It will be called regularly during the process and pass the
123
+ # percentage complete (0.0 to 1.0) as an argument to the block.
124
+ def append_movie(movie, &block)
125
+ select(duration, 0)
126
+ insert_into_selection(movie, &block)
127
+ deselect
128
+ end
129
+
130
+ # Inserts given movie into called movie. The position defaults to the beginning
131
+ # of the movie. If a duration is passed, that amount of the movie will be replaced.
132
+ #
133
+ # You can track the progress of this operation by passing a block to this
134
+ # method. It will be called regularly during the process and pass the
135
+ # percentage complete (0.0 to 1.0) as an argument to the block.
136
+ def insert_movie(movie, position = 0, duration = 0, &block)
137
+ select(position, duration)
138
+ insert_into_selection(movie, &block)
139
+ deselect
140
+ end
141
+
142
+ # Returns a new movie from the specified portion of called movie.
143
+ #
144
+ # You can track the progress of this operation by passing a block to this
145
+ # method. It will be called regularly during the process and pass the
146
+ # percentage complete (0.0 to 1.0) as an argument to the block.
147
+ def clone_section(position = 0, duration = 0, &block)
148
+ select(position, duration)
149
+ movie = clone_selection(&block)
150
+ deselect
151
+ movie
152
+ end
153
+
154
+ # Deletes the specified section on movie and returns a new movie
155
+ # with that content.
156
+ #
157
+ # You can track the progress of this operation by passing a block to this
158
+ # method. It will be called regularly during the process and pass the
159
+ # percentage complete (0.0 to 1.0) as an argument to the block.
160
+ def clip_section(position = 0, duration = 0, &block)
161
+ select(position, duration)
162
+ movie = clip_selection(&block)
163
+ deselect
164
+ movie
165
+ end
166
+
167
+ # Deletes the specified section on movie.
168
+ def delete_section(position = 0, duration = 0)
169
+ select(position, duration)
170
+ delete_selection
171
+ deselect
172
+ end
101
173
  end
102
174
  end
@@ -26,5 +26,15 @@ module QuickTime
26
26
  def text?
27
27
  media_type == :text
28
28
  end
29
+
30
+ # Returns the bounding width of this track in number of pixels.
31
+ def width
32
+ bounds[:right] - bounds[:left]
33
+ end
34
+
35
+ # Returns the bounding height of this track in number of pixels.
36
+ def height
37
+ bounds[:bottom] - bounds[:top]
38
+ end
29
39
  end
30
40
  end
@@ -1,99 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
1
2
 
2
- # Gem::Specification for Rmov-0.1.4
3
- # Originally generated by Echoe
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{rmov}
5
+ s.version = "0.1.5"
4
6
 
5
- --- !ruby/object:Gem::Specification
6
- name: rmov
7
- version: !ruby/object:Gem::Version
8
- version: 0.1.4
9
- platform: ruby
10
- authors:
11
- - Ryan Bates
12
- autorequire:
13
- bindir: bin
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-07-28}
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/dot.png", "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.homepage = %q{http://github.com/ryanb/rmov}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rmov", "--main", "README.rdoc"]
17
+ s.require_paths = ["lib", "ext"]
18
+ s.rubyforge_project = %q{rmov}
19
+ s.rubygems_version = %q{1.3.3}
20
+ s.summary = %q{Ruby wrapper for the QuickTime C API.}
14
21
 
15
- date: 2008-10-03 00:00:00 -07:00
16
- default_executable:
17
- dependencies: []
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
18
25
 
19
- description: Ruby wrapper for the QuickTime C API.
20
- email: ryan (at) railscasts (dot) com
21
- executables: []
22
-
23
- extensions:
24
- - ext/extconf.rb
25
- extra_rdoc_files:
26
- - CHANGELOG
27
- - ext/exporter.c
28
- - ext/extconf.rb
29
- - ext/movie.c
30
- - ext/rmov_ext.c
31
- - ext/rmov_ext.h
32
- - ext/track.c
33
- - lib/quicktime/exporter.rb
34
- - lib/quicktime/movie.rb
35
- - lib/quicktime/track.rb
36
- - lib/rmov.rb
37
- - LICENSE
38
- - README.rdoc
39
- - tasks/setup.rake
40
- - tasks/spec.rake
41
- - TODO
42
- files:
43
- - CHANGELOG
44
- - ext/exporter.c
45
- - ext/extconf.rb
46
- - ext/movie.c
47
- - ext/rmov_ext.c
48
- - ext/rmov_ext.h
49
- - ext/track.c
50
- - lib/quicktime/exporter.rb
51
- - lib/quicktime/movie.rb
52
- - lib/quicktime/track.rb
53
- - lib/rmov.rb
54
- - LICENSE
55
- - Manifest
56
- - Rakefile
57
- - README.rdoc
58
- - spec/fixtures/settings.st
59
- - spec/quicktime/exporter_spec.rb
60
- - spec/quicktime/movie_spec.rb
61
- - spec/quicktime/track_spec.rb
62
- - spec/spec.opts
63
- - spec/spec_helper.rb
64
- - tasks/setup.rake
65
- - tasks/spec.rake
66
- - TODO
67
- - rmov.gemspec
68
- has_rdoc: true
69
- homepage: http://github.com/ryanb/rmov
70
- post_install_message:
71
- rdoc_options:
72
- - --line-numbers
73
- - --inline-source
74
- - --title
75
- - Rmov
76
- - --main
77
- - README.rdoc
78
- require_paths:
79
- - lib
80
- - ext
81
- required_ruby_version: !ruby/object:Gem::Requirement
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- version: "0"
86
- version:
87
- required_rubygems_version: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- version: "1.2"
92
- version:
93
- requirements: []
94
-
95
- rubyforge_project: rmov
96
- rubygems_version: 1.2.0
97
- specification_version: 2
98
- summary: Ruby wrapper for the QuickTime C API.
99
- test_files: []
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end
Binary file
Binary file
@@ -26,4 +26,22 @@ describe QuickTime::Exporter do
26
26
  lambda { @exporter.save_settings('foo/bar/baz') }.should raise_error(QuickTime::Error)
27
27
  end
28
28
  end
29
+ describe "example.mov" do
30
+ before(:each) do
31
+ @movie = QuickTime::Movie.open(File.dirname(__FILE__) + '/../fixtures/example.mov')
32
+ @exporter = @movie.exporter
33
+ end
34
+
35
+ it "should be able to export from loaded settings.st" do
36
+ load_path = File.dirname(__FILE__) + '/../fixtures/settings.st'
37
+ path = File.dirname(__FILE__) + '/../output/loaded_exported_example.mov'
38
+ File.delete(path) rescue nil
39
+
40
+ @exporter.load_settings(load_path)
41
+ @exporter.export(path)
42
+ exported_movie = QuickTime::Movie.open(path)
43
+ exported_movie.duration.should == @movie.duration
44
+ exported_movie.tracks.size == @movie.tracks.size
45
+ end
46
+ end
29
47
  end
@@ -111,12 +111,28 @@ describe QuickTime::Movie do
111
111
 
112
112
  it "flatten should save movie into file" do
113
113
  path = File.dirname(__FILE__) + '/../output/flattened_example.mov'
114
- File.delete(path) rescue nil
114
+ File.delete(path) if File.exist?(path)
115
115
  @movie.flatten(path)
116
116
  mov = QuickTime::Movie.open(path)
117
117
  mov.duration.should == 3.1
118
118
  end
119
119
 
120
+ it "save should update movie in current file" do
121
+ path = File.dirname(__FILE__) + '/../output/saved_example.mov'
122
+ File.delete(path) if File.exist?(path)
123
+ @movie.flatten(path)
124
+ mov = QuickTime::Movie.open(path)
125
+ mov.audio_tracks.each { |t| t.delete } # delete track to demonstrate change
126
+ mov.save
127
+ mov2 = QuickTime::Movie.open(path)
128
+ mov2.audio_tracks.should be_empty
129
+ end
130
+
131
+ it "save should raise exception when saving new movie without filepath" do
132
+ mov = QuickTime::Movie.empty
133
+ lambda { mov.save }.should raise_error
134
+ end
135
+
120
136
  it "export_pict should output a pict file at a given duration" do
121
137
  path = File.dirname(__FILE__) + '/../output/example.pct'
122
138
  File.delete(path) rescue nil
@@ -137,6 +153,15 @@ describe QuickTime::Movie do
137
153
  @movie.poster_time = 2.1
138
154
  @movie.poster_time.should == 2.1
139
155
  end
156
+
157
+ it "should overlay 2nd movie with transparency" do
158
+ m2 = QuickTime::Movie.open(File.dirname(__FILE__) + '/../fixtures/dot.png')
159
+ @movie.composite_movie(m2, 0)
160
+ @movie.video_tracks.last.enable_alpha
161
+ File.delete(File.dirname(__FILE__) + '/../output/transparent.mov') rescue nil
162
+ @movie.flatten(File.dirname(__FILE__) + '/../output/transparent.mov')
163
+ # this test needs to be checked manually by looking at the output movie
164
+ end
140
165
  end
141
166
 
142
167
  describe "empty movie" do
@@ -6,7 +6,7 @@ describe QuickTime::Track do
6
6
  @movie = QuickTime::Movie.open(File.dirname(__FILE__) + '/../fixtures/example.mov')
7
7
  end
8
8
 
9
- describe "example.mov video track" do
9
+ describe "video track" do
10
10
  before(:each) do
11
11
  @track = @movie.video_tracks.first
12
12
  end
@@ -49,9 +49,37 @@ describe QuickTime::Track do
49
49
  @track.offset = 2.5
50
50
  @track.offset.should == 2.5
51
51
  end
52
+
53
+ it "should be able to scale size of track" do
54
+ @track.scale(0.5, 0.5)
55
+ @track.width.should == 30
56
+ @track.height.should == 25
57
+ end
58
+
59
+ it "should be able to move (translate) position of track" do
60
+ @track.translate(10, 20)
61
+ @track.bounds[:left].should == 10
62
+ @track.bounds[:top].should == 20
63
+ end
64
+
65
+ it "should reset transformations" do
66
+ @track.scale(0.5, 0.5)
67
+ @track.translate(10, 20)
68
+ @track.reset_transformations
69
+ @track.bounds[:left].should == 0
70
+ @track.bounds[:top].should == 0
71
+ @track.bounds[:right].should == 60
72
+ @track.bounds[:bottom].should == 50
73
+ end
74
+
75
+ it "should rotate track" do
76
+ @track.rotate(90)
77
+ @track.width.should == 50
78
+ @track.height.should == 60
79
+ end
52
80
  end
53
-
54
- describe "example.mov audio track" do
81
+
82
+ describe "audio track" do
55
83
  before(:each) do
56
84
  @track = @movie.audio_tracks.first
57
85
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rmov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Bates
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-10-03 00:00:00 -07:00
12
+ date: 2009-07-28 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -52,6 +52,7 @@ files:
52
52
  - Manifest
53
53
  - Rakefile
54
54
  - README.rdoc
55
+ - spec/fixtures/dot.png
55
56
  - spec/fixtures/settings.st
56
57
  - spec/quicktime/exporter_spec.rb
57
58
  - spec/quicktime/movie_spec.rb
@@ -64,6 +65,8 @@ files:
64
65
  - rmov.gemspec
65
66
  has_rdoc: true
66
67
  homepage: http://github.com/ryanb/rmov
68
+ licenses: []
69
+
67
70
  post_install_message:
68
71
  rdoc_options:
69
72
  - --line-numbers
@@ -90,9 +93,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
93
  requirements: []
91
94
 
92
95
  rubyforge_project: rmov
93
- rubygems_version: 1.2.0
96
+ rubygems_version: 1.3.3
94
97
  signing_key:
95
- specification_version: 2
98
+ specification_version: 3
96
99
  summary: Ruby wrapper for the QuickTime C API.
97
100
  test_files: []
98
101