Search code examples
iosswiftmpmovieplayercontroller

How to play the next youtube video in a playlist using XCDYouTubeKit for Swift?


I'm using XCDYouTubeKit, written as a subclass of MPMoviePlayerViewController.

I'm having an issue playing the next video in my playlist. When I tap the forward button, the state of the player is stopped, and I'm not sure how to resume it?

Here's my code:

override func viewDidLoad()
{
    super.viewDidLoad()

    youtubeVideoPlayer = XCDYouTubeVideoPlayerViewController(videoIdentifier: videoID)

    self.view.addSubview( (youtubeVideoPlayer?.view)! )

    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "moviePlayerNowPlayingMovieDidChange:",
        name: MPMoviePlayerNowPlayingMovieDidChangeNotification,
        object: youtubeVideoPlayer?.moviePlayer)

    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "moviePlayerLoadStateDidChange:",
        name: MPMoviePlayerLoadStateDidChangeNotification,
        object: youtubeVideoPlayer?.moviePlayer)

    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "moviePlayerPlaybackDidChange:",
        name: MPMoviePlayerPlaybackStateDidChangeNotification,
        object: youtubeVideoPlayer?.moviePlayer)

    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "moviePlayerPlayBackDidFinish:",
        name: MPMoviePlayerPlaybackDidFinishNotification,
        object: youtubeVideoPlayer?.moviePlayer)
}

func moviePlayerPlayBackDidFinish(notification: NSNotification)
{
    print("moviePlayerPlayBackDidFinish")
    youtubeVideoPlayer!.view.removeFromSuperview()

    self.dismissViewControllerAnimated(true, completion: nil);
}

func moviePlayerNowPlayingMovieDidChange(notification: NSNotification)
{
    print("moviePlayerNowPlayingMovieDidChange")
}

func moviePlayerLoadStateDidChange(notification: NSNotification)
{
    print("moviePlayerLoadStateDidChange")
    youtubeVideoPlayer?.moviePlayer.play()

    let state: MPMoviePlaybackState = (youtubeVideoPlayer?.moviePlayer.playbackState)!

    switch state
    {
    case MPMoviePlaybackState.Stopped:
        print("stopped")
        break

    case MPMoviePlaybackState.Interrupted:
        print("interrupted")
        break

    case MPMoviePlaybackState.SeekingForward:
        print("forward")
        break

    case MPMoviePlaybackState.SeekingBackward:
        print("backward")
        break

    case MPMoviePlaybackState.Paused:
        print("paused")
        break

    case MPMoviePlaybackState.Playing:
        print("playing")
        break
    }   
}

func moviePlayerPlaybackDidChange(notification: NSNotification)
{
    print("moviePlayerPlaybackDidChange")

    let state: MPMoviePlaybackState = (youtubeVideoPlayer?.moviePlayer.playbackState)!

    switch state
    {
        case MPMoviePlaybackState.Stopped:
        print("stopped")
        videoIDIndex = videoIDIndex + 1
        playNextVideo()
        break

        case MPMoviePlaybackState.Interrupted:
        print("interrupted")
        break

        case MPMoviePlaybackState.SeekingForward:
        print("forward")
        break

        case MPMoviePlaybackState.SeekingBackward:
        print("backward")
        break

        case MPMoviePlaybackState.Paused:
        print("paused")
        break

        case MPMoviePlaybackState.Playing:
        print("playing")
        break
    }
}

func playNextVideo()
{
    if segueIdentifer == "SegueFromPlaylistVideos"
    {
        print("Playlist")
        NSNotificationCenter.defaultCenter().removeObserver(
            self,
            name: MPMoviePlayerPlaybackDidFinishNotification,
            object: youtubeVideoPlayer?.moviePlayer
        )

        print("videoIDs_ARRAY = \(videoIDs_ARRAY)")
        print("videoIDs_ARRAY[videoIDIndex] = \( (videoIDs_ARRAY[videoIDIndex] as String) )")

        youtubeVideoPlayer?.videoIdentifier = videoIDs_ARRAY[videoIDIndex] as String
    }
}

The sequence are as follows when the first video is played in the playlist, and I tap the forward to move to the next video:

moviePlayerNowPlayingMovieDidChange

moviePlayerLoadStateDidChange

moviePlayerPlaybackDidChange

playing

playing

moviePlayerLoadStateDidChange

playing

moviePlayerPlaybackDidChange

stopped

Playlist

videoIDs_ARRAY = ["NztC0z1JNq0", "uqRBijuCZd8"]

videoIDs_ARRAY[videoIDIndex] = uqRBijuCZd8

moviePlayerLoadStateDidChange

stopped

As you can see at the end, the state of the player is stopped.

I'm not sure how to resume it so it will play the next video. I've tried to add youtubeVideoPlayer?.moviePlayer.play() within moviePlayerLoadStateDidChange but the player does not resume playing.

Any thoughts on this?

Thanks


Solution

  • I don't know syntax in Swift so please translate objective-c to swift 
    
    I have 2 solutions for you problem :- 
    
        1. You can stop current playing video syntax in objective-c like 
        [self.youtubeVideoPlayer.moviePlayer stop]; 
        and then you can set new video 
    
        self.youtubeVideoPlayer.videoIdentifier=videoIdentifier;
                self.youtubeVideoPlayer.moviePlayer.shouldAutoplay=TRUE;
                [self.youtubeVideoPlayer presentInView:self.playerView];
                [self.youtubeVideoPlayer.moviePlayer prepareToPlay];
                self.youtubeVideoPlayer.moviePlayer.shouldAutoplay=TRUE;
    
         2. You can do like this 
        set nil to your XCDYouTubeVideoPlayerViewController reference and set it again 
    
        self.youtubeVideoPlayer = nil;
        self.youtubeVideoPlayer = [[XCDYouTubeVideoPlayerViewController alloc] init];
                self.youtubeVideoPlayer.moviePlayer.shouldAutoplay=TRUE;
                self.youtubeVideoPlayer.moviePlayer.controlStyle= MPMovieControlStyleNone;
                self.youtubeVideoPlayer.moviePlayer.scalingMode = MPMovieScalingModeFill;
    
         and then you can set new video 
    
        self.youtubeVideoPlayer.videoIdentifier=videoIdentifier;
                self.youtubeVideoPlayer.moviePlayer.shouldAutoplay=TRUE;
                [self.youtubeVideoPlayer presentInView:self.playerView];
                [self.youtubeVideoPlayer.moviePlayer prepareToPlay];
                self.youtubeVideoPlayer.moviePlayer.shouldAutoplay=TRUE;
    
    Example: -
    #import "ViewController.h"
    
    #import "XCDYouTubeVideoPlayerViewController.h"
    
    @interface ViewController ()
    {
        NSArray *urlArray;
        int arrindex;
    }
    @property (weak, nonatomic) IBOutlet UIView *playerView;
    @property (nonatomic, strong) XCDYouTubeVideoPlayerViewController *videoPlayerViewController;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        urlArray = [[NSArray alloc] initWithObjects:@"zVyEPNIR-yk",@"r5RXlY3at-E",@"sUFKakydp2c",@"1xvLHxFUwIk", nil];
        arrindex = 0;
        NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
        [defaultCenter addObserver:self selector:@selector(moviePlayerPlaybackStateDidChange1:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
        [defaultCenter addObserver:self selector:@selector(moviePlayerLoadStateDidChange1:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
        [self setVideo];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    - (void)setVideo
    {
        self.videoPlayerViewController = [[XCDYouTubeVideoPlayerViewController alloc] init];
        self.videoPlayerViewController.moviePlayer.shouldAutoplay=TRUE;
        self.videoPlayerViewController.moviePlayer.controlStyle= MPMovieControlStyleNone;
        self.videoPlayerViewController.moviePlayer.scalingMode = MPMovieScalingModeFill;
    
        [self.playerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    
        NSString *videoIdentifier =[urlArray objectAtIndex:arrindex];
        self.videoPlayerViewController.videoIdentifier=videoIdentifier;
    
        self.videoPlayerViewController.moviePlayer.shouldAutoplay=TRUE;
        [self.videoPlayerViewController presentInView:self.playerView];
        [self.videoPlayerViewController.moviePlayer prepareToPlay];
        self.videoPlayerViewController.moviePlayer.shouldAutoplay=TRUE;
    }
    - (IBAction)Next:(id)sender {
            arrindex++;
        if (arrindex<urlArray.count) {
            self.videoPlayerViewController=nil;
            [self setVideo];
        }
    }
    - (void) moviePlayerLoadStateDidChange1:(NSNotification *)notification
    {
        MPMoviePlayerController *moviePlayerController = notification.object;
        MPMovieLoadState state = moviePlayerController.loadState;
        if (state & MPMovieLoadStatePlayable)
        {
            [self.videoPlayerViewController.moviePlayer play];
        }
        else if (state & MPMovieLoadStatePlaythroughOK)
        {
        }
        else if (state & MPMovieLoadStateStalled)
        {
        }
    }
    
    - (void) moviePlayerPlaybackStateDidChange1:(NSNotification *)notification
    {
        long reason=(long)self.videoPlayerViewController.moviePlayer.playbackState;
        if (reason==0)
        {
            NSLog(@"I'm Not Playing");
        }
        else if (reason==1)
        {
            NSLog(@"I'm Playingggggggggggggggg");
        }
        else if (reason ==2)
        {
            NSLog(@"pause....................................");
        }
        else if (reason ==3)
        {
            //NSLog(@"Interrupteddddddddddddddddd");
        }
        else if (reason ==4)
        {
            //NSLog(@"Seeking Forward");
        }
        else if (reason ==5)
        {
            //NSLog(@"Seeking Backward");
        }
    }
    
    @end
    
    I hope this helps you.