Class: QuickTime::Movie

Inherits:
Object
  • Object
show all
Defined in:
lib/quicktime/movie.rb,
ext/movie.c

Overview

see ext/movie.c for additional methods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.emptyObject

Returns a new, empty movie.



10
11
12
# File 'lib/quicktime/movie.rb', line 10

def self.empty
  new.load_empty
end

.open(filepath) ⇒ Object

Opens a movie at filepath.



5
6
7
# File 'lib/quicktime/movie.rb', line 5

def self.open(filepath)
  new.load_from_file(filepath)
end

Instance Method Details

#append_movie(movie) ⇒ Object

Adds given movie to the end of movie which this method is called on.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'ext/movie.c', line 215

static VALUE movie_append_movie(VALUE obj, VALUE src)
{
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  SetMovieSelection(MOVIE(obj), GetMovieDuration(MOVIE(obj)), 0);
  PasteMovieSelection(MOVIE(obj), MOVIE(src));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return obj;
}

#audio_tracksObject

Returns an array of audio tracks in this movie.



38
39
40
# File 'lib/quicktime/movie.rb', line 38

def audio_tracks
  tracks.select { |t| t.audio? }
end

#boundsObject

Returns a hash of boundaries. The hash contains four keys: :left, :top, :right, :bottom. Each holds an integer representing the pixel value.



138
139
140
141
142
143
144
145
146
147
148
# File 'ext/movie.c', line 138

static VALUE movie_bounds(VALUE obj)
{
  VALUE bounds_hash = rb_hash_new();
  Rect bounds;
  GetMovieBox(MOVIE(obj), &bounds);
  rb_hash_aset(bounds_hash, ID2SYM(rb_intern("left")), INT2NUM(bounds.left));
  rb_hash_aset(bounds_hash, ID2SYM(rb_intern("top")), INT2NUM(bounds.top));
  rb_hash_aset(bounds_hash, ID2SYM(rb_intern("right")), INT2NUM(bounds.right));
  rb_hash_aset(bounds_hash, ID2SYM(rb_intern("bottom")), INT2NUM(bounds.bottom));
  return bounds_hash;
}

#changed?Boolean

Determine if a movie has changed since opening. Returns true/false. See reset_changed_status to reset this value.

Returns:

  • (Boolean)


302
303
304
305
306
307
308
309
# File 'ext/movie.c', line 302

static VALUE movie_changed(VALUE obj)
{
  if (HasMovieChanged(MOVIE(obj))) {
    return Qtrue;
  } else {
    return Qfalse;
  }
}

#clear_changed_statusObject

Resets the “changed?” status. Does not revert the movie itself.



316
317
318
319
320
# File 'ext/movie.c', line 316

static VALUE movie_clear_changed_status(VALUE obj)
{
  ClearMovieChanged(MOVIE(obj));
  return Qnil;
}

#clip_section(start_time, duration) ⇒ Object

Deletes given section on movie and returns a new movie with that section. Both start_time and duration should be floats representing seconds.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'ext/movie.c', line 280

static VALUE movie_clip_section(VALUE obj, VALUE start, VALUE duration)
{
  VALUE new_movie_obj = rb_obj_alloc(cMovie);
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, start), MOVIE_TIME(obj, duration));
  RMOVIE(new_movie_obj)->movie = CutMovieSelection(MOVIE(obj));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return new_movie_obj;
}

#clone_section(start_time, duration) ⇒ Object

Returns a new movie in the given section. Does not modify original movie. Both start_time and duration should be floats representing seconds.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'ext/movie.c', line 253

static VALUE movie_clone_section(VALUE obj, VALUE start, VALUE duration)
{
  VALUE new_movie_obj = rb_obj_alloc(cMovie);
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, start), MOVIE_TIME(obj, duration));
  RMOVIE(new_movie_obj)->movie = CopyMovieSelection(MOVIE(obj));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return new_movie_obj;
}

#composite_movie(movie, position) ⇒ Object

Adds the tracks of given movie into called movie at given position (in seconds).

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'ext/movie.c', line 169

static VALUE movie_composite_movie(VALUE obj, VALUE src, VALUE position)
{
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, position), 0);
  AddMovieSelection(MOVIE(obj), MOVIE(src));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return obj;
}

#delete_section(start_time, duration) ⇒ Object

Deletes given section from movie. Both start_time and duration should be floats representing seconds.



235
236
237
238
239
240
# File 'ext/movie.c', line 235

static VALUE movie_delete_section(VALUE obj, VALUE start, VALUE duration)
{
  SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, start), MOVIE_TIME(obj, duration));
  ClearMovieSelection(MOVIE(obj));
  return obj;
}

#disposeObject

Dispose of the loaded QuickTime movie. This will automatically be done when this movie instance is garbage collected. However if you are iterating through many movies it is often helpful to dispose of it as soon as you’re done with it.



44
45
46
47
48
49
50
51
# File 'ext/movie.c', line 44

static VALUE movie_dispose(VALUE obj)
{
  if (MOVIE(obj)) {
    DisposeMovie(MOVIE(obj));
    RMOVIE(obj)->movie = NULL;
  }
  return obj;
}

#durationObject

Returns the length of this movie in seconds using raw_duration and time_scale.



16
17
18
# File 'lib/quicktime/movie.rb', line 16

def duration
  raw_duration.to_f/time_scale
end

#export(*args, &block) ⇒ Object

Convenience method for exporting the movie. See Exporter::export.



58
59
60
# File 'lib/quicktime/movie.rb', line 58

def export(*args, &block)
  exporter.export(*args, &block)
end

#export_image(filepath, seconds) ⇒ Object

Exports a frame of the movie at the given time (in seconds) to the given file. The image format is automatically determined from the file extension. If this cannot be determined from the extension then you can use export_image_type to specify the ostype manually.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/quicktime/movie.rb', line 87

def export_image(filepath, seconds)
  # TODO support more file types
  type = case File.extname(filepath).downcase
    when '.pct', '.pict' then 'PICT'
    when '.tif', '.tiff' then 'TIFF'
    when '.jpg', '.jpeg' then 'JPEG'
    when '.png'          then 'PNGf'
    when '.tga'          then 'TPIC'
    when '.bmp'          then 'BMPf'
    when '.psd'          then '8BPS'
    else raise QuickTime::Error, "Unable to guess ostype from file extension of #{filepath}"
  end
  export_image_type(filepath, seconds, type)
end

#export_image_type(filepath, time, ostype) ⇒ Object

Exports an image as the given ostype. It is best to use export_image instead if the ostype can be determined from the filepath extension.



354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'ext/movie.c', line 354

static VALUE movie_export_image_type(VALUE obj, VALUE filepath, VALUE frame_time, VALUE ostype_obj)
{
  GraphicsImportComponent component;
  PicHandle picture;
  Handle handle;
  FSSpec fs;
  OSErr err;
  
  picture = GetMoviePict(MOVIE(obj), MOVIE_TIME(obj, frame_time));
  
  err = NativePathNameToFSSpec(RSTRING(filepath)->ptr, &fs, 0);
  if (err != fnfErr)
    rb_raise(eQuickTime, "Error %d occurred while opening file for export at %s.", err, RSTRING(filepath)->ptr);
  
  // Convert the picture handle into a PICT file (still in a handle)
  // by adding a 512-byte header to the start.
  handle = NewHandleClear(512);
  err = HandAndHand((Handle)picture, handle);
  if (err != noErr)
    rb_raise(eQuickTime, "Error %d occurred while converting handle for pict export %s.", err, RSTRING(filepath)->ptr);
  
  err = OpenADefaultComponent(GraphicsImporterComponentType, kQTFileTypePicture, &component);
  if (err != noErr)
    rb_raise(eQuickTime, "Error %d occurred while opening picture component for %s.", err, RSTRING(filepath)->ptr);
  
  err = GraphicsImportSetDataHandle(component, handle);
  if (err != noErr)
    rb_raise(eQuickTime, "Error %d occurred while setting graphics importer data handle for %s.", err, RSTRING(filepath)->ptr);
  
  err = GraphicsImportExportImageFile(component, OSTYPE(RSTRING(ostype_obj)->ptr), 0, &fs, smSystemScript);
  if (err != noErr)
    rb_raise(eQuickTime, "Error %d occurred while exporting pict to file %s.", err, RSTRING(filepath)->ptr);
  
  CloseComponent(component);
  DisposeHandle(handle);
  DisposeHandle((Handle)picture);
  
  return Qnil;
}

#exporterObject

Returns an Exporter instance for this movie.



53
54
55
# File 'lib/quicktime/movie.rb', line 53

def exporter
  Exporter.new(self)
end

#flatten(filepath) ⇒ Object

Saves the movie to the given filepath by flattening it.



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'ext/movie.c', line 328

static VALUE movie_flatten(VALUE obj, VALUE filepath)
{
  OSErr err;
  FSSpec fs;
  VALUE new_movie_obj = rb_obj_alloc(cMovie);
  
  err = NativePathNameToFSSpec(RSTRING(filepath)->ptr, &fs, 0);
  if (err != fnfErr)
    rb_raise(eQuickTime, "Error %d occurred while opening file for export at %s", err, RSTRING(filepath)->ptr);
  
  // TODO make these flags settable through an options hash
  RMOVIE(new_movie_obj)->movie = FlattenMovieData(MOVIE(obj),
                                  flattenDontInterleaveFlatten
                                  | flattenCompressMovieResource
                                  | flattenAddMovieToDataFork
                                  | flattenForceMovieResourceBeforeMovieData,
                                  &fs, 'TVOD', smSystemScript, createMovieFileDontCreateResFile);
  return new_movie_obj;
}

#heightObject

Returns the bounding height of this movie in number of pixels.



26
27
28
# File 'lib/quicktime/movie.rb', line 26

def height
  bounds[:bottom] - bounds[:top]
end

#append_movie(movie, position) ⇒ Object

Inserts given movie into called movie at given position (in seconds).

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'ext/movie.c', line 192

static VALUE movie_insert_movie(VALUE obj, VALUE src, VALUE position)
{
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, position), 0);
  PasteMovieSelection(MOVIE(obj), MOVIE(src));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return obj;
}

#load_emptyObject

Loads a new, empty QuickTime movie. Should only be called if no movie has been loaded (or it has been disposed). Usually you go through Movie.empty.



100
101
102
103
104
105
106
107
108
# File 'ext/movie.c', line 100

static VALUE movie_load_empty(VALUE obj)
{
  if (MOVIE(obj)) {
    rb_raise(eQuickTime, "Movie has already been loaded.");
  } else {
    RMOVIE(obj)->movie = NewMovie(0);
    return obj; 
  }
}

#load_from_file(filepath) ⇒ Object

Loads a new, empty QuickTime movie at given filepath. Should only be called if no movie has been loaded (or it has been disposed). Usually you go through Movie.open.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'ext/movie.c', line 60

static VALUE movie_load_from_file(VALUE obj, VALUE filepath)
{
  if (MOVIE(obj)) {
    rb_raise(eQuickTime, "Movie has already been loaded.");
  } else {
    OSErr err;
    FSSpec fs;
    short frefnum = -1;
    short movie_resid = 0;
    Movie *movie = ALLOC(Movie);
    
    err = NativePathNameToFSSpec(RSTRING(filepath)->ptr, &fs, 0);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while reading file at %s", err, RSTRING(filepath)->ptr);
    
    err = OpenMovieFile(&fs, &frefnum, fsRdPerm);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while opening movie at %s", err, RSTRING(filepath)->ptr);
    
    err = NewMovieFromFile(movie, frefnum, &movie_resid, 0, newMovieActive, 0);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while loading movie at %s", err, RSTRING(filepath)->ptr);
    
    err = CloseMovieFile(frefnum);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while closing movie file at %s", err, RSTRING(filepath)->ptr);
    
    RMOVIE(obj)->movie = *movie;
    
    return obj;
  }
}

#new_audio_track(width, height) ⇒ Object

Creates a new audio track with given width/height on movie and returns it.



70
71
72
73
74
# File 'lib/quicktime/movie.rb', line 70

def new_audio_track(width, height)
  track = new_track(width, height)
  track.new_audio_media
  track
end

#new_text_track(width, height) ⇒ Object

Creates a new text track with given width/height on movie and returns it.



77
78
79
80
81
# File 'lib/quicktime/movie.rb', line 77

def new_text_track(width, height)
  track = new_track(width, height)
  track.new_text_media
  track
end

#new_track(width, height) ⇒ Object

Creates a new track with the given width/height on the movie and returns it.

This method is generally not called directly. Instead you should call new_video_track or new_audio_track. If you call method make sure to call new_media on track to setup the media.



424
425
426
427
428
429
# File 'ext/movie.c', line 424

static VALUE movie_new_track(VALUE obj, VALUE width, VALUE height)
{
  VALUE track_obj = rb_obj_alloc(cTrack);
  RTRACK(track_obj)->track = NewMovieTrack(MOVIE(obj), NUM2INT(width), NUM2INT(height), kFullVolume);
  return track_obj;
}

#new_video_track(width, height) ⇒ Object

Creates a new video track with given width/height on movie and returns it.



63
64
65
66
67
# File 'lib/quicktime/movie.rb', line 63

def new_video_track(width, height)
  track = new_track(width, height)
  track.new_video_media
  track
end

#poster_timeObject

Returns the poster time of the movie (in seconds).



399
400
401
402
# File 'ext/movie.c', line 399

static VALUE movie_get_poster_time(VALUE obj)
{
  return rb_float_new((double)GetMoviePosterTime(MOVIE(obj))/GetMovieTimeScale(MOVIE(obj)));
}

#poster_time=(seconds) ⇒ Object

Sets the poster_time of the movie (in seconds).



409
410
411
412
413
# File 'ext/movie.c', line 409

static VALUE movie_set_poster_time(VALUE obj, VALUE seconds)
{
  SetMoviePosterTime(MOVIE(obj), MOVIE_TIME(obj, seconds));
  return Qnil;
}

#raw_durationObject

Returns the raw duration of the movie. Combine this with time_scale to reach the duration in seconds.



116
117
118
119
# File 'ext/movie.c', line 116

static VALUE movie_raw_duration(VALUE obj)
{
  return INT2NUM(GetMovieDuration(MOVIE(obj)));
}

#text_tracksObject

Returns an array of text tracks in this movie.



48
49
50
# File 'lib/quicktime/movie.rb', line 48

def text_tracks
  tracks.select { |t| t.text? }
end

#time_scaleObject

Returns the time scale of the movie. Usually only needed when working with raw_duration.



127
128
129
130
# File 'ext/movie.c', line 127

static VALUE movie_time_scale(VALUE obj)
{
  return INT2NUM(GetMovieTimeScale(MOVIE(obj)));
}

#track_countObject

Returns the number of tracks in the movie.



155
156
157
158
# File 'ext/movie.c', line 155

static VALUE movie_track_count(VALUE obj)
{
  return INT2NUM(GetMovieTrackCount(MOVIE(obj)));
}

#tracksObject

Returns an array of tracks in this movie.



31
32
33
34
35
# File 'lib/quicktime/movie.rb', line 31

def tracks
  (1..track_count).map do |i|
    Track.new.load_from_movie(self, i)
  end
end

#video_tracksObject

Returns an array of video tracks in this movie.



43
44
45
# File 'lib/quicktime/movie.rb', line 43

def video_tracks
  tracks.select { |t| t.video? }
end

#widthObject

Returns the bounding width of this movie in number of pixels.



21
22
23
# File 'lib/quicktime/movie.rb', line 21

def width
  bounds[:right] - bounds[:left]
end