How do I add an AVPlayer to a QWidget? - macos

On Mac, I want to use AVPlayer to play video in my Qt 4.8 application since it has features that Phonon::VideoPlayer doesn't have.
How do I add the AVPlayerLayer to a QWidget so it becomes visible? I'm doing the following:
pimpl->player = [[AVPlayer alloc] initWithURL:[NSURL fileURLWithPath:videoFile]];
pimpl->player.actionAtItemEnd = AVPlayerActionAtItemEndPause;
pimpl->player.rate = 0;
pimpl->playerLayer = [[AVPlayerLayer playerLayerWithPlayer:pimpl->player] retain];
[pimpl->playerLayer setFrame: CGRectMake(0, 0, rect().width(), rect().height())];
NSView* view = (NSView*)winId();
[[view layer] addSublayer:pimpl->playerLayer];
When I play my video, I hear it, but I don't see it. Any idea what I'm doing wrong?

Rather than using winId(), use QMacCocoaViewContainer, but QMacCocoaViewContainer has a bug which will cause the NSView to not be displayed in Qt 4.8 unless setAttribute(Qt::WA_NativeWindow); is set.
As well, the NSView may not have a layer, so a layer need to be created.
[pimpl->view setWantsLayer:YES];
[pimpl->view makeBackingLayer];
So in total it looks like:
pimpl->view = [[NSView alloc] initWithFrame: CGRectMake(0, 0, w, h)];
[pimpl->view setHidden:NO];
[pimpl->view setNeedsDisplay:YES];
[pimpl->view setWantsLayer:YES];
[pimpl->view makeBackingLayer];
viewFrame = new QMacCocoaViewContainer(NULL, this);
viewFrame->setGeometry(rect());
viewFrame->setVisible(true);
viewFrame->setCocoaView(pimpl->view);
NSString* videoFile = [NSString stringWithCString:filename.toUtf8().data() encoding:NSUTF8StringEncoding];
pimpl->player = [[AVPlayer alloc] initWithURL:[NSURL fileURLWithPath:videoFile]];
pimpl->player.actionAtItemEnd = AVPlayerActionAtItemEndPause;
pimpl->player.rate = 0;
pimpl->playerLayer = [[AVPlayerLayer playerLayerWithPlayer:pimpl->player] retain];
[pimpl->playerLayer setFrame: CGRectMake(0, 0, w, h)];
[pimpl->playerLayer setHidden: NO];
CALayer* layer = [pimpl->view layer];
[layer addSublayer:pimpl->playerLayer];

Related

CALayer mask Layer animating

I want to mask CALayer with another layer whose frame I want to keep changing in every draw call thereby animating. Is it possible to do change the frame of mask layer in every draw call rather than making a new mask layer?
Try the following code. This code will run on Cocoa App for macOS. Kindly change the classes accordingly if you are going for Cocoa Touch for iOS. I hope this works for you.
// ViewController.h
import
#interface ViewController : NSViewController{
CALayer * maskLayer;
CALayer * Layer;
}
// ViewController.m
#implementation ViewController
-(void)viewDidLoad{
[super viewDidLoad];
maskLayer = [CALayer layer];
Layer = [CALayer layer];
Layer.backgroundColor = [[NSColor blueColor] CGColor];
Layer.frame = CGRectMake(20, 20, 720, 900);
Layer.contents = [NSImage imageNamed:#"bg1"];
maskLayer.frame = CGRectMake(20, 20, 720, 900);
maskLayer.opacity = 0.5;
[maskLayer mask];
maskLayer.contents = [NSImage imageNamed:#"bg"];
[self.view.layer addSublayer:Layer];
[self.view.layer addSublayer:maskLayer];
[self maskLayerAnimation];
}
-(void)maskLayerAnimation{
[CATransaction begin];
CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:#"opacity"];
fadeAnim.fromValue = [NSNumber numberWithFloat:1.0];
fadeAnim.toValue = [NSNumber numberWithFloat:0.0];
fadeAnim.duration = 5.0;
[CATransaction setCompletionBlock:^{
NSLog(#"animation completed");
maskLayer.frame = CGRectMake(20, 20, 720, 700);
maskLayer.contents = [NSImage imageNamed:#"bg2"];
}];;
[maskLayer addAnimation:fadeAnim forKey:#"opacity"];
[CATransaction commit];
}

fullscreen uiview not worked perfectly

good morning,
i have a problem when i tried to pass to a full screen by clicking on the zoom button.In fact when i tapped the button displays a video and a toolbar that allows to move in the video. it's seems worked perfectly but i discovered that when I move through the slider to a level almost 60% I can not move forward or backward.
i think that the problem is due to layout setting.
this the code :
- (void)changeFullScreen:(BOOL)isFullScreen index:(int)index{
if (isFullScreen == YES) {
CGAffineTransform affineTransforme = CGAffineTransformMakeRotation(M_PI_2);
//CGFloat scale = [UIScreen mainScreen].bounds.size.height / [UIScreen mainScreen].bounds.size.width;
//affineTransforme = CGAffineTransformScale(affineTransforme,scale , scale);
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
EMPOIVideoCell *cell = [poiTableView cellForRowAtIndexPath:indexPath];
tmpVideoPlayerview = [cell.containerView viewWithTag:101];
//tmpVideoPlayerview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
tmpVideoPlayerview.transform = affineTransforme; //CGAffineTransformTranslate(affineTransforme, 190, 0);
fullScreenView = [[UIViewController alloc] init];
tmpVideoPlayerview.frame = CGRectMake(-248, 0, fullScreenView.view.bounds.size.height , fullScreenView.view.bounds.size.width);
tmpVideoPlayerview.videoContainer.frame = tmpVideoPlayerview.frame;
tmpVideoPlayerview.videoContainer.layer.frame = tmpVideoPlayerview.frame;
playerLayer = [AVPlayerLayer playerLayerWithPlayer:tmpVideoPlayerview.videoPlayer];
playerLayer.frame = tmpVideoPlayerview.videoContainer.bounds;
[tmpVideoPlayerview.avPlayerLayer removeFromSuperlayer];
[tmpVideoPlayerview.videoContainer.layer addSublayer:playerLayer];
tmpVideoPlayerview.contentMode = UIViewContentModeScaleToFill;
//[tmpVideoPlayerview updateConstraints];
[tmpVideoPlayerview setNeedsLayout] ;
[tmpVideoPlayerview layoutIfNeeded];
fullScreenView.view.clipsToBounds = YES;
[fullScreenView.view addSubview:tmpVideoPlayerview];
[self addChildViewController:fullScreenView];
[self.view addSubview:fullScreenView.view];
//[fullScreenView.view updateConstraints];
//[fullScreenView.view layoutIfNeeded];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
photo to explain the situation

Adding UISegmentedControl to UIScrollView programmatically

I am tyring to add UISegmentedControl to UIScrolview programmatically.
I am using below code..
I don't why the scrollview is not enabled.
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 435)];
scroll.contentSize = CGSizeMake(320, 700);
scroll.showsHorizontalScrollIndicator = YES;
NSArray *menu = [NSArray arrayWithObjects:[UIImage imageNamed:#"Accountimg.png"],[UIImage imageNamed:#"Challengesimg.png"],[UIImage imageNamed:#"Profileimg.png"],[UIImage imageNamed:#"Challengesimg.png"],nil];
UISegmentedControl *menuSegmentedControl = [[UISegmentedControl alloc] initWithItems:menu];
menuSegmentedControl.frame = CGRectMake(0,0,450,40);
menuSegmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
[scroll addSubview:menuSegmentedControl];
[menuScrollView addSubview:scroll];
[menuSegmentedControl release];
[scroll release];
I am unable to scroll horizontally..
Thanks in advance
UPDATE:
I am able to get the horizontal scroll.
Code updated:
menuSegmentedControl.frame = CGRectMake(0,0,500,35);
menuSegmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
menuScrollView.contentSize = CGSizeMake(menuSegmentedControl.frame.size.width, menuSegmentedControl.frame.size.height);
menuScrollView.showsVerticalScrollIndicator = NO;
[menuScrollView addSubview:menuSegmentedControl];
menuScrollView.clipsToBounds = YES;
Thank you.

Create an animation like that of an NSPopOver

I'm working at a custom Window object that is displayed as child in a parent Window.
For this object I'd like to create an animation like that of an NSPopover.
My first idea is to create a Screenshot of the child Window, than animate it using Core Animation and finally showing the real Window.
Before begging the implementation I would like to know if exists a better method and what you think about my solution.
It's not trivial. Here's how I do it:
#interface ZoomWindow : NSWindow
{
CGFloat animationTimeMultiplier;
}
#property (nonatomic, readwrite, assign) CGFloat animationTimeMultiplier;
#end
#implementation ZoomWindow
#synthesize animationTimeMultiplier;
- (NSTimeInterval)animationResizeTime: (NSRect)newWindowFrame
{
float multiplier = animationTimeMultiplier;
if (([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) != 0) {
multiplier *= 10;
}
return [super animationResizeTime: newWindowFrame] * multiplier;
}
#end
#implementation NSWindow (PecuniaAdditions)
- (ZoomWindow*)createZoomWindowWithRect: (NSRect)rect
{
// Code mostly from http://www.noodlesoft.com/blog/2007/06/30/animation-in-the-time-of-tiger-part-1/
// Copyright 2007 Noodlesoft, L.L.C.. All rights reserved.
// The code is provided under the MIT license.
// The code has been extended to support layer-backed views. However, only the top view is
// considered here. The code might not produce the desired output if only a subview has its layer
// set. So better set it on the top view (which should cover most cases).
NSImageView *imageView;
NSImage *image;
NSRect frame;
BOOL isOneShot;
frame = [self frame];
isOneShot = [self isOneShot];
if (isOneShot) {
[self setOneShot: NO];
}
BOOL hasLayer = [[self contentView] wantsLayer];
if ([self windowNumber] <= 0) // <= 0 if hidden
{
// We need to temporarily switch off the backing layer of the content view or we get
// context errors on the second or following runs of this code.
[[self contentView] setWantsLayer: NO];
// Force window device. Kinda crufty but I don't see a visible flash
// when doing this. May be a timing thing wrt the vertical refresh.
[self orderBack: self];
[self orderOut: self];
[[self contentView] setWantsLayer: hasLayer];
}
// Capture the window into an off-screen bitmap.
image = [[NSImage alloc] initWithSize: frame.size];
[[self contentView] lockFocus];
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect: NSMakeRect(0.0, 0.0, frame.size.width, frame.size.height)];
[[self contentView] unlockFocus];
[image addRepresentation: rep];
// If the content view is layer-backed the above initWithFocusedViewRect call won't get the content
// of the view (seems it doesn't work for CALayers). So we need a second call that captures the
// CALayer content and copies it over the captured image (compositing so the window frame and its content).
if (hasLayer)
{
NSRect contentFrame = [[self contentView] bounds];
int bitmapBytesPerRow = 4 * contentFrame.size.width;
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
CGContextRef context = CGBitmapContextCreate (NULL,
contentFrame.size.width,
contentFrame.size.height,
8,
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
[[[self contentView] layer] renderInContext: context];
CGImageRef img = CGBitmapContextCreateImage(context);
CFRelease(context);
NSImage *subImage = [[NSImage alloc] initWithCGImage: img size: contentFrame.size];
CFRelease(img);
[image lockFocus];
[subImage drawAtPoint: NSMakePoint(0, 0)
fromRect: NSMakeRect(0, 0, contentFrame.size.width, contentFrame.size.height)
operation: NSCompositeCopy
fraction: 1];
[image unlockFocus];
}
ZoomWindow *zoomWindow = [[ZoomWindow alloc] initWithContentRect: rect
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreBuffered
defer: NO];
zoomWindow.animationTimeMultiplier = 0.3;
[zoomWindow setBackgroundColor: [NSColor colorWithDeviceWhite: 0.0 alpha: 0.0]];
[zoomWindow setHasShadow: [self hasShadow]];
[zoomWindow setLevel: [self level]];
[zoomWindow setOpaque: NO];
[zoomWindow setReleasedWhenClosed: NO];
[zoomWindow useOptimizedDrawing: YES];
imageView = [[NSImageView alloc] initWithFrame: [zoomWindow contentRectForFrameRect: frame]];
[imageView setImage: image];
[imageView setImageFrameStyle: NSImageFrameNone];
[imageView setImageScaling: NSScaleToFit];
[imageView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
[zoomWindow setContentView: imageView];
[self setOneShot: isOneShot];
return zoomWindow;
}
- (void)fadeIn
{
[self setAlphaValue: 0.f];
[self orderFront: nil];
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration: 0.3];
[[self animator] setAlphaValue: 1.f];
[NSAnimationContext endGrouping];
}
- (void)zoomInWithOvershot: (NSRect)overshotFrame withFade: (BOOL)fade makeKey: (BOOL)makeKey
{
[self setAlphaValue: 0];
NSRect frame = [self frame];
ZoomWindow *zoomWindow = [self createZoomWindowWithRect: frame];
zoomWindow.alphaValue = 0;
[zoomWindow orderFront: self];
NSDictionary *windowResize = #{NSViewAnimationTargetKey: zoomWindow,
NSViewAnimationEndFrameKey: [NSValue valueWithRect: overshotFrame],
NSViewAnimationEffectKey: NSViewAnimationFadeInEffect};
NSArray *animations = #[windowResize];
NSViewAnimation *animation = [[NSViewAnimation alloc] initWithViewAnimations: animations];
[animation setAnimationBlockingMode: NSAnimationBlocking];
[animation setAnimationCurve: NSAnimationEaseIn];
[animation setDuration: 0.2];
[animation startAnimation];
zoomWindow.animationTimeMultiplier = 0.5;
[zoomWindow setFrame: frame display: YES animate: YES];
[self setAlphaValue: 1];
if (makeKey) {
[self makeKeyAndOrderFront: self];
} else {
[self orderFront: self];
}
[zoomWindow close];
}
This is implemented in an NSWindow category. So you can call:
- (void)zoomInWithOvershot: (NSRect)overshotFrame withFade: (BOOL)fade makeKey: (BOOL)makeKey
on any NSWindow.
I should add that I haven't been able to get both animations to run at the same time (fade and size), but the effect is quite similar to how NSPopover does it. Maybe someone else can fix the animation issue.
Needless to say this code works on 10.6 too where you don't have NSPopover (that's why I have written it in the first place).

Uisegment buttons over scroll view

hi iam trying to put a uisegmented controls over a uiscrollview beacuse i want them to scroll horizontally this is the code i tried
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 600, 300)];
scroll.contentSize = CGSizeMake(500, 50);
scroll.showsHorizontalScrollIndicator = YES;
scroll.pagingEnabled = YES;
scroll.showsHorizontalScrollIndicator = YES;
scroll.autoresizingMask = YES;
scroll.autoresizesSubviews = YES;
NSArray *itemArray = [NSArray arrayWithObjects: #"One", #"Two", #"Three",#"four",#"Five", nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(0,10, 500, 50);
segmentedControl.segmentedControlStyle = UISegmentedControlStylePlain;
segmentedControl.selectedSegmentIndex = 4;
[scroll addSubview:segmentedControl];
[self.view addSubview:scroll];
any one please help me to accomplish this . thanks in advance happy coding
The frame for the scroll View must be less than the Content size of scroll view. If you will increase your content size definitely it will work. For example:-
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
scroll.contentSize = CGSizeMake(500, 50);
scroll.showsHorizontalScrollIndicator = YES;
scroll.pagingEnabled = YES;
scroll.showsHorizontalScrollIndicator = YES;
scroll.autoresizingMask = YES;
scroll.autoresizesSubviews = YES;
NSArray *itemArray = [NSArray arrayWithObjects: #"One", #"Two", #"Three",#"four",#"Five", nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(0,10, 500, 50);
segmentedControl.segmentedControlStyle = UISegmentedControlStylePlain;
segmentedControl.selectedSegmentIndex = 4;
[scroll addSubview:segmentedControl];
[self.view addSubview:scroll];
If its supportive please mark the answer correct. Thanks very much.

Resources