1 #import "VideoViewController.h"
2 #import "GStreamerBackend.h"
3 #import <UIKit/UIKit.h>
5 @interface VideoViewController () {
6 GStreamerBackend *gst_backend;
7 NSInteger media_width; /* Width of the clip */
8 NSInteger media_height; /* height ofthe clip */
9 Boolean dragging_slider; /* Whether the time slider is being dragged or not */
10 Boolean is_local_media; /* Whether this clip is stored locally or is being streamed */
11 Boolean is_playing_desired; /* Whether the user asked to go to PLAYING */
16 @implementation VideoViewController
24 /* The text widget acts as an slave for the seek bar, so it reflects what the seek bar shows, whether
25 * it is an actual pipeline position or the position the user is currently dragging to. */
26 - (void) updateTimeWidget
28 NSInteger position = time_slider.value / 1000;
29 NSInteger duration = time_slider.maximumValue / 1000;
30 NSString *position_txt = @" -- ";
31 NSString *duration_txt = @" -- ";
34 NSUInteger hours = duration / (60 * 60);
35 NSUInteger minutes = (duration / 60) % 60;
36 NSUInteger seconds = duration % 60;
38 duration_txt = [NSString stringWithFormat:@"%02lu:%02lu:%02lu", (unsigned long)hours, (unsigned long)minutes, (unsigned long)seconds];
41 NSUInteger hours = position / (60 * 60);
42 NSUInteger minutes = (position / 60) % 60;
43 NSUInteger seconds = position % 60;
45 position_txt = [NSString stringWithFormat:@"%02lu:%02lu:%02lu", (unsigned long)hours, (unsigned long)minutes, (unsigned long)seconds];
48 NSString *text = [NSString stringWithFormat:@"%@ / %@",
49 position_txt, duration_txt];
51 time_label.text = text;
55 * Methods from UIViewController
62 play_button.enabled = FALSE;
63 pause_button.enabled = FALSE;
65 /* As soon as the GStreamer backend knows the real values, these ones will be replaced */
69 gst_backend = [[GStreamerBackend alloc] init:self videoView:video_view];
72 - (void)viewDidDisappear:(BOOL)animated
78 [UIApplication sharedApplication].idleTimerDisabled = NO;
81 - (void)didReceiveMemoryWarning
83 [super didReceiveMemoryWarning];
84 // Dispose of any resources that can be recreated.
87 /* Called when the Play button is pressed */
88 -(IBAction) play:(id)sender
91 is_playing_desired = YES;
92 [UIApplication sharedApplication].idleTimerDisabled = YES;
95 /* Called when the Pause button is pressed */
96 -(IBAction) pause:(id)sender
99 is_playing_desired = NO;
100 [UIApplication sharedApplication].idleTimerDisabled = NO;
103 /* Called when the time slider position has changed, either because the user dragged it or
104 * we programmatically changed its position. dragging_slider tells us which one happened */
105 - (IBAction)sliderValueChanged:(id)sender {
106 if (!dragging_slider) return;
107 // If this is a local file, allow scrub seeking, this is, seek as soon as the slider is moved.
109 [gst_backend setPosition:time_slider.value];
110 [self updateTimeWidget];
113 /* Called when the user starts to drag the time slider */
114 - (IBAction)sliderTouchDown:(id)sender {
116 dragging_slider = YES;
119 /* Called when the user stops dragging the time slider */
120 - (IBAction)sliderTouchUp:(id)sender {
121 dragging_slider = NO;
122 // If this is a remote file, scrub seeking is probably not going to work smoothly enough.
123 // Therefore, perform only the seek when the slider is released.
125 [gst_backend setPosition:time_slider.value];
126 if (is_playing_desired)
130 /* Called when the size of the main view has changed, so we can
131 * resize the sub-views in ways not allowed by storyboarding. */
132 - (void)viewDidLayoutSubviews
134 CGFloat view_width = video_container_view.bounds.size.width;
135 CGFloat view_height = video_container_view.bounds.size.height;
137 CGFloat correct_height = view_width * media_height / media_width;
138 CGFloat correct_width = view_height * media_width / media_height;
140 if (correct_height < view_height) {
141 video_height_constraint.constant = correct_height;
142 video_width_constraint.constant = view_width;
144 video_width_constraint.constant = correct_width;
145 video_height_constraint.constant = view_height;
148 time_slider.frame = CGRectMake(time_slider.frame.origin.x, time_slider.frame.origin.y, toolbar.frame.size.width - time_slider.frame.origin.x - 8, time_slider.frame.size.height);
152 * Methods from GstreamerBackendDelegate
155 -(void) gstreamerInitialized
157 dispatch_async(dispatch_get_main_queue(), ^{
158 play_button.enabled = TRUE;
159 pause_button.enabled = TRUE;
160 message_label.text = @"Ready";
161 [gst_backend setUri:uri];
162 is_local_media = [uri hasPrefix:@"file://"];
163 is_playing_desired = NO;
167 -(void) gstreamerSetUIMessage:(NSString *)message
169 dispatch_async(dispatch_get_main_queue(), ^{
170 message_label.text = message;
174 -(void) mediaSizeChanged:(NSInteger)width height:(NSInteger)height
177 media_height = height;
178 dispatch_async(dispatch_get_main_queue(), ^{
179 [self viewDidLayoutSubviews];
180 [video_view setNeedsLayout];
181 [video_view layoutIfNeeded];
185 -(void) setCurrentPosition:(NSInteger)position duration:(NSInteger)duration
187 /* Ignore messages from the pipeline if the time sliders is being dragged */
188 if (dragging_slider) return;
190 dispatch_async(dispatch_get_main_queue(), ^{
191 time_slider.maximumValue = duration;
192 time_slider.value = position;
193 [self updateTimeWidget];