Commit a708b862 authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

MacOSX/VLC_app: Initial import. Big playlist still causes memory and cpu high...

MacOSX/VLC_app: Initial import. Big playlist still causes memory and cpu high load. Interface is ugly. Miss many functionality. But code is light. Supports multiple player. Fullscreen a-la frontrow interface (yet a bit ugly).
parent 7ea9b1c2
......@@ -5,14 +5,13 @@
<key>IBClasses</key>
<array>
<dict>
<key>CLASS</key>
<string>VLCCategoryOutlineView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSOutlineView</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>detailListItemDoubleClicked</key>
<string>id</string>
<key>newMainWindow</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>VLCController</string>
<key>LANGUAGE</key>
......@@ -21,12 +20,18 @@
<dict>
<key>categoryList</key>
<string>id</string>
<key>detailItemFetchedStatus</key>
<string>id</string>
<key>detailItemsCount</key>
<string>id</string>
<key>detailList</key>
<string>id</string>
<key>detailSearchField</key>
<string>id</string>
<key>videoView</key>
<key>fillScreenButton</key>
<string>id</string>
<key>videoView</key>
<string>VLCBrowsableVideoView</string>
</dict>
<key>SUPERCLASS</key>
<string>NSObject</string>
......@@ -39,6 +44,28 @@
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>moveDown</key>
<string>id</string>
<key>moveUp</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>VLCBrowsableVideoView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>selectedObject</key>
<string>id</string>
<key>target</key>
<string>id</string>
</dict>
<key>SUPERCLASS</key>
<string>VLCVideoView</string>
</dict>
<dict>
<key>CLASS</key>
<string>VLCVideoView</string>
......
......@@ -10,7 +10,7 @@
<integer>5</integer>
<key>IBOpenObjects</key>
<array>
<integer>253</integer>
<integer>81</integer>
</array>
<key>IBSystem Version</key>
<string>9B18</string>
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
......@@ -9,7 +9,7 @@
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.VLC</string>
<string>org.videolan.vlc</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
......
/*****************************************************************************
* ImageAndTextCell.h: Helpful cell to display an image and a text.
* Borrowed from Apple's sample code for most part.
*****************************************************************************
* Copyright (C) 2007 Pierre d'Herbemont
* Copyright (C) 2007 the VideoLAN team
* $Id$
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import <Cocoa/Cocoa.h>
@interface ImageAndTextCell : NSTextFieldCell {
NSString *imageKeyPath;
id representedObject;
}
/* Will be set at creation time */
@property (copy) NSString * imageKeyPath;
/* Will be set through an outlineView delegate. Represent an object that respond
* to the imageKeyPath. Text is displayed through the usual super class
* @"value" bindings */
@property (retain) id representedObject;
@end
/*****************************************************************************
* ImageAndTextCell.h: Helpful cell to display an image and a text.
* Borrowed from Apple's sample code for most part.
*****************************************************************************
* Copyright (C) 2007 Pierre d'Herbemont
* Copyright (C) 2007 the VideoLAN team
* $Id$
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import "ImageAndTextCell.h"
@implementation ImageAndTextCell
@synthesize imageKeyPath;
@synthesize representedObject;
- (id)init {
if (self = [super init]) {
[self setLineBreakMode:NSLineBreakByTruncatingTail];
[self setSelectable:YES];
}
return self;
}
- (void)dealloc {
[imageKeyPath release];
[super dealloc];
}
- (id)copyWithZone:(NSZone *)zone {
ImageAndTextCell *cell = (ImageAndTextCell *)[super copyWithZone:zone];
cell->imageKeyPath = [imageKeyPath copy];
cell->representedObject = [representedObject retain];
return cell;
}
- (NSImage *)cellImage
{
return imageKeyPath ? [[self representedObject] valueForKeyPath: imageKeyPath] : nil;
}
- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent {
NSRect textFrame, imageFrame;
NSImage * image = [self cellImage];
NSDivideRect (aRect, &imageFrame, &textFrame, 6 + [image size].width, NSMinXEdge);
[super editWithFrame: textFrame inView: controlView editor:textObj delegate:anObject event: theEvent];
}
- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength {
NSRect textFrame, imageFrame;
NSImage * image = [self cellImage];
NSDivideRect (aRect, &imageFrame, &textFrame, 6 + [image size].width, NSMinXEdge);
[super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength];
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
NSImage * image = [self cellImage];
if (image != nil) {
NSRect imageFrame;
NSSize imageSize = [image size];
NSDivideRect(cellFrame, &imageFrame, &cellFrame, 6 + imageSize.width, NSMinXEdge);
if ([self drawsBackground]) {
[[self backgroundColor] set];
NSRectFill(imageFrame);
}
imageFrame.origin.x += 3;
imageFrame.size = imageSize;
if ([controlView isFlipped])
imageFrame.origin.y += ceil((cellFrame.size.height + imageFrame.size.height) / 2);
else
imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2);
[image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver];
}
[super drawWithFrame:cellFrame inView:controlView];
}
- (NSSize)cellSize {
NSImage * image = [self cellImage];
NSSize cellSize = [super cellSize];
cellSize.width += (image ? [image size].width : 0) + 6;
return cellSize;
}
- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView {
NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
NSImage * image = [self cellImage];
// If we have an image, we need to see if the user clicked on the image portion.
if (image != nil) {
// This code closely mimics drawWithFrame:inView:
NSSize imageSize = [image size];
NSRect imageFrame;
NSDivideRect(cellFrame, &imageFrame, &cellFrame, 6 + imageSize.width, NSMinXEdge);
imageFrame.origin.x += 3;
imageFrame.size = imageSize;
// If the point is in the image rect, then it is a content hit
if (NSMouseInRect(point, imageFrame, [controlView isFlipped])) {
// We consider this just a content area. It is not trackable, nor it it editable text. If it was, we would or in the additional items.
// By returning the correct parts, we allow NSTableView to correctly begin an edit when the text portion is clicked on.
return NSCellHitContentArea;
}
}
// At this point, the cellFrame has been modified to exclude the portion for the image. Let the superclass handle the hit testing at this point.
return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];
}
@end
/*****************************************************************************
* VLCAppAdditions.m: Helpful additions to NS* classes
*****************************************************************************
* Copyright (C) 2007 Pierre d'Herbemont
* Copyright (C) 2007 the VideoLAN team
* $Id$
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import <Cocoa/Cocoa.h>
@interface NSIndexPath (VLCAppAddition)
- (NSIndexPath *)indexPathByRemovingFirstIndex;
- (NSUInteger)lastIndex;
@end
@interface NSArray (VLCAppAddition)
- (id)objectAtIndexPath:(NSIndexPath *)path withNodeKeyPath:(NSString *)nodeKeyPath;
@end
@interface NSView (VLCAppAdditions)
- (void)moveSubviewsToVisible;
@end
/* Split view that supports slider animation */
@interface VLCOneSplitView : NSSplitView
- (float)sliderPosition;
- (void)setSliderPosition:(float)newPosition;
@end
\ No newline at end of file
/*****************************************************************************
* VLCAppAdditions.m: Helpful additions to NS* classes
*****************************************************************************
* Copyright (C) 2007 Pierre d'Herbemont
* Copyright (C) 2007 the VideoLAN team
* $Id$
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import "VLCAppAdditions.h"
#import <QuartzCore/QuartzCore.h>
@implementation NSIndexPath (VLCAppAddition)
- (NSIndexPath *)indexPathByRemovingFirstIndex
{
if( [self length] <= 1 )
return [[[NSIndexPath alloc] init] autorelease];
NSIndexPath * ret;
NSUInteger * ints = malloc(sizeof(NSUInteger)*[self length]);
if( !ints ) return nil;
[self getIndexes:ints];
ret = [NSIndexPath indexPathWithIndexes:ints+1 length:[self length]-1];
free(ints);
return ret;
}
- (NSUInteger)lastIndex
{
if(![self length])
return 0;
return [self indexAtPosition:[self length]-1];
}
@end
@implementation NSArray (VLCAppAddition)
- (id)objectAtIndexPath:(NSIndexPath *)path withNodeKeyPath:(NSString *)nodeKeyPath
{
if( ![path length] || !nodeKeyPath )
return self;
id object = [self objectAtIndex:[path indexAtPosition:0]];
id subarray = [object valueForKeyPath:nodeKeyPath];
if([path length] == 1)
return subarray ? subarray : object;
if(!subarray)
return object;
return [subarray objectAtIndexPath:[path indexPathByRemovingFirstIndex] withNodeKeyPath:nodeKeyPath];
}
@end
@implementation NSView (VLCAppAdditions)
- (void)moveSubviewsToVisible
{
for(NSView * view in [self subviews])
{
if( ([view autoresizingMask] & NSViewHeightSizable) &&
!NSContainsRect([view frame], [self bounds]) )
{
NSRect newFrame = NSIntersectionRect( [self bounds], [view frame] );
if( !NSIsEmptyRect(newFrame) )
[view setFrame:NSIntersectionRect( [self bounds], [view frame] )];
}
}
}
@end
/* Split view that supports slider animation */
@implementation VLCOneSplitView
- (float)sliderPosition
{
return [[[self subviews] objectAtIndex:0] frame].size.height;
}
- (void)setSliderPosition:(float)newPosition
{
[self setPosition:newPosition ofDividerAtIndex:0];
}
+ (id)defaultAnimationForKey:(NSString *)key
{
if([key isEqualToString:@"sliderPosition"])
{
return [CABasicAnimation animation];
}
return [super defaultAnimationForKey: key];
}
@end
/*****************************************************************************
* VLCAppBindings.m: Helpful addition code related to bindings uses
*****************************************************************************
* Copyright (C) 2007 Pierre d'Herbemont
* Copyright (C) 2007 the VideoLAN team
* $Id$
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import <Cocoa/Cocoa.h>
#import <VLC/VLC.h>
/* We do implement some category functions,
* But we don't publicise them, as they should
* only be used with bindings. */
@interface VLCMediaDiscoverer (VLCAppBindings)
@end
@interface VLCMedia (VLCAppBindings)
@end
@interface VLCMediaPlayer (VLCAppBindings)
@end
/*****************************************************************************
* VLCAppBindings.m: Helpful addition code related to bindings uses
*****************************************************************************
* Copyright (C) 2007 Pierre d'Herbemont
* Copyright (C) 2007 the VideoLAN team
* $Id$
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import "VLCAppBindings.h"
/* This is globally a big hack to ease binding uses */
/******************************************************************************
* VLCMediaDiscoverer (MasterViewBindings)
*/
@implementation VLCMediaDiscoverer (MasterViewBindings)
+(void)initialize
{
[VLCMediaDiscoverer setKeys:[NSArray arrayWithObject:@"running"] triggerChangeNotificationsForDependentKey:@"currentlyFetchingItems"];
}
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
/* Thanks to Julien Robert, we'll have some nice auto triggered KVO event from here */
static NSDictionary * dict = nil;
if( !dict )
{
dict = [[NSDictionary dictionaryWithObjectsAndKeys:
[NSSet setWithObject:@"discoveredMedia.flatAspect"], @"childrenInMasterViewForDetailView",
nil] retain];
}
return [dict objectForKey: key];
}
/* General shortcuts */
- (BOOL)currentlyFetchingItems
{
return [self isRunning];
}
- (NSImage *)image
{
static NSImage * sdImage = nil;
if( !sdImage )
sdImage = [[NSImage imageNamed:@"applications-internet.png"] retain];
return sdImage;
}
/* MasterView specific bindings */
- (NSArray *)childrenInMasterView
{
return nil;
}
- (NSString *)descriptionInMasterView
{
return [self localizedName];
}
- (VLCMediaListAspect *)childrenInMasterViewForDetailView
{
return [[self discoveredMedia] flatAspect];
}
- (BOOL)editableInMasterView
{
return NO;
}
- (BOOL)selectableInMasterView
{
return YES;
}
/* VideoView specific bindings */
- (NSArray *)childrenInVideoView
{
return [[[self discoveredMedia] flatAspect] valueForKeyPath:@"media"];
}
- (NSString *)descriptionInVideoView
{
return [self localizedName];
}
- (BOOL)isLeaf
{
return YES;
}
@end
/******************************************************************************
* VLCMedia (VLCAppBindings)
*/
@implementation VLCMedia (VLCAppBindings)
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
/* Thanks to Julien Robert, we'll have some nice auto triggered KVO event from here */
static NSDictionary * dict = nil;
if( !dict )
{
dict = [[NSDictionary dictionaryWithObjectsAndKeys:
[NSSet setWithObject:@"subitems.hierarchicalNodeAspect.media"], @"childrenInMasterView",
[NSSet setWithObject:@"metaDictionary.title"], @"descriptionInMasterView",
[NSSet setWithObject:@"subitems.flatAspect"], @"childrenInMasterViewForDetailView",
[NSSet setWithObject:@"metaDictionary.title"], @"descriptionInVideoView",
[NSSet setWithObject:@"state"], @"stateAsImage",
nil] retain];
}
return [dict objectForKey: key];
}
/* MasterView specific bindings */
- (NSArray *)childrenInMasterView
{
return [[[self subitems] hierarchicalNodeAspect] valueForKeyPath:@"media"];
}
- (void)setDescriptionInMasterView:(NSString *)description
{
NSLog(@"unimplemented: meta edition");
}
- (NSString *)descriptionInMasterView
{
return [[self metaDictionary] objectForKey:@"title"];
}
- (VLCMediaListAspect *)childrenInMasterViewForDetailView
{
return [[self subitems] flatAspect];
}
- (BOOL)editableInMasterView
{
return YES;
}
- (BOOL)selectableInMasterView
{
return YES;
}
- (BOOL)currentlyFetchingItems
{
return NO;
}
- (NSImage *)image
{
static NSImage * playlistImage = nil;
if( !playlistImage )
playlistImage = [[NSImage imageNamed:@"type_playlist.png"] retain];
return playlistImage;
}
/* VideoView specific bindings */
- (NSArray *)childrenInVideoView
{
return [[[self subitems] flatAspect] valueForKeyPath:@"media"];
}
- (NSString *)descriptionInVideoView
{
return [[self metaDictionary] objectForKey:@"title"];
}
/* DetailList specific bindings */
- (NSImage *)stateAsImage
{
static NSImage * playing = nil;
static NSImage * error = nil;
if(!playing)
playing = [[NSImage imageNamed:@"volume_high.png"] retain];
if(!error)
error = [[NSImage imageNamed:@"dialog-error.png"] retain];
if( [self state] == VLCMediaStatePlaying )
return playing;
else if( [self state] == VLCMediaStateBuffering )
return playing;
else if( [self state] == VLCMediaStateError )
return error;
return nil;
}
@end
@implementation VLCMediaPlayer (VLCAppBindings)
+ (void)initialize
{
[self setKeys:[NSArray arrayWithObjects:@"playing", @"media", nil] triggerChangeNotificationsForDependentKey:@"description"];
}
- (NSString *)description
{
if([self media])
return [self valueForKeyPath:@"media.metaDictionary.title"];
else
return @"VLC Media Player";
}
@end
/*****************************************************************************
* VLCBrowsableVideoView.h: VideoView subclasses that allow fullscreen
* browsing
*****************************************************************************
* Copyright (C) 2007 Pierre d'Herbemont
* Copyright (C) 2007 the VideoLAN team
* $Id$
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import <QuartzCore/QuartzCore.h>
#import <VLC/VLC.h>
@interface VLCBrowsableVideoView : VLCVideoView {
BOOL menuDisplayed;
NSArray * itemsTree;
NSRange displayedItems;
NSInteger selectedIndex;
CALayer * selectionLayer;
CALayer * backLayer;
CALayer * menuLayer;
NSIndexPath * selectedPath;