VLCKit: VLCMediaPlayerDelegate in a Cocoa Application - objective-c

I'm trying to develop a Cocoa Application for Mac OSX 10.10 that implements some video streaming in VLCKit.
Now:
I've compiled the .framework library and I've imported it in Xcode.
I've added a Custom View in my Main.storyboard and set it to a VLCVideoView
In my ViewController.h i've implemented the VLCMediaPlayerDelegate to receive notification from the player
Here's my code:
viewController.h
#import <Cocoa/Cocoa.h>
#import <VLCKit/VLCKit.h>
#interface ViewController : NSViewController<VLCMediaPlayerDelegate>
#property (weak) IBOutlet VLCVideoView *_vlcVideoView;
//delegates
- (void)mediaPlayerTimeChanged:(NSNotification *)aNotification;
#end
viewController.m
#import "ViewController.h"
#implementation ViewController
{
VLCMediaPlayer *player;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[player setDelegate:self];
[self._vlcVideoView setAutoresizingMask: NSViewHeightSizable|NSViewWidthSizable];
self._vlcVideoView.fillScreen = YES;
player = [[VLCMediaPlayer alloc] initWithVideoView:self._vlcVideoView];
NSURL *url = [NSURL URLWithString:#"http://MyRemoteUrl.com/video.mp4"];
VLCMedia *movie = [VLCMedia mediaWithURL:url];
[player setMedia:movie];
[player play];
}
- (void)mediaPlayerTimeChanged:(NSNotification *)aNotification
{
//Here I want to retrieve the current video position.
}
#end
The video start and play correctly. However I can't get the delegate to work.
Where I am wrong?
Here are my questions:
How can I setup the delegate to receive notifications about the current player time?
How can I read the NSNotification? (I'm not really used to Obj-C)
Thank you in advance for any answer!

I've managed it!
How can I setup the delegate to receive notifications about the current player time? I had to add an observer to NSNotificationCenter.
Here's the code:
- (void)viewDidLoad
{
[super viewDidLoad];
[player setDelegate:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(mediaPlayerTimeChanged:) name:VLCMediaPlayerTimeChanged object:nil];
}
How can I read the NSNotification? I had to retrieve the VLCMediaPlayer object inside the notification.
Code:
- (void)mediaPlayerTimeChanged:(NSNotification *)aNotification
{
VLCMediaPlayer *player = [aNotification object];
VLCTime *currentTime = player.time;
}

Related

OS X Delegate set label from other window (Xcode)

I'm quite new to Mac programming (not to Objective C).
I'm developing a small application, that shows some data and opens a second window on button press.
In the second window is a textfield and a submit button. If the submit button is pressed, the window should close + the value of the textfield needs to be passed to the first window.
I think the best method for that is a simple Delegate. I tried that but i can't change the label in the first window using the second window..
The delegate however seems to work as i can call methods from the other class and send data to it. It just won't change the label.
As this is my first try on Delegates, im pretty sure I've done something stupid here^^
or is there a better solution? Can't be to complicated to change a label from an second window.. right?
ViewController.h (FirstController)
#import <Cocoa/Cocoa.h>
#class ViewController;
#protocol ViewControllerDelegate
-(void)sayHello:(ViewController *)ViewController;
#end
#interface ViewController : NSViewController
{
IBOutlet NSTextField *txtlabel;
}
#property (nonatomic, assign) id delegate;
-(void)helloDelegate;
-(void)reciveVar:(NSString*)strvar;
#end
ViewController.m (FirstController)
#import "ViewController.h"
#implementation ViewController
#synthesize delegate;
-(id)init {
self = [super init];
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
txtlabel.stringValue=#"TEST";
}
-(void)helloDelegate
{
[delegate sayHello:self];
}
-(void)reciveVar:(NSString*)strvar
{
NSLog(#"recived: %#", strvar);
txtlabel.stringValue=strvar; // DOSENT WORK!!
}
#end
secondController.h
#import <Cocoa/Cocoa.h>
#import "ViewController.h"
#interface secondController : NSViewController <ViewControllerDelegate>
{
IBOutlet NSTextField *txtfield;
}
-(IBAction)submit:(id)sender;
#end
secondController.m
#import "firstController.h"
#implementation secondController
-(void)viewDidLoad
{
[super viewDidLoad];
ViewController *custom = [[ViewController alloc] init];
// assign delegate
custom.delegate = self;
[custom helloDelegate];
}
-(void)sayHello:(ViewController *)ViewController
{
NSLog(#"Hiya!");
}
-(IBAction)submit:(id)sender
{
NSString *txtval= txtfield.stringValue;
NSLog(#"submit: %#", txtval);
ViewController *custom = [[ViewController alloc] init];
// assign delegate
custom.delegate = self;
[custom reciveVar:txtval];
}
#end
LOG Output:
Hiya!
submit: test
recived: test
(so i guess the delegate works..)
SOLVED. (Thanks to Phillip Mills)
NSNotification is way simpler and efficient than Delegates in this case.
ViewController.m
[...]
- (void)viewDidLoad
{
[super viewDidLoad];
txtlabel.stringValue=#"TEST";
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleUpdatedData:)
name:#"DataUpdated"
object:nil];
}
-(void)handleUpdatedData:(NSNotification *)notification
{
NSLog(#"recieved %#", notification);
txtlabel.stringValue=[notification object];
}
secondController.m
-(IBAction)submit:(id)sender
{
NSString *txtval= txtfield.stringValue;
NSLog(#"submit: %#", txtval);
[[NSNotificationCenter defaultCenter] postNotificationName:#"DataUpdated"
object:txtval];
}

How do I present UIViewController from SKscene with social framework?

I am making a game like Flappy Bird. How do I present a UIViewController from SKScene?
First of all, I tell my environments
Mac OS X 10.9
Xcode 5.0.2
Sprite Kit(framework), social.framework(framework) are added in my project
My goal is to display a "Share" button upon Game Over. Tapping the share button image should present a SLComposeViewController (Twitter Share). The contents of the scene should not change.
I'd like to solve bellow issue and change display from GameOverScene to tweetSheet(display)
composed with social.framework.
The issue
[self presentViewController:tweetSheet animated:YES completion:nil];
//Error:No visible #interface for 'GameOverScene' declares the selector "presentViewController":animated:completion:
My coding files are below(I extracted parts of important codes).
ViewController.h
import <UIKit/UIKit.h>
import <SpriteKit/SpriteKit.h>
import <iAd/iAd.h>
#interface ViewController : UIViewController<ADBannerViewDelegate><br>
#end
GameOverScene.h
#import <SpriteKit/SpriteKit.h>
#class SpriteViewController;
#interface GameOverScene : SKScene {
}
#end
GameOverScene.m
#import "GameOverScene.h"
#import "NewGameScene.h"
#import "MainScene.h"
#import <Social/Social.h>
#implementation GameOverScene {
//The twitter button
SKSpriteNode *_twitterbutton;
}
- (id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size]) {
//Creating the twitterbutton with the twitterbutton image from Images.xcassets
_twitterbutton = [SKSpriteNode spriteNodeWithImageNamed:#"twitterbutton"];
[_twitterbutton setSize:CGSizeMake(50, 50)];
[_twitterbutton setPosition:CGPointMake(self.size.width/2, self.size.height/5 + 50)];
//Adding the twitter button
[self addChild:_twitterbutton];
//Again, this is important, otherwise we can't identify what button is pressed
_twitterbutton.name = #"twitterbutton";
[_twitterbutton setPosition:CGPointMake(self.size.width/2, self.size.height/5 + 50)]
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//Same as in NewGameScene menu
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//Is the twitter button touched?
if([node.name isEqualToString:#"twitterbutton"]){
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]){
SLComposeViewController *tweetSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[tweetSheet setInitialText:#"TestTweet from the Game !!"];
[self presentViewController:tweetSheet animated:YES completion:nil];
**//Error:No visible #interface for 'GameOverScene' declares the selector "presentViewController":animated:completion:**
}
}
ViewControlloer.m
#import "ViewController.h"
#import "NewGameScene.h"
#implementation ViewController
//Loads the view onto our main class
- (void)loadView
{
self.view = [[SKView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
}
//Executes when view finishes loading
- (void)viewWillLayoutSubviews
{
[super viewDidLoad];
//Set the resize mode to flexible width and height
[self.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
//Create our view from our original view
//Make sure to leave originalContentView in, otherwise the app will crash
SKView *skView = (SKView *)self.originalContentView;
//We create a new NewGameScene according to the current dimensions
SKScene *scene = [NewGameScene sceneWithSize:skView.bounds.size];
//Create a transition class with animation type fade and a duration of .4 seconds
SKTransition *transition = [SKTransition fadeWithDuration:.4];
//Present the menu view (NewGameScene) with our fade in transition
[skView presentScene:scene transition:transition];
}
#end
You cannot present a viewController from within a SKScene as it is actually only being rendered on a SKView. You need a way to send a message to the viewController, which in turn will present the viewController. For this, you can use delegation.
Add the following protocol definition to your SKScene's .h file:
#protocol sceneDelegate <NSObject>
-(void)showShareScreen;
#end
And declare a delegate property in the interface:
#property (weak, nonatomic) id <sceneDelegate> delegate;
Then, at the point where you want to present the share screen, instead of the line:
[self presentViewController:tweetSheet animated:YES completion:nil];
Use this line:
[self.delegate showShareScreen];
Now, in your viewController's .h file, implement the protocol:
#interface ViewController : UIViewController <sceneDelegate>
And, in your .m file, add the following line before you present the scene:
scene.delegate = self;
Then add the following method there:
-(void)presentShareScreen
{
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
[tweetSheet setInitialText:#"TestTweet from the Game !!"];
[self presentViewController:tweetSheet animated:YES completion:nil];
}
}
An alternate method would be to use NSNotificationCenter
Keep the -presentShareScreen method as described in the previous alternative.
Add the viewController as a listener to the notification in it's -viewDidLoad method:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(presentShareScreen) name:#"showShareScreen" object:nil];
Then, in the scene at the point where you want to show this viewController, use this line:
[[NSNotificationCenter defaultCenter] postNotificationName:#"showShareScreen" object:nil];

How to call a ViewController.m method from the AppDelegate.m

In my ViewController.m I have my void "Save Data":
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize myDatePicker, myTextField;
-(void)saveData
{
NSArray *value = [[NSArray alloc] initWithObjects:[myTextField text],[myDatePicker date], nil];
[value writeToFile:[self getFilePath] atomically:YES];
}
And I want to use my void "Save Data" in my AppDelegate.m :
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self.ViewController saveData];
}
But Xcode doesn't recognize the "ViewController" neither "saveData".
I don't know if I have to #import something in my AppDelegate, please help.
How you access your viewcontroller from the app delegate will depend on how many viewcontrollers you have / where it is in your current navigation hierarchy, etc etc. You could add a property for it, or perhaps it will be your app delegate's rootViewController.
However, you'd probably be better off listening out for a notification in your viewcontroller when the app enters the background. This means that the logic you need can be entirely self contained within your viewcontroller, and your app delegate doesn't need to know anything about it.
In your viewcontroller's initialization method, you can register to receive notifications:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
Then, implement the method:
- (void)applicationDidEnterBackground:(NSNotification *)notification
{
[self saveData];
}
And make sure you also remove yourself as an observer in your viewcontroller's dealloc method:
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
}
In your "appDelegate.m" implementation file at the top do this import ->
#import "ViewController.h"
This will make the custom class ViewController visible to the appDelegate.
In order to be able to call the -(void)saveData method from another class (in our case the other class is the AppDelegate class), this method needs to be declared in the public interface. That means ->
#import "ViewController.h"
#interface ViewController ()
-(void)saveData;
#end

How to access properties from other view controllers

I am using Xcode 4.6.1 to develop for iOS 6.
I have two view controllers: viewController1 and viewController2. I am trying to access a property defined in viewController1 in viewController2 as follow (but it isn't working):
This is viewController1.m:
#import "viewController1.h"
#interface viewController1 ()
#property (nonatomic) MPMoviePlayerController *videoPlayer;
#end
#implementation viewController1
...
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
...
self.videoPlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
...
[self.videoPlayer play];
...
}
This is viewController2.m:
#import "viewController2.h"
#import "viewController1.h"
#interface viewController2 ()
#end
#implementation viewController2
...
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
viewController1 *thePlayer;
[thePlayer.videoPlayer pause];
//This is where I get an error:
//Property 'videoPlayer' not found on object of type 'viewController1 *'
}
I have tried a lot of searching but I wasn't able to figure out what am I doing wrong. Any help would be highly appreciated.
Thanks! :)
You've got your videoPlayer property defined in your viewController1.m, but you import viewController1.h.
Move videoPlayer to viewController1.h. DO NOT import viewController1.m.

AdMob in iOS with UIWebView

I'm using the latest Xcode (4.4.1) and developing for iOS 5.1. I am utilizing the bottom tab bar interface provided by Apple. One of the tabs uses a UIWebView that utilizes the full screen space. When I try to add a standard banner provided by AdMob, it does not add a banner at all. I was following along with: https://developers.google.com/mobile-ads-sdk/docs/admob/fundamentals. Code attached below
About.h
#import <UIKit/UIKit.h>
#import "GADBannerView.h"
#interface About : UIViewController <UIWebViewDelegate> {
IBOutlet UIWebView *webView;
// Declare one as an instance variable
GADBannerView *bannerView_;
}
#property (nonatomic, retain) UIWebView *webView;
#end
About.m
#import "About.h"
#import "GADBannerView.h"
#import "GADRequest.h"
#import "constants.h"
#implementation About
#synthesize webView;
//#synthesize bannerView = bannerView_;
+ (void)initialize {
// Set user agent (the only problem is that we can't modify the User-Agent later in the program)
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:UserAgent, #"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString *fullURL = ([IsBeta isEqualToString: #"true"]) ? #"http://beta.wouldyouratherapp.com/questions/index/0/1" : #"http://wouldyouratherapp.com/questions/index/0/1";
NSURL *url = [NSURL URLWithString:fullURL]; NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; [webView loadRequest:requestObj];
// Create a view of the standard size at the bottom of the screen.
// Available AdSize constants are explained in GADAdSize.h.
bannerView_ = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
// Specify the ad's "unit identifier." This is your AdMob Publisher ID.
bannerView_.adUnitID = MyAdUnitID;
// Let the runtime know which UIViewController to restore after taking
// the user wherever the ad goes and add it to the view hierarchy.
bannerView_.rootViewController = self;
[self.view addSubview:bannerView_];
// Initiate a generic request to load it with an ad.
[bannerView_ loadRequest:[GADRequest request]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#end
Yes, I have added all the frameworks already, and MyAdUnitID is already defined in the constants file, so everything SHOULD be working, but I guess I am missing something. Any help?
If you're adding the bannerView_, you'll have to decrease the height of your webView accordingly to make room for the bannerView_. Since the origin of the ad looks like its at (0,0), you probably want something similar to this in your adView:DidReceiveAd: callback:
webView.frame = CGRectMake (0, bannerView_.frame.size.height, webView.frame.size.width, webView.frame.size.height - bannerView_.frame.size.height);