one-k-rmov 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +6 -1
- data/Rakefile +3 -3
- data/ext/track.c +180 -41
- data/rmov.gemspec +4 -4
- metadata +4 -4
data/CHANGELOG
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
|
2
|
+
0.2.1 (February 26, 2009)
|
3
|
+
|
2
4
|
* adding more property information from movie and track, such as codec information
|
3
5
|
|
4
|
-
|
6
|
+
* adds audio channel information
|
7
|
+
|
8
|
+
0.2.0 1K Studios Forked Version
|
9
|
+
purpose is to expose more reporting about movie, track information reporting
|
5
10
|
|
6
11
|
0.1.4 (October 3rd, 2008)
|
7
12
|
|
data/Rakefile
CHANGED
@@ -2,11 +2,11 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('rmov', '0.2.
|
5
|
+
Echoe.new('rmov', '0.2.2') do |p|
|
6
6
|
p.summary = "Ruby wrapper for the QuickTime C API."
|
7
|
-
p.description = "Ruby wrapper for the QuickTime C API."
|
7
|
+
p.description = "Ruby wrapper for the QuickTime C API. Updates by 1K include exposing some movie properties such as codec and audio channel descriptions"
|
8
8
|
p.url = "http://github.com/ryanb/rmov"
|
9
|
-
p.author = 'Ryan Bates'
|
9
|
+
p.author = 'Ryan Bates, with updates by 1K Studios, LLC'
|
10
10
|
p.email = "ryan (at) railscasts (dot) com"
|
11
11
|
p.ignore_pattern = ["script/*", "tmp/*", "spec/output/*", "**/*.o", "**/*.bundle", "**/*.mov"]
|
12
12
|
p.extensions = ["ext/extconf.rb"]
|
data/ext/track.c
CHANGED
@@ -69,6 +69,15 @@ static VALUE track_frame_count(VALUE obj)
|
|
69
69
|
return INT2NUM(GetMediaSampleCount(TRACK_MEDIA(obj)));
|
70
70
|
}
|
71
71
|
|
72
|
+
/* helper function, returns media type of the track
|
73
|
+
*/
|
74
|
+
static OSType track_get_media_type(VALUE obj)
|
75
|
+
{
|
76
|
+
OSType media_type;
|
77
|
+
GetMediaHandlerDescription(TRACK_MEDIA(obj), &media_type, 0, 0);
|
78
|
+
return media_type;
|
79
|
+
}
|
80
|
+
|
72
81
|
/*
|
73
82
|
call-seq: media_type() -> media_type_sym
|
74
83
|
|
@@ -76,9 +85,8 @@ static VALUE track_frame_count(VALUE obj)
|
|
76
85
|
*/
|
77
86
|
static VALUE track_media_type(VALUE obj)
|
78
87
|
{
|
79
|
-
OSType media_type;
|
88
|
+
OSType media_type = track_get_media_type(obj);
|
80
89
|
|
81
|
-
GetMediaHandlerDescription(TRACK_MEDIA(obj), &media_type, 0, 0);
|
82
90
|
if (media_type == SoundMediaType) {
|
83
91
|
return ID2SYM(rb_intern("audio"));
|
84
92
|
} else if (media_type == VideoMediaType) {
|
@@ -95,13 +103,10 @@ static VALUE track_media_type(VALUE obj)
|
|
95
103
|
*/
|
96
104
|
static ImageDescriptionHandle track_image_description(VALUE obj)
|
97
105
|
{
|
98
|
-
|
99
|
-
OSType media_type;
|
100
|
-
OSErr osErr = noErr;
|
106
|
+
OSErr osErr;
|
101
107
|
|
102
108
|
/* restrict reporting to video track */
|
103
|
-
|
104
|
-
if (media_type != VideoMediaType)
|
109
|
+
if (track_get_media_type(obj) != VideoMediaType)
|
105
110
|
return NULL;
|
106
111
|
|
107
112
|
SampleDescriptionHandle sample_description = NULL;
|
@@ -111,7 +116,7 @@ static ImageDescriptionHandle track_image_description(VALUE obj)
|
|
111
116
|
return NULL;
|
112
117
|
}
|
113
118
|
|
114
|
-
GetMediaSampleDescription(
|
119
|
+
GetMediaSampleDescription(TRACK_MEDIA(obj), 1, sample_description);
|
115
120
|
osErr = GetMoviesError();
|
116
121
|
if (osErr != noErr) {
|
117
122
|
rb_raise(eQuickTime, "Movie Error %d when determining image description", osErr);
|
@@ -263,39 +268,6 @@ static VALUE track_set_volume(VALUE obj, VALUE volume_obj)
|
|
263
268
|
return Qnil;
|
264
269
|
}
|
265
270
|
|
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
271
|
/*
|
300
272
|
call-seq: offset() -> seconds
|
301
273
|
|
@@ -359,6 +331,171 @@ static VALUE track_new_text_media(VALUE obj)
|
|
359
331
|
return obj;
|
360
332
|
}
|
361
333
|
|
334
|
+
/* helper function to return the channel layouts
|
335
|
+
returns layout == NULL if there is a problem
|
336
|
+
*/
|
337
|
+
static AudioChannelLayout* track_get_audio_channel_layout(VALUE obj)
|
338
|
+
{
|
339
|
+
/* restrict reporting to audio track */
|
340
|
+
if (track_get_media_type(obj) != SoundMediaType) return NULL;
|
341
|
+
|
342
|
+
UInt32 size = 0;
|
343
|
+
OSErr osErr;
|
344
|
+
AudioChannelLayout* layout = NULL;
|
345
|
+
|
346
|
+
osErr = QTGetTrackPropertyInfo(TRACK(obj), kQTPropertyClass_Audio, kQTAudioPropertyID_ChannelLayout, NULL, &size, NULL);
|
347
|
+
if (osErr != noErr || size <= 0) goto bail;
|
348
|
+
|
349
|
+
layout = (AudioChannelLayout*)calloc(1, size);
|
350
|
+
if (layout == NULL) {
|
351
|
+
osErr = memFullErr;
|
352
|
+
goto bail;
|
353
|
+
}
|
354
|
+
|
355
|
+
osErr = QTGetTrackProperty(TRACK(obj), kQTPropertyClass_Audio, kQTAudioPropertyID_ChannelLayout, size, layout, NULL);
|
356
|
+
if (osErr != noErr) goto bail;
|
357
|
+
|
358
|
+
return layout;
|
359
|
+
|
360
|
+
/* clean up in the event of an error*/
|
361
|
+
bail:
|
362
|
+
rb_raise(eQuickTime, "Error %d when getting audio channel layout", osErr);
|
363
|
+
free(layout);
|
364
|
+
return NULL;
|
365
|
+
}
|
366
|
+
|
367
|
+
/*
|
368
|
+
call-seq: track_get_audio_channel_count() -> number_of_channels
|
369
|
+
*/
|
370
|
+
static VALUE track_get_audio_channel_count(VALUE obj)
|
371
|
+
{
|
372
|
+
AudioChannelLayout *layout = track_get_audio_channel_layout(obj);
|
373
|
+
if (layout == NULL) return Qnil;
|
374
|
+
|
375
|
+
UInt32 numChannels = (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) ? layout->mNumberChannelDescriptions : AudioChannelLayoutTag_GetNumberOfChannels(layout->mChannelLayoutTag);
|
376
|
+
|
377
|
+
free(layout);
|
378
|
+
|
379
|
+
return INT2NUM(numChannels);
|
380
|
+
}
|
381
|
+
|
382
|
+
// add a channel hash with a given value(v)
|
383
|
+
#define ADD_CHANNEL(ary, c, v) c=rb_hash_new(); rb_ary_push(ary, c); rb_hash_aset(c, ID2SYM(rb_intern("assignment")), ID2SYM(rb_intern(v)))
|
384
|
+
|
385
|
+
static char* track_str_for_AudioChannelLabel(label) {
|
386
|
+
|
387
|
+
char *trackStr = NULL;
|
388
|
+
|
389
|
+
switch (label) {
|
390
|
+
|
391
|
+
case kAudioChannelLabel_Left:
|
392
|
+
trackStr = "left";
|
393
|
+
break;
|
394
|
+
case kAudioChannelLabel_Right:
|
395
|
+
trackStr = "right";
|
396
|
+
break;
|
397
|
+
case kAudioChannelLabel_Center:
|
398
|
+
trackStr = "center";
|
399
|
+
break;
|
400
|
+
case kAudioChannelLabel_LFEScreen:
|
401
|
+
trackStr = "LFEScreen";
|
402
|
+
break;
|
403
|
+
case kAudioChannelLabel_LeftSurround:
|
404
|
+
trackStr = "leftSurround";
|
405
|
+
break;
|
406
|
+
case kAudioChannelLabel_RightSurround:
|
407
|
+
trackStr = "rightSurround";
|
408
|
+
break;
|
409
|
+
case kAudioChannelLabel_LeftCenter:
|
410
|
+
trackStr = "leftCenter";
|
411
|
+
break;
|
412
|
+
case kAudioChannelLabel_RightCenter:
|
413
|
+
trackStr = "rightCenter";
|
414
|
+
break;
|
415
|
+
case kAudioChannelLabel_CenterSurround:
|
416
|
+
trackStr = "centerSurround";
|
417
|
+
break;
|
418
|
+
case kAudioChannelLabel_LeftSurroundDirect:
|
419
|
+
trackStr = "leftSurroundDirect";
|
420
|
+
break;
|
421
|
+
case kAudioChannelLabel_RightSurroundDirect:
|
422
|
+
trackStr = "rightSurroundDirect";
|
423
|
+
break;
|
424
|
+
case kAudioChannelLabel_TopCenterSurround:
|
425
|
+
trackStr = "topCenterSurround";
|
426
|
+
break;
|
427
|
+
|
428
|
+
default:
|
429
|
+
rb_raise(eQuickTime, "Not Implemented: AudioChannelLabel in track_get_audio_channel_map : %d", label);
|
430
|
+
break;
|
431
|
+
}
|
432
|
+
|
433
|
+
return trackStr;
|
434
|
+
}
|
435
|
+
|
436
|
+
static VALUE track_get_audio_channel_map(VALUE obj)
|
437
|
+
{
|
438
|
+
AudioChannelLayout *layout = track_get_audio_channel_layout(obj);
|
439
|
+
if (layout == NULL) return Qnil;
|
440
|
+
|
441
|
+
VALUE channels = Qnil;
|
442
|
+
UInt32 numChannels, x;
|
443
|
+
VALUE channel;
|
444
|
+
AudioChannelLayoutTag layoutTag = layout->mChannelLayoutTag;
|
445
|
+
|
446
|
+
if (layoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
|
447
|
+
// using the descriptions
|
448
|
+
// not implemented
|
449
|
+
numChannels = layout->mNumberChannelDescriptions;
|
450
|
+
channels = rb_ary_new2(numChannels);
|
451
|
+
|
452
|
+
// loop through all channels, adding assignment descriptions
|
453
|
+
AudioChannelDescription desc;
|
454
|
+
char *trackStr;
|
455
|
+
for (x=0; x < numChannels; x++) {
|
456
|
+
desc = layout->mChannelDescriptions[x];
|
457
|
+
trackStr = track_str_for_AudioChannelLabel(desc.mChannelLabel);
|
458
|
+
ADD_CHANNEL(channels, channel, trackStr);
|
459
|
+
}
|
460
|
+
|
461
|
+
|
462
|
+
} else {
|
463
|
+
numChannels = AudioChannelLayoutTag_GetNumberOfChannels(layoutTag);
|
464
|
+
channels = rb_ary_new2(numChannels);
|
465
|
+
|
466
|
+
if (layoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
|
467
|
+
// use the bitmap approach
|
468
|
+
// not implemented
|
469
|
+
rb_raise(eQuickTime, "Not Implemented: kAudioChannelLayoutTag_UseChannelBitmap in track_get_audio_channel_map");
|
470
|
+
|
471
|
+
|
472
|
+
} else {
|
473
|
+
// using a standard LayoutTag
|
474
|
+
switch (layoutTag) {
|
475
|
+
|
476
|
+
case kAudioChannelLayoutTag_Mono:
|
477
|
+
ADD_CHANNEL(channels, channel, "mono");
|
478
|
+
break;
|
479
|
+
|
480
|
+
case kAudioChannelLayoutTag_Stereo:
|
481
|
+
ADD_CHANNEL(channels, channel, "left");
|
482
|
+
ADD_CHANNEL(channels, channel, "right");
|
483
|
+
break;
|
484
|
+
|
485
|
+
default:
|
486
|
+
// unsupported
|
487
|
+
rb_raise(eQuickTime, "Unsupported ChannelLayoutTag in track_get_audio_channel_map: %d", layoutTag);
|
488
|
+
break;
|
489
|
+
}
|
490
|
+
|
491
|
+
}
|
492
|
+
|
493
|
+
}
|
494
|
+
|
495
|
+
free(layout);
|
496
|
+
|
497
|
+
return channels;
|
498
|
+
}
|
362
499
|
|
363
500
|
void Init_quicktime_track()
|
364
501
|
{
|
@@ -375,6 +512,8 @@ void Init_quicktime_track()
|
|
375
512
|
rb_define_method(cTrack, "codec", track_codec, 0);
|
376
513
|
rb_define_method(cTrack, "width", track_width, 0);
|
377
514
|
rb_define_method(cTrack, "height", track_height, 0);
|
515
|
+
rb_define_method(cTrack, "channel_count", track_get_audio_channel_count, 0);
|
516
|
+
rb_define_method(cTrack, "channel_map", track_get_audio_channel_map, 0);
|
378
517
|
|
379
518
|
rb_define_method(cTrack, "id", track_id, 0);
|
380
519
|
rb_define_method(cTrack, "delete", track_delete, 0);
|
data/rmov.gemspec
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{rmov}
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.2"
|
6
6
|
|
7
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-
|
10
|
-
s.description = %q{Ruby wrapper for the QuickTime C API.}
|
8
|
+
s.authors = ["Ryan Bates, with updates by 1K Studios, LLC"]
|
9
|
+
s.date = %q{2009-02-27}
|
10
|
+
s.description = %q{Ruby wrapper for the QuickTime C API. Updates by 1K include exposing some movie properties such as codec and audio channel descriptions}
|
11
11
|
s.email = %q{ryan (at) railscasts (dot) com}
|
12
12
|
s.extensions = ["ext/extconf.rb"]
|
13
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"]
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: one-k-rmov
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Ryan Bates
|
7
|
+
- Ryan Bates, with updates by 1K Studios, LLC
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-27 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description: Ruby wrapper for the QuickTime C API.
|
16
|
+
description: Ruby wrapper for the QuickTime C API. Updates by 1K include exposing some movie properties such as codec and audio channel descriptions
|
17
17
|
email: ryan (at) railscasts (dot) com
|
18
18
|
executables: []
|
19
19
|
|