diff options
Diffstat (limited to 'Video Tuneup')
| -rw-r--r-- | Video Tuneup/ViewController.h | 14 | ||||
| -rw-r--r-- | Video Tuneup/ViewController.m | 168 | ||||
| -rw-r--r-- | Video Tuneup/en.lproj/ViewController_iPad.xib | 58 |
3 files changed, 230 insertions, 10 deletions
diff --git a/Video Tuneup/ViewController.h b/Video Tuneup/ViewController.h index 99a7a1b..8c84b4f 100644 --- a/Video Tuneup/ViewController.h +++ b/Video Tuneup/ViewController.h @@ -16,6 +16,11 @@ @interface ViewController : UIViewController { AVURLAsset *asset; AVURLAsset *songAsset; + + // Related to scrubbing + float mRestoreAfterScrubbingRate; + BOOL seekToZeroBeforePlay; + id mTimeObserver; } @property (nonatomic, retain) AVPlayer *player; @@ -27,6 +32,8 @@ @property (nonatomic, retain) IBOutlet UIButton *rewindButton; @property (nonatomic, retain) IBOutlet UIToolbar *videoNavBar; @property (nonatomic, retain) IBOutlet UILabel *exportStatus; +@property (nonatomic, retain) IBOutlet UISlider* mScrubber; + - (void)hideCameraRollText; - (IBAction)loadAssetFromFile:sender; @@ -36,6 +43,13 @@ - (IBAction)rewind:sender; - (IBAction)exportToCameraRoll:sender; - (void)syncUI; +- (void)syncScrubber; +- (void)beginScrubbing:(id)sender; +- (void)scrub:(id)sender; +- (void)endScrubbing:(id)sender; +- (BOOL)isScrubbing; +- (void)initScrubberTimer; +- (CMTime)playerItemDuration; - (void)exportDidFinish:(AVAssetExportSession*)session; @end
\ No newline at end of file diff --git a/Video Tuneup/ViewController.m b/Video Tuneup/ViewController.m index 4fc5a99..83a82a9 100644 --- a/Video Tuneup/ViewController.m +++ b/Video Tuneup/ViewController.m @@ -15,7 +15,8 @@ static const NSString *ItemStatusContext; @implementation ViewController -@synthesize player, playerItem, playerView, playButton, pauseButton, rewindButton, editor, videoNavBar, exportStatus; +@synthesize player, playerItem, playerView, playButton, pauseButton, rewindButton, editor, videoNavBar, exportStatus, +mScrubber; #pragma mark - Video playback @@ -26,6 +27,7 @@ static const NSString *ItemStatusContext; ([player.currentItem status] == AVPlayerItemStatusReadyToPlay && CMTimeCompare([player.currentItem duration], kCMTimeZero) != 0)) { playButton.enabled = YES; + NSLog(@"Enabling play button"); } else { @@ -35,13 +37,18 @@ static const NSString *ItemStatusContext; } - (void)refreshEditor { - // Update assets + NSLog(@"Refreshing editor"); + + // Update editor assets if (asset) self.editor.video = asset; if (songAsset) self.editor.song = songAsset; - // Begin export + // Remove old player + [self.player pause]; + + // Build composition for playback [self.editor buildNewCompositionForPlayback:YES]; // Initialize editor's player @@ -127,18 +134,20 @@ static const NSString *ItemStatusContext; CMTimeCompare([player.currentItem duration], kCMTimeZero) != 0)) { // Paused NSLog(@"Playing item"); [player play]; + [self initScrubberTimer]; [self.videoNavBar setItems:[NSArray arrayWithObjects:[self.videoNavBar.items objectAtIndex:0], [self.videoNavBar.items objectAtIndex:1], [self.videoNavBar.items objectAtIndex:2], - [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPause target:self action:@selector(play:)],nil] animated:NO]; + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPause target:self action:@selector(play:)],[self.videoNavBar.items objectAtIndex:4],[self.videoNavBar.items objectAtIndex:5],nil] animated:NO]; } else { [player pause]; [self.videoNavBar setItems:[NSArray arrayWithObjects:[self.videoNavBar.items objectAtIndex:0], [self.videoNavBar.items objectAtIndex:1], [self.videoNavBar.items objectAtIndex:2], - [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(play:)],nil] animated:NO]; + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(play:)],[self.videoNavBar.items objectAtIndex:4], + [self.videoNavBar.items objectAtIndex:5], nil] animated:NO]; } } @@ -152,6 +161,154 @@ static const NSString *ItemStatusContext; [player seekToTime:kCMTimeZero]; } + +// Handle scrubbing +// Based on sample code from http://developer.apple.com/library/ios/#samplecode/AVPlayerDemo/Listings/Classes_AVPlayerDemoPlaybackViewController_m.html#//apple_ref/doc/uid/DTS40010101-Classes_AVPlayerDemoPlaybackViewController_m-DontLinkElementID_8 + +#pragma mark - +#pragma mark Movie scrubber control + +/* --------------------------------------------------------- + ** Methods to handle manipulation of the movie scrubber control + ** ------------------------------------------------------- */ + +- (CMTime)playerItemDuration +{ + return [playerItem duration]; +} + +/* Requests invocation of a given block during media playback to update the movie scrubber control. */ +-(void)initScrubberTimer +{ + double interval = .1f; + + CMTime playerDuration = [self playerItemDuration]; + if (CMTIME_IS_INVALID(playerDuration)) + { + return; + } + double duration = CMTimeGetSeconds(playerDuration); + if (isfinite(duration)) + { + CGFloat width = CGRectGetWidth([mScrubber bounds]); + interval = 0.5f * duration / width; + } + + /* Update the scrubber during normal playback. */ + mTimeObserver = [player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC) + queue:NULL /* If you pass NULL, the main queue is used. */ + usingBlock:^(CMTime time) + { + [self syncScrubber]; + }]; + +} + +/* Set the scrubber based on the player current time. */ +- (void)syncScrubber +{ + CMTime playerDuration = [self playerItemDuration]; + if (CMTIME_IS_INVALID(playerDuration)) + { + mScrubber.minimumValue = 0.0; + return; + } + + double duration = CMTimeGetSeconds(playerDuration); + if (isfinite(duration)) + { + float minValue = [mScrubber minimumValue]; + float maxValue = [mScrubber maximumValue]; + double time = CMTimeGetSeconds([player currentTime]); + + [mScrubber setValue:(maxValue - minValue) * time / duration + minValue]; + } +} + +/* The user is dragging the movie controller thumb to scrub through the movie. */ +- (IBAction)beginScrubbing:(id)sender +{ + mRestoreAfterScrubbingRate = [player rate]; + [player setRate:0.f]; + + /* Remove previous timer. */ +// [self removePlayerTimeObserver]; +} + +/* Set the player current time to match the scrubber position. */ +- (IBAction)scrub:(id)sender +{ + if ([sender isKindOfClass:[UISlider class]]) + { + UISlider* slider = sender; + + CMTime playerDuration = [self playerItemDuration]; + if (CMTIME_IS_INVALID(playerDuration)) { + return; + } + + double duration = CMTimeGetSeconds(playerDuration); + if (isfinite(duration)) + { + float minValue = [slider minimumValue]; + float maxValue = [slider maximumValue]; + float value = [slider value]; + + double time = duration * (value - minValue) / (maxValue - minValue); + + [player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)]; + } + } +} + +/* The user has released the movie thumb control to stop scrubbing through the movie. */ +- (IBAction)endScrubbing:(id)sender +{ + if (!mTimeObserver) + { + CMTime playerDuration = [self playerItemDuration]; + if (CMTIME_IS_INVALID(playerDuration)) + { + return; + } + + double duration = CMTimeGetSeconds(playerDuration); + if (isfinite(duration)) + { + CGFloat width = CGRectGetWidth([mScrubber bounds]); + double tolerance = 0.5f * duration / width; + + mTimeObserver = [player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(tolerance, NSEC_PER_SEC) queue:NULL usingBlock: + ^(CMTime time) + { + [self syncScrubber]; + }]; + } + } + + if (mRestoreAfterScrubbingRate) + { + [player setRate:mRestoreAfterScrubbingRate]; + mRestoreAfterScrubbingRate = 0.f; + } +} + +- (BOOL)isScrubbing +{ + return mRestoreAfterScrubbingRate != 0.f; +} + +-(void)enableScrubber +{ + self.mScrubber.enabled = YES; +} + +-(void)disableScrubber +{ + self.mScrubber.enabled = NO; +} + + - (IBAction)exportToCameraRoll:(id)sender { NSLog(@"Editing..."); @@ -238,6 +395,7 @@ static const NSString *ItemStatusContext; - (void)playerItemDidReachEnd:(NSNotification *)notification { [player seekToTime:kCMTimeZero]; + [player play]; // loop player. If not doing this, set button to pause } diff --git a/Video Tuneup/en.lproj/ViewController_iPad.xib b/Video Tuneup/en.lproj/ViewController_iPad.xib index bcd19c2..d4cece4 100644 --- a/Video Tuneup/en.lproj/ViewController_iPad.xib +++ b/Video Tuneup/en.lproj/ViewController_iPad.xib @@ -2,10 +2,10 @@ <archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00"> <data> <int key="IBDocument.SystemTarget">1280</int> - <string key="IBDocument.SystemVersion">11C74</string> + <string key="IBDocument.SystemVersion">11D50d</string> <string key="IBDocument.InterfaceBuilderVersion">1938</string> - <string key="IBDocument.AppKitVersion">1138.23</string> - <string key="IBDocument.HIToolboxVersion">567.00</string> + <string key="IBDocument.AppKitVersion">1138.32</string> + <string key="IBDocument.HIToolboxVersion">568.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string key="NS.object.0">933</string> @@ -117,7 +117,6 @@ <string key="targetRuntimeIdentifier">IBIPadFramework</string> <int key="IBUIContentHorizontalAlignment">0</int> <int key="IBUIContentVerticalAlignment">0</int> - <float key="IBUIValue">0.5</float> </object> </array> <string key="NSFrame">{{0, 587}, {671, 44}}</string> @@ -318,6 +317,14 @@ <int key="connectionID">44</int> </object> <object class="IBConnectionRecord"> + <object class="IBCocoaTouchOutletConnection" key="connection"> + <string key="label">mScrubber</string> + <reference key="source" ref="841351856"/> + <reference key="destination" ref="119532371"/> + </object> + <int key="connectionID">51</int> + </object> + <object class="IBConnectionRecord"> <object class="IBCocoaTouchEventConnection" key="connection"> <string key="label">loadAssetFromFile:</string> <reference key="source" ref="1049445720"/> @@ -345,6 +352,42 @@ </object> <object class="IBConnectionRecord"> <object class="IBCocoaTouchEventConnection" key="connection"> + <string key="label">beginScrubbing:</string> + <reference key="source" ref="119532371"/> + <reference key="destination" ref="841351856"/> + <int key="IBEventType">1</int> + </object> + <int key="connectionID">55</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBCocoaTouchEventConnection" key="connection"> + <string key="label">endScrubbing:</string> + <reference key="source" ref="119532371"/> + <reference key="destination" ref="841351856"/> + <int key="IBEventType">7</int> + </object> + <int key="connectionID">56</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBCocoaTouchEventConnection" key="connection"> + <string key="label">endScrubbing:</string> + <reference key="source" ref="119532371"/> + <reference key="destination" ref="841351856"/> + <int key="IBEventType">8</int> + </object> + <int key="connectionID">57</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBCocoaTouchEventConnection" key="connection"> + <string key="label">scrub:</string> + <reference key="source" ref="119532371"/> + <reference key="destination" ref="841351856"/> + <int key="IBEventType">13</int> + </object> + <int key="connectionID">58</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBCocoaTouchEventConnection" key="connection"> <string key="label">exportToCameraRoll:</string> <reference key="source" ref="806269495"/> <reference key="destination" ref="841351856"/> @@ -504,7 +547,7 @@ <nil key="activeLocalization"/> <dictionary class="NSMutableDictionary" key="localizations"/> <nil key="sourceID"/> - <int key="maxID">49</int> + <int key="maxID">58</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <array class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -555,6 +598,7 @@ </dictionary> <dictionary class="NSMutableDictionary" key="outlets"> <string key="exportStatus">UILabel</string> + <string key="mScrubber">UISlider</string> <string key="pauseButton">UIButton</string> <string key="playButton">UIButton</string> <string key="playerView">PlayerView</string> @@ -566,6 +610,10 @@ <string key="name">exportStatus</string> <string key="candidateClassName">UILabel</string> </object> + <object class="IBToOneOutletInfo" key="mScrubber"> + <string key="name">mScrubber</string> + <string key="candidateClassName">UISlider</string> + </object> <object class="IBToOneOutletInfo" key="pauseButton"> <string key="name">pauseButton</string> <string key="candidateClassName">UIButton</string> |
