Browse Source

extra/MacOSX/Framework: Initial import of the Mac OS X Framework.

Pierre d'Herbemont 18 years ago
commit
f9ebe365a2

+ 18 - 0
Examples/test/Controller.h

@@ -0,0 +1,18 @@
+/* Controller */
+
+#import <Cocoa/Cocoa.h>
+#import <VLC/VLC.h>
+
+@interface Controller : NSObject
+{
+    IBOutlet id window;
+    IBOutlet id playlistOutline;
+    IBOutlet id videoHolderView;
+    
+    VLCVideoView * videoView;
+    VLCPlaylist  * playlist;
+}
+- (void)awakeFromNib;
+
+- (void)play:(id)sender;
+@end

+ 34 - 0
Examples/test/Controller.m

@@ -0,0 +1,34 @@
+#import "Controller.h"
+
+@implementation Controller
+- (void)awakeFromNib
+{
+    NSRect rect;
+    VLCPlaylistDataSource * aDataSource;
+
+    /* Won't be released */
+    videoView = [[VLCVideoView alloc] init];
+
+    rect = [videoHolderView frame];
+    [[window contentView] replaceSubview: videoHolderView with: videoView];
+    [videoView setFrame: rect];
+    [videoView setAutoresizingMask: NSViewHeightSizable|NSViewWidthSizable];
+
+    /* Won't be released */
+    playlist = [[VLCPlaylist alloc] init];
+
+    /* Won't be released */
+    aDataSource = [[VLCPlaylistDataSource alloc] initWithPlaylist:playlist videoView:videoView];
+
+    [playlistOutline setDataSource: aDataSource];
+    [playlistOutline registerForDraggedTypes: [NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil]];
+}
+
+- (void)play:(id)sender
+{
+    if(![videoView playlist])
+        [videoView setPlaylist: playlist];
+    if( [sender isKindOfClass:[NSTableView class]] && [sender selectedRow] >= 0)
+        [videoView playItemAtIndex: [sender selectedRow]];
+}
+@end

BIN
Examples/test/English.lproj/InfoPlist.strings


+ 14 - 0
Examples/test/English.lproj/MainMenu.nib/classes.nib

@@ -0,0 +1,14 @@
+{
+    IBClasses = (
+        {
+            ACTIONS = {play = id; }; 
+            CLASS = Controller; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {playlistOutline = id; videoHolderView = id; window = id; }; 
+            SUPERCLASS = NSObject; 
+        }, 
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {CLASS = NSSegmentedControl; LANGUAGE = ObjC; SUPERCLASS = NSControl; }
+    ); 
+    IBVersion = 1; 
+}

+ 22 - 0
Examples/test/English.lproj/MainMenu.nib/info.nib

@@ -0,0 +1,22 @@
+<?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">
+<plist version="1.0">
+<dict>
+	<key>IBDocumentLocation</key>
+	<string>135 107 356 240 0 0 1680 1028 </string>
+	<key>IBEditorPositions</key>
+	<dict>
+		<key>29</key>
+		<string>132 353 338 44 0 0 1680 1028 </string>
+	</dict>
+	<key>IBFramework Version</key>
+	<string>446.1</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>21</integer>
+		<integer>29</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>8R218</string>
+</dict>
+</plist>

BIN
Examples/test/English.lproj/MainMenu.nib/keyedobjects.nib


+ 28 - 0
Examples/test/Info.plist

@@ -0,0 +1,28 @@
+<?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">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>com.yourcompany.test</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>

+ 26 - 0
Examples/test/main.m

@@ -0,0 +1,26 @@
+//
+//  main.m
+//  test
+//
+//  Created by Pierre d'Herbemont on 13/04/07.
+//  Copyright __MyCompanyName__ 2007. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <VLC/VLC.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+    /* If we can't load the VLC.framework dyld will tell us anyway
+     * But this is cool */
+    if(test_vlc_framework() == 0xbabe)
+        printf("We are linked to VLC.framework!\n");
+    else
+    {
+        fprintf(stderr, "*** Can't load the VLC.framework\n");
+        return -1;
+    }
+    
+    return NSApplicationMain(argc, (const char **) argv);
+}

+ 302 - 0
Examples/test/test.xcodeproj/project.pbxproj

@@ -0,0 +1,302 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		630AFC550BCFD65300802A4E /* VLC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 630AFC540BCFD65300802A4E /* VLC.framework */; };
+		6333027A0BD24CDB00193D7D /* Controller.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 633302780BD24CDB00193D7D /* Controller.h */; };
+		6333027B0BD24CDB00193D7D /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 633302790BD24CDB00193D7D /* Controller.m */; };
+		6333039B0BD2553F00193D7D /* VLC.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 630AFC540BCFD65300802A4E /* VLC.framework */; };
+		8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; };
+		8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
+		8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
+		8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		630AFC670BCFD81B00802A4E /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 10;
+			files = (
+				6333039B0BD2553F00193D7D /* VLC.framework in CopyFiles */,
+				6333027A0BD24CDB00193D7D /* Controller.h in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+		13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+		29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; };
+		29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+		29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+		32CA4F630368D1EE00C91783 /* test_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_Prefix.pch; sourceTree = "<group>"; };
+		630AFC540BCFD65300802A4E /* VLC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VLC.framework; path = ../../VLC.framework; sourceTree = SOURCE_ROOT; };
+		633302780BD24CDB00193D7D /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
+		633302790BD24CDB00193D7D /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
+		8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+		8D1107320486CEB800E47090 /* test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = test.app; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		8D11072E0486CEB800E47090 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
+				630AFC550BCFD65300802A4E /* VLC.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		080E96DDFE201D6D7F000001 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				633302780BD24CDB00193D7D /* Controller.h */,
+				633302790BD24CDB00193D7D /* Controller.m */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				630AFC540BCFD65300802A4E /* VLC.framework */,
+				1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
+			);
+			name = "Linked Frameworks";
+			sourceTree = "<group>";
+		};
+		1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				29B97324FDCFA39411CA2CEA /* AppKit.framework */,
+				13E42FB307B3F0F600E4EEF1 /* CoreData.framework */,
+				29B97325FDCFA39411CA2CEA /* Foundation.framework */,
+			);
+			name = "Other Frameworks";
+			sourceTree = "<group>";
+		};
+		19C28FACFE9D520D11CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8D1107320486CEB800E47090 /* test.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		29B97314FDCFA39411CA2CEA /* test */ = {
+			isa = PBXGroup;
+			children = (
+				080E96DDFE201D6D7F000001 /* Classes */,
+				29B97315FDCFA39411CA2CEA /* Other Sources */,
+				29B97317FDCFA39411CA2CEA /* Resources */,
+				29B97323FDCFA39411CA2CEA /* Frameworks */,
+				19C28FACFE9D520D11CA2CBB /* Products */,
+			);
+			name = test;
+			sourceTree = "<group>";
+		};
+		29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				32CA4F630368D1EE00C91783 /* test_Prefix.pch */,
+				29B97316FDCFA39411CA2CEA /* main.m */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+		29B97317FDCFA39411CA2CEA /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				8D1107310486CEB800E47090 /* Info.plist */,
+				089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
+				29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
+				1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		8D1107260486CEB800E47090 /* test */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "test" */;
+			buildPhases = (
+				8D1107290486CEB800E47090 /* Resources */,
+				630AFC670BCFD81B00802A4E /* CopyFiles */,
+				8D11072C0486CEB800E47090 /* Sources */,
+				8D11072E0486CEB800E47090 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = test;
+			productInstallPath = "$(HOME)/Applications";
+			productName = test;
+			productReference = 8D1107320486CEB800E47090 /* test.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		29B97313FDCFA39411CA2CEA /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "test" */;
+			hasScannedForEncodings = 1;
+			mainGroup = 29B97314FDCFA39411CA2CEA /* test */;
+			projectDirPath = "";
+			targets = (
+				8D1107260486CEB800E47090 /* test */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		8D1107290486CEB800E47090 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */,
+				8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		8D11072C0486CEB800E47090 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8D11072D0486CEB800E47090 /* main.m in Sources */,
+				6333027B0BD24CDB00193D7D /* Controller.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				089C165DFE840E0CC02AAC07 /* English */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+		29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = {
+			isa = PBXVariantGroup;
+			children = (
+				29B97319FDCFA39411CA2CEA /* English */,
+			);
+			name = MainMenu.nib;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		C01FCF4B08A954540054247B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../..\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Applications";
+				PRODUCT_NAME = test;
+				WRAPPER_EXTENSION = app;
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		C01FCF4C08A954540054247B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(NATIVE_ARCH)";
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../..\"";
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Applications";
+				PRODUCT_NAME = test;
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
+		C01FCF4F08A954540054247B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+			};
+			name = Debug;
+		};
+		C01FCF5008A954540054247B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(NATIVE_ARCH)";
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C01FCF4B08A954540054247B /* Debug */,
+				C01FCF4C08A954540054247B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C01FCF4E08A954540054247B /* Build configuration list for PBXProject "test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C01FCF4F08A954540054247B /* Debug */,
+				C01FCF5008A954540054247B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}

+ 7 - 0
Examples/test/test_Prefix.pch

@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'test' target in the 'test' project
+//
+
+#ifdef __OBJC__
+    #import <Cocoa/Cocoa.h>
+#endif

+ 39 - 0
Headers/VLC/VLC.h

@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * VLC.h: VLC.framework main header
+ *****************************************************************************
+ * 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.
+ *****************************************************************************/
+
+#ifndef VLC_FRAMEWORK_VLC_H
+#define VLC_FRAMEWORK_VLC_H
+
+typedef void * _opaque_ptr;
+
+#import <VLC/VLCMedia.h>
+#import <VLC/VLCMediaDiscoverer.h>
+#import <VLC/VLCMediaLibrary.h>
+#import <VLC/VLCPlaylist.h>
+#import <VLC/VLCPlaylistDataSource.h>
+#import <VLC/VLCServicesDiscoverer.h>
+#import <VLC/VLCTime.h>
+#import <VLC/VLCVideoView.h>
+
+#endif /* VLC_FRAMEWORK_VLC_H */

+ 56 - 0
Headers/VLC/VLCMedia.h

@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * VLCMedia.h: VLC.framework VLCMedia header
+ *****************************************************************************
+ * 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/VLCPlaylist.h>
+
+/* Meta */
+extern NSString * VLCMetaInformationTitle; /* Associated to an NSString */
+extern NSString * VLCMetaInformationAuthor; /* Associated to an NSString */
+extern NSString * VLCMetaInformationArtwork; /* Associated to an NSImage */
+
+/* Notification */
+extern NSString * VLCMediaSubItemAdded;
+
+@class VLCPlaylist;
+
+@interface VLCMedia : NSObject
+{
+    void * md;
+    NSString * url;
+    VLCPlaylist *subitems;
+    NSMutableDictionary *metaInformation;
+}
+
+- (id)initWithURL:(NSString *)anURL;
++ (id)mediaWithURL:(NSString *)anURL;
+
+- (void) dealloc;
+
+- (NSString *)url;
+- (VLCPlaylist *)subitems;
+
+/* Returns a dictionary with corresponding object associated with a meta */
+- (NSDictionary *)metaInformation;
+@end

+ 42 - 0
Headers/VLC/VLCMediaDiscoverer.h

@@ -0,0 +1,42 @@
+/*****************************************************************************
+ * VLCMediaDiscoverer.h: VLC.framework VLCMediaDiscoverer header
+ *****************************************************************************
+ * 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/VLCPlaylist.h>
+
+@class VLCPlaylist;
+
+@interface VLCMediaDiscoverer : NSObject
+{
+    NSString *localizedName;
+    VLCPlaylist * playlist;
+    void * mdis;
+}
+
+- (id)initWithName:(NSString *)aServiceName;
+
+- (VLCPlaylist *)playlist;
+
+- (NSString *)localizedName;
+@end

+ 42 - 0
Headers/VLC/VLCMediaLibrary.h

@@ -0,0 +1,42 @@
+/*****************************************************************************
+ * VLCMediaDiscoverer.h: VLC.framework VLCMediaDiscoverer header
+ *****************************************************************************
+ * 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/VLCPlaylist.h>
+
+@class VLCPlaylist;
+
+@interface VLCMediaLibrary : NSObject
+{
+    VLCPlaylist * allMedia;
+    void * mlib;
+}
+
++ (id)sharedMediaLibrary;
+
+- (VLCPlaylist *)allMedia;
+
+- (NSArray *) playlists;
+
+@end

+ 61 - 0
Headers/VLC/VLCPlaylist.h

@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * VLCPlaylist.h: VLC.framework VLCPlaylist header
+ *****************************************************************************
+ * 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 <Foundation/Foundation.h>
+
+#import <VLC/VLCMedia.h>
+
+/* Hack to avoid troubles with modules/macosx for now */
+#define VLCPlaylist VLCPlaylistBis
+
+/* Notification Posted */
+extern NSString * VLCPlaylistItemChanged;
+extern NSString * VLCPlaylistItemDeleted;
+extern NSString * VLCPlaylistItemAdded;
+
+@class VLCMedia;
+
+@interface VLCPlaylist : NSObject
+{
+    NSMutableArray * items;
+    void * p_mlist;
+}
+- (id)init;
+
+- (void)lock;
+- (void)unlock;
+
+- (VLCMedia *)mediaAtIndex: (int)index;
+- (int)countMedia;
+
+- (NSArray *)sublists;
+- (VLCPlaylist *)flatPlaylist;
+
+- (VLCMedia *)providerMedia;
+
+- (void)addMedia: (VLCMedia *)item;
+- (void)insertMedia: (VLCMedia *)item atIndex: (int)index;
+- (void)removeMediaAtIndex: (int)index;
+@end
+

+ 62 - 0
Headers/VLC/VLCPlaylistDataSource.h

@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * VLCPlaylistDataSource.h: VLC.framework VLCPlaylistDataSource header
+ *****************************************************************************
+ * 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 <VLC/VLCPlaylist.h>
+#import <VLC/VLCVideoView.h>
+
+/* This class can be used as a data source for an NSOutlineView
+ * it will display the playlist content. If provided the videoView
+ * will automatically be associated to the given playlist, and actions
+ * in the outlineView will trigger the videoView, visual feedback of the
+ * current item in the videoview will be displayed in the outlineview
+ */
+@interface VLCPlaylistDataSource : NSObject
+{
+    VLCPlaylist  * playlist;
+    VLCVideoView * videoView;
+    
+    NSOutlineView *outlineView;
+}
+- (id)initWithPlaylist:(VLCPlaylist *)aPlaylist;
+- (id)initWithPlaylist:(VLCPlaylist *)aPlaylist videoView:(VLCVideoView *)aVideoView;
+
+- (VLCPlaylist *)playlist;
+- (VLCVideoView *)videoView;
+@end
+
+/* It could be really useful to use that, this probably need to be reviewed to see
+ * if it really belongs here */
+@interface VLCPlaylistDataSource (OutlineViewDataSource)
+- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item;
+- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item;
+- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item;
+- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
+@end
+
+@interface VLCPlaylistDataSource (OutlineViewDataSourceDropping)
+- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index;
+- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index;
+@end
+
+

+ 34 - 0
Headers/VLC/VLCServicesDiscoverer.h

@@ -0,0 +1,34 @@
+/*****************************************************************************
+ * VLCMediaDiscoverer.h: VLC.framework VLCMediaDiscoverer header
+ *****************************************************************************
+ * 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 VLCServicesDiscoverer : NSObject
+{
+    NSArray * services;
+}
++ (id)sharedDiscoverer;
+- (id)init;
+- (NSArray *)services;
+@end

+ 35 - 0
Headers/VLC/VLCTime.h

@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * VLCTime.h: VLC.framework VLCTime header
+ *****************************************************************************
+ * 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 VLCTime : NSObject
+{
+    NSNumber * value;
+}
+- (id)initWithNumber:(NSNumber *)aNumber;
+
+- (NSNumber *)numberRepresentation;
+- (NSString *)stringRepresentation;
+@end

+ 100 - 0
Headers/VLC/VLCVideoView.h

@@ -0,0 +1,100 @@
+/*****************************************************************************
+ * VLCVideoView.h: VLC.framework VLCVideoView header
+ *****************************************************************************
+ * 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/VLCTime.h>
+#import <VLC/VLCPlaylist.h>
+
+@protocol VLCVideoViewDelegate;
+
+/* Notification */
+extern NSString * VLCVideoDidChangeVolume;
+extern NSString * VLCVideoDidChangeTime;
+extern NSString * VLCVideoDidChangeCurrentlyPlayingItem;
+extern NSString * VLCVideoDidStop;
+extern NSString * VLCVideoDidPause;
+extern NSString * VLCVideoDidPlay;
+
+@interface VLCVideoView : NSView
+{
+    VLCPlaylist   * playlist;
+    NSConnection  * connection;
+    id              delegate;
+    BOOL            stretchVideo;
+
+    void * p_mi;
+    void * p_mlp;
+}
+
+- (id)initWithFrame:(NSRect)frameRect;
+- (void)dealloc;
+
+- (void)setPlaylist: (VLCPlaylist *)newPlaylist;
+- (VLCPlaylist *)playlist;
+
+/* Play */
+- (void)play;
+- (void)playItemAtIndex:(int)index;
+- (void)playMedia:(VLCMedia *)media;
+- (void)pause;
+- (void)setCurrentTime:(VLCTime *)timeObj;
+
+/* State */
+- (BOOL)isPlaying;
+- (BOOL)isPaused;
+- (VLCTime *)currentTime;
+- (id)currentPlaylistItem;
+
+/* Video output property */
+- (void)setStretchesVideo:(BOOL)flag;
+- (BOOL)stretchesVideo;
+
+/* Fullscreen */
+- (void)enterFullscreen;
+- (void)leaveFullscreen;
+
+/* Delegate */
+- (void)setDelegate: (id)newDelegate;
+- (id)delegate;
+@end
+
+@protocol VLCVideoViewDelegate
+- (void)videoDidStop:(NSNotification *)notification;
+- (void)videoDidPlay:(NSNotification *)notification;
+- (void)videoDidPause:(NSNotification *)notification;
+- (void)videoDidPlayNextPlaylistElement:(NSNotification *)notification;
+
+- (void)videoDidChangeVolume:(NSNotification *)notification;
+
+/* Returns NO if the Video shouldn't be paused */
+- (BOOL)videoWillPause:(NSNotification *)notification;
+/* Returns NO if the Video shouldn't play next playlist element */
+- (BOOL)videoWillPlayNextPlaylistElement:(NSNotification *)notification;
+
+/* Posted when the progress of the video has reached a new step
+ * (every second?).
+ * The -object contained in the notification is the new VLCTime */
+- (void)videoDidChangeTime:(NSNotification *)notification;
+@end

+ 43 - 0
Headers/VLCEventManager.h

@@ -0,0 +1,43 @@
+/*****************************************************************************
+ * VLCEventManager.h: VLC.framework VLCEventManager header
+ *****************************************************************************
+ * 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 <pthread.h>
+
+/* This object is here to ensure safe inter thread communication */
+
+@interface VLCEventManager : NSObject
+{
+    NSMutableArray *    messageQueue;
+    pthread_t           dispatcherThread;
+    pthread_mutex_t     queueLock;
+    pthread_cond_t      signalData;
+}
+
+/* Return the default manager */
++ (id)sharedManager;
+
+- (void)callOnMainThreadDelegateOfObject:(id)aTarget withDelegateMethod:(SEL)aSelector withNotificationName:(NSString *)aNotificationName;
+- (void)callOnMainThreadObject:(id)aTarget withMethod:(SEL)aSelector withArgumentAsObject: (id)arg;
+@end

+ 68 - 0
Headers/VLCLibrary.h

@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * VLCLibrary.h: VLC.framework VLCLibrary implementation
+ *****************************************************************************
+ * 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>
+
+#include <vlc/libvlc.h>
+#include <vlc/libvlc_structures.h>
+
+#import <VLC/VLCPlaylist.h>
+
+/*
+ * VLCLibrary object
+ */
+
+@interface VLCLibrary : NSObject
++ (libvlc_instance_t *)sharedInstance;
+@end
+
+/*
+ * Utility function
+ */
+#define quit_on_exception( ex ) __quit_on_exception( ex, __FUNCTION__, __FILE__, __LINE__ )
+static inline void __quit_on_exception( libvlc_exception_t * ex, const char * function, const char * file, int line_number )
+{
+    if (libvlc_exception_raised( ex ))
+    {
+        /* XXX: localization */
+        NSRunCriticalAlertPanel( @"Error", [NSString stringWithFormat:@"libvlc has thrown us an error: %s (%s:%d %s)", libvlc_exception_get_message(ex), file, line_number, function], @"Quit", nil, nil );
+        exit( ex->i_code );
+    }
+}
+
+/*
+ * LibVLCBridging category
+ */
+
+@interface VLCPlaylist (LibVLCBridging)
++ (id) playlistWithLibVLCMediaList: (libvlc_media_list_t *)p_new_mlist;
+- (libvlc_media_list_t *) libVLCMediaList;
+@end
+
+@interface VLCMedia (LibVLCBridging)
+- (id) initWithLibVLCMediaDescriptor:  (libvlc_media_descriptor_t *)p_md;
++ (id) mediaWithLibVLCMediaDescriptor: (libvlc_media_descriptor_t *)p_md;
+- (libvlc_media_descriptor_t *) libVLCMediaDescriptor;
+@end

+ 157 - 0
Makefile

@@ -0,0 +1,157 @@
+CC=gcc
+CFLAGS=-g -O2
+OBJCFLAGS=-fobjc-exceptions 
+LDFLAGS=-single_module -read_only_relocs suppress
+
+# We should set this properly.
+srcdir=../../..
+LIBVLC=$(srcdir)/src/.libs/libvlc.1.dylib $(srcdir)/src/.libs/libvlc-control.0.dylib
+LIBVLC_HEADERS=$(srcdir)/include
+VLCCONFIG=$(srcdir)/vlc-config
+
+MODULES = $(patsubst %,$(SRC_DIR)/%,$(_MODULES))
+
+HEADERS_DIR = Headers
+
+_EXPORTED_HEADERS= \
+     VLC/VLC.h \
+     VLC/VLCMedia.h \
+     VLC/VLCMediaDiscoverer.h \
+     VLC/VLCMediaLibrary.h \
+     VLC/VLCPlaylist.h \
+     VLC/VLCPlaylistDataSource.h \
+     VLC/VLCServicesDiscoverer.h \
+     VLC/VLCTime.h \
+     VLC/VLCVideoView.h
+
+EXPORTED_HEADERS = $(patsubst %,$(HEADERS_DIR)/%,$(_EXPORTED_HEADERS))
+
+EXPORTED_RESOURCES= \
+     Resources/Info.plist \
+     Resources/version.plist
+
+SRC_DIR = Sources
+
+_SRC = \
+     test.m \
+     VLCEventManager.m \
+     VLCLibrary.m \
+	 VLCMedia.m \
+	 VLCMediaLibrary.m \
+     VLCMediaDiscoverer.m \
+	 VLCPlaylist.m \
+     VLCPlaylistDataSource.m \
+     VLCServicesDiscoverer.m \
+     VLCTime.m \
+     VLCVideoView.m
+
+SRC = $(patsubst %,$(SRC_DIR)/%,$(_SRC))
+
+HEADERS = $(EXPORTED_HEADERS)
+
+INCLUDES=  -I .  -I $(LIBVLC_HEADERS) -I $(HEADERS_DIR)
+
+FRAMEWORKS= -framework Cocoa  
+
+OBJECTS=$(SRC:.m=.o)
+
+all: VLC.framework
+
+$(OBJECTS): $(HEADERS)
+
+.m.o: $<
+	$(CC) -c $(CFLAGS) $(OBJCFLAGS) $(INCLUDES) $< -o $@
+
+DIR = VLC.framework \
+      VLC.framework/Version/Current/Framework \
+      VLC.framework/Version/Current/Headers \
+
+VLC.framework/lib/libvlc.dylib: $(srcdir)/src/.libs/libvlc.dylib VLC.framework/lib
+	cp -f $(srcdir)/src/.libs/libvlc.1.dylib VLC.framework/lib/libvlc.dylib && \
+	install_name_tool -id `pwd`/VLC.framework/lib/libvlc.1.dylib \
+	                   VLC.framework/lib/libvlc.dylib
+
+VLC.framework/lib/libvlc-control.dylib: $(srcdir)/src/.libs/libvlc-control.dylib VLC.framework/lib
+	mkdir -p VLC.framework/Version/Current/lib && \
+	cp -f $< $@ && \
+	install_name_tool -id `pwd`/$@ $@ && \
+	install_name_tool -change /usr/local/lib/libvlc.1.dylib \
+	                          `pwd`/VLC.framework/lib/libvlc.dylib  $@
+
+
+VLC.framework/Headers: $(HEADERS)
+	mkdir -p VLC.framework/Version/Current/Headers && \
+	cp -f $(EXPORTED_HEADERS) VLC.framework/Version/Current/Headers && \
+	ln -sf Version/Current/Headers VLC.framework
+
+VLC.framework/Resources:
+	mkdir -p VLC.framework/Version/Current/Resources && \
+	cp -f $(EXPORTED_RESOURCES) VLC.framework/Version/Current/Resources && \
+	ln -sf Version/Current/Resources VLC.framework
+
+
+VLC.framework/modules:
+	/usr/bin/install -c -d ./VLC.framework/Version/Current/modules && \
+	for i in `top_builddir="$(srcdir)" $(VLCCONFIG) --target plugin` ; do \
+	  if test -n "$$i" ; \
+        then \
+	    cp "`pwd`/`dirname $$i`/.libs/`basename $$i`.dylib" \
+	       "./VLC.framework/Version/Current/modules" ; \
+		module="./VLC.framework/Version/Current/modules/`basename $$i`.dylib"; \
+	    install_name_tool -change /usr/local/lib/libvlc.1.dylib \
+                                  @loader_path/../lib/libvlc.dylib \
+                          "$$module"; \
+	    echo "changing install name of $$module";\
+	    for lib in `otool -L "$$module" | grep @executable_path | sed 's/(\([0-z]*\ *\.*\,*\)*)//g'` ; do \
+	        install_name_tool -change "$$lib" \
+                                       `echo "$$lib" | sed 's:executable_path:loader_path/../:'` \
+                              "$$module"; \
+	    done; \
+	  fi \
+    done && \
+	ln -sf Version/Current/modules VLC.framework
+	
+
+VLC.framework/share:
+	cp -R $(srcdir)/share ./VLC.framework/Version/Current && \
+	ln -sf Version/Current/share ./VLC.framework
+
+VLC.framework/lib: 
+	mkdir -p VLC.framework/Version/Current/lib && \
+	if test -d $(srcdir)/extras/contrib/vlc-lib; then \
+	  for i in $(srcdir)/extras/contrib/vlc-lib/*.dylib ; do \
+		module="VLC.framework/Version/Current/lib/`basename $${i}`"; \
+	    cp `pwd`/$${i}  $${module} ; \
+		install_name_tool -change /usr/local/lib/libvlc.1 @loader_path/../lib/libvlc.dylib \
+		                  $${module}; \
+	    echo "changing install name of $$module";\
+	    for lib in `otool -L "$$module" | grep @executable_path | sed 's/(\([0-z]*\ *\.*\,*\)*)//g'` ; do \
+	        install_name_tool -change "$$lib" \
+                                       `echo "$$lib" | sed 's:executable_path:loader_path/../:'` \
+                              "$$module"; \
+	    done; \
+	  done \
+    fi && \
+	ln -sf Version/Current/lib VLC.framework
+    
+VLC.framework/VLC:
+	ln -sf Version/Current/VLC VLC.framework
+
+VLC.framework/Version/Current/VLC: $(OBJECTS) $(LIBVLC) VLC.framework/Headers VLC.framework/Resources VLC.framework/lib/libvlc-control.dylib VLC.framework/lib/libvlc.dylib VLC.framework/modules VLC.framework/share VLC.framework/VLC
+	mkdir -p VLC.framework/Version/Current/Framework && \
+	$(CXX) -dynamiclib $(LDFLAGS) $(OBJECTS) $(FRAMEWORKS) $(LIBVLC) $(MODULES) $(LIBS) -install_name @loader_path/../Frameworks/VLC.framework/Version/Current/VLC -o VLC.framework/Version/Current/VLC && \
+	install_name_tool -change /usr/local/lib/libvlc-control.0.dylib \
+	                          `pwd`/VLC.framework/lib/libvlc-control.dylib \
+	                   VLC.framework/Version/Current/VLC && \
+	install_name_tool -change /usr/local/lib/libvlc.1.dylib \
+	                          `pwd`/VLC.framework/lib/libvlc.dylib \
+	                   VLC.framework/Version/Current/VLC && \
+	touch VLC.framework
+
+VLC.framework:: VLC.framework/Version/Current/VLC
+ 
+.PHONY: clean
+
+clean:
+	rm -Rf VLC.framework
+	rm -Rf $(OBJECTS) *.o $(SRC_DIR)/*.o

+ 22 - 0
Resources/Info.plist

@@ -0,0 +1,22 @@
+<?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">
+<plist version="1.0">
+<dict>
+        <key>CFBundleDevelopmentRegion</key>
+        <string>English</string>
+        <key>CFBundleExecutable</key>
+        <string>Quartz</string>
+        <key>CFBundleIdentifier</key>
+        <string>org.videolan.vlcframework</string>
+        <key>CFBundleInfoDictionaryVersion</key>
+        <string>6.0</string>
+        <key>CFBundleName</key>
+        <string>VLC</string>
+        <key>CFBundlePackageType</key>
+        <string>FMWK</string>
+        <key>CFBundleShortVersionString</key>
+        <string>0.1</string>
+        <key>CFBundleVersion</key>
+        <string>0.1</string>
+</dict>
+</plist>

+ 12 - 0
Resources/version.plist

@@ -0,0 +1,12 @@
+<?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">
+<plist version="1.0">
+<dict>
+	<key>CFBundleShortVersionString</key>
+	<string>0.1</string>
+	<key>CFBundleVersion</key>
+	<string>0.1</string>
+	<key>ProjectName</key>
+	<string>VLC</string>
+</dict>
+</plist>

+ 218 - 0
Sources/VLCEventManager.m

@@ -0,0 +1,218 @@
+/*****************************************************************************
+ * VLCTime.h: VLC.framework VLCTime implementation
+ *****************************************************************************
+ * 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 "VLCEventManager.h"
+#import <pthread.h>
+
+static VLCEventManager * defaultManager = NULL;
+
+enum message_type_t
+{
+    VLCNotification,
+    VLCObjectMethodWithObjectArg
+};
+
+struct message {
+    id target;
+    SEL sel;
+    union u
+    {
+        NSString * name;
+        id object;
+    } u;
+    enum message_type_t type;
+};
+
+@interface VLCEventManager (Private)
+- (void)callDelegateOfObjectAndSendNotificationWithArgs:(NSData*)data;
+- (void)callObjectMethodWithArgs:(NSData*)data;
+- (void)callDelegateOfObject:(id) aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName;
+- (pthread_cond_t *)signalData;
+- (pthread_mutex_t *)queueLock;
+- (NSMutableArray *)messageQueue;
+@end
+
+static void * EventDispatcherMainLoop(void * user_data)
+{
+    VLCEventManager * self = user_data;
+
+    for(;;)
+    {
+        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+        struct message * message, * message_newer = NULL;
+        NSData *dataMessage;
+        int i;
+
+        /* Wait for some data */
+        pthread_mutex_lock( [self queueLock] );
+        
+        /* Wait until we have something on the queue */
+        if ([[self messageQueue] count] <= 0 ) do {
+            pthread_cond_wait( [self signalData], [self queueLock] );
+        } while([[self messageQueue] count] <= 0 );
+        
+        message = (struct message *)[(NSData *)[[self messageQueue] lastObject] bytes];
+        
+        /* Don't send the same notification twice */
+        if( message->type == VLCNotification )
+        {
+            for( i = 0; i < [[self messageQueue] count]-1; i++ )
+            {
+                message_newer = (struct message *)[(NSData *)[[self messageQueue] objectAtIndex: i] bytes];
+                if( message_newer->type != VLCNotification )
+                    continue;
+                if( message_newer->target == message->target && message_newer->target == message->target && [message_newer->u.name isEqualToString:message->u.name] )
+                {
+                    [message_newer->target release];
+                    [message->u.name release];
+                    [[self messageQueue] removeObjectAtIndex: i];
+                    i--;
+                }
+            }
+        }
+
+        dataMessage = [[self messageQueue] lastObject];
+        
+        pthread_mutex_unlock( [self queueLock] );
+        
+        if( message->type == VLCNotification )
+            [self performSelectorOnMainThread:@selector(callDelegateOfObjectAndSendNotificationWithArgs:) withObject:[dataMessage retain] waitUntilDone: NO];
+        else
+            [self performSelectorOnMainThread:@selector(callObjectMethodWithArgs:) withObject:[dataMessage retain] waitUntilDone: NO];
+
+        pthread_mutex_lock( [self queueLock] );
+        [[self messageQueue] removeLastObject];
+        pthread_mutex_unlock( [self queueLock] );
+    
+        [pool release];
+    }
+}
+
+@implementation VLCEventManager
++ (id)sharedManager
+{
+    /* We do want a lock here to avoid leaks */
+    if ( !defaultManager )
+    {
+        defaultManager = [[VLCEventManager alloc] init];
+    }
+
+    return defaultManager;
+}
+
+- (id)init
+{
+    if( self = [super init] )
+    {
+        pthread_mutex_init( &queueLock, NULL );
+        pthread_cond_init( &signalData, NULL );
+        pthread_create( &dispatcherThread, NULL, EventDispatcherMainLoop, self );
+        messageQueue = [[NSMutableArray alloc] initWithCapacity:10];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    pthread_kill( dispatcherThread, SIGKILL );
+    pthread_join( dispatcherThread, NULL );
+    [super dealloc];
+}
+
+- (void)callOnMainThreadDelegateOfObject:(id)aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName
+{
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+    struct message message = { [aTarget retain], aSelector, [aNotificationName retain], VLCNotification };
+    pthread_mutex_lock( [self queueLock] );
+    [[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(struct message)] atIndex:0];
+    pthread_cond_signal( [self signalData] );
+    pthread_mutex_unlock( [self queueLock] );
+    [pool release];
+}
+
+- (void)callOnMainThreadObject:(id)aTarget withMethod:(SEL)aSelector withArgumentAsObject: (id)arg
+{
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+    struct message message = { [aTarget retain], aSelector, [arg retain], VLCObjectMethodWithObjectArg };
+    pthread_mutex_lock( [self queueLock] );
+    [[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(struct message)] atIndex:0];
+    pthread_cond_signal( [self signalData] );
+    pthread_mutex_unlock( [self queueLock] );
+    [pool release];
+}
+@end
+
+@implementation VLCEventManager (Private)
+- (void)callDelegateOfObjectAndSendNotificationWithArgs:(NSData*)data
+{
+    struct message * message = (struct message *)[data bytes];
+
+    [self callDelegateOfObject:message->target withDelegateMethod:message->sel withNotificationName:message->u.name];
+    [message->u.name release];
+    [message->target release];
+    [data release];
+}
+
+- (void)callObjectMethodWithArgs:(NSData*)data
+{
+    struct message * message = (struct message *)[data bytes];
+    void (*method)(id, SEL, id) = (void (*)(id, SEL, id))[message->target methodForSelector: message->sel];
+
+    method( message->target, message->sel, message->u.object);
+    [message->u.object release];
+    [message->target release];
+    [data release];
+}
+
+
+- (NSMutableArray *)messageQueue
+{
+    return messageQueue;
+}
+- (pthread_cond_t *)signalData
+{
+    return &signalData;
+}
+
+- (pthread_mutex_t *)queueLock
+{
+    return &queueLock;
+}
+
+- (void)callDelegateOfObject:(id) aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName
+{
+    NSMethodSignature * aSignature;
+    NSInvocation * anInvocation;
+
+    [[NSNotificationCenter defaultCenter] postNotification: [NSNotification notificationWithName:aNotificationName object:aTarget]];
+
+    if (![aTarget delegate] || ![[aTarget delegate] respondsToSelector: aSelector])
+        return;
+
+    /* NSInvocation could maybe be prefered here */
+    void (*method)(id, SEL, id) = (void (*)(id, SEL, id))[[aTarget delegate] methodForSelector: aSelector];
+    method( [aTarget delegate], aSelector, [NSNotification notificationWithName:aNotificationName object:aTarget]);
+
+}
+@end

+ 44 - 0
Sources/VLCLibrary.m

@@ -0,0 +1,44 @@
+/*****************************************************************************
+ * VLCLibrary.h: VLC.framework VLCLibrary implementation
+ *****************************************************************************
+ * 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 "VLCLibrary.h"
+
+static libvlc_instance_t * shared_instance = NULL;
+
+@implementation VLCLibrary
++ (libvlc_instance_t *)sharedInstance
+{
+    if(!shared_instance)
+    {
+        libvlc_exception_t ex;
+        char *lib_vlc_params[] = { "vlc", "-I", "dummy", "-vvvvvv" };
+        libvlc_exception_init( &ex );
+        
+        shared_instance = libvlc_new( 4, lib_vlc_params, &ex );
+        quit_on_exception( &ex );
+    }
+    return shared_instance;
+}
+@end
+

+ 257 - 0
Sources/VLCMedia.m

@@ -0,0 +1,257 @@
+/*****************************************************************************
+ * VLCMedia.m: VLC.framework VLCMedia implementation
+ *****************************************************************************
+ * 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/VLCMedia.h>
+#import <VLC/VLCPlaylist.h>
+#import "VLCEventManager.h"
+#import "VLCLibrary.h"
+
+#include <vlc/libvlc.h>
+
+NSString * VLCMetaInformationTitle = @"title";
+NSString * VLCMetaInformationAuthor = @"author";
+NSString * VLCMetaInformationArtwork = @"artwork";
+
+/* Our notification */
+NSString * VLCMediaSubItemAdded = @"VLCMediaSubItemAdded";
+NSString * VLCMediaMetaChanged = @"VLCMediaMetaChanged";
+
+/* libvlc event callback */
+static void HandleMediaSubItemAdded( const libvlc_event_t * event, void * self)
+{
+    [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject: self
+                                     withDelegateMethod: @selector(subItemAdded:)
+                                     withNotificationName: VLCMediaSubItemAdded];
+}
+
+/* libvlc event callback */
+static void HandleMediaMetaChanged( const libvlc_event_t * event, void * self)
+{
+    [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject: self
+                                     withDelegateMethod: @selector(metaChanged:)
+                                     withNotificationName: VLCMediaMetaChanged];
+
+}
+
+@interface VLCMedia (Private)
+- (void)initializeInternalMediaDescriptor;
+- (void)subItemAdded:(NSNotification *)notification;
+- (void)metaChanged:(NSNotification *)notification;
+- (void)fetchMetaInformation;
+@end
+
+@implementation VLCMedia (Private)
+- (void)initializeInternalMediaDescriptor
+{
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(subItemAdded:) name:VLCMediaSubItemAdded object:self];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(metaChanged:) name:VLCMediaMetaChanged object:self];
+    libvlc_exception_t ex;
+    libvlc_exception_init( &ex );
+    libvlc_event_manager_t * p_em = libvlc_media_descriptor_event_manager( md, &ex );
+    libvlc_event_attach( p_em, libvlc_MediaDescriptorSubItemAdded, HandleMediaSubItemAdded, self, &ex );
+    libvlc_event_attach( p_em, libvlc_MediaDescriptorMetaChanged, HandleMediaMetaChanged, self, &ex );
+    quit_on_exception( &ex );
+    libvlc_media_list_t * p_mlist = libvlc_media_descriptor_subitems( md, NULL );
+    if (!p_mlist)
+        subitems = nil;
+    else
+    {
+        subitems= [[VLCPlaylist playlistWithLibVLCMediaList: p_mlist] retain];
+        libvlc_media_list_release( p_mlist );
+    }
+    [self fetchMetaInformation];
+}
+
+- (void)subItemAdded:(NSNotification *)notification
+{
+    if(!subitems)
+    {
+        libvlc_media_list_t * p_mlist = libvlc_media_descriptor_subitems( md, NULL );
+        [self willChangeValueForKey:@"subitems"];
+        subitems = [[VLCPlaylist playlistWithLibVLCMediaList: p_mlist] retain];
+        [self didChangeValueForKey:@"subitems"];
+        libvlc_media_list_release( p_mlist );
+    }
+}
+- (void)metaChanged:(NSNotification *)notification
+{
+    [self fetchMetaInformation];
+}
+
+- (void)fetchMetaInformation
+{
+    NSMutableDictionary * temp;
+    libvlc_exception_t ex;
+    char * title;
+    char * artist;
+    char * arturl = NULL;
+
+    libvlc_exception_init( &ex );
+
+    title = libvlc_media_descriptor_get_meta( md, libvlc_meta_Title, &ex );
+    quit_on_exception( &ex );
+
+    artist = libvlc_media_descriptor_get_meta( md, libvlc_meta_Artist, &ex );
+    quit_on_exception( &ex );
+
+    arturl = libvlc_media_descriptor_get_meta( md, libvlc_meta_ArtworkURL, &ex );
+    quit_on_exception( &ex );
+
+    temp = [NSMutableDictionary dictionaryWithCapacity: 2];
+
+    if (title)
+        [temp setObject: [NSString stringWithUTF8String: title] forKey: VLCMetaInformationTitle];
+    
+#if 0
+    /* We need to perform that in a thread because this takes long. */
+    if (arturl)
+    {
+        NSString *plainStringURL = [NSString stringWithUTF8String:arturl];
+        NSString *escapedStringURL = [plainStringURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+        NSURL *aURL = [NSURL URLWithString:escapedStringURL];
+        NSImage * art =  [[NSImage alloc] initWithContentsOfURL: aURL];
+        [art autorelease];
+        if( art )
+            [temp setObject: art forKey: VLCMetaInformationArtwork];
+    }
+#endif
+
+    free( title );
+    free( artist );
+    free( arturl );
+
+    [self willChangeValueForKey:@"metaInformation"];
+    if( metaInformation )
+        [metaInformation release];
+    metaInformation = [[NSMutableDictionary alloc] initWithDictionary:temp];
+    [self didChangeValueForKey:@"metaInformation"];
+}
+@end
+
+@implementation VLCMedia
+- (id)initWithURL:(NSString *)anURL
+{
+    if (self = [super init])
+    {
+        libvlc_exception_t ex;
+        url = [anURL copy];
+
+        libvlc_exception_init( &ex );
+        
+        md = libvlc_media_descriptor_new( [VLCLibrary sharedInstance],
+                                          [anURL cString],
+                                          &ex );
+        quit_on_exception( &ex );
+        metaInformation = nil;
+        [self initializeInternalMediaDescriptor];
+    }
+    return self;
+}
+
++ (id)mediaWithURL:(NSString *)anURL;
+{
+    return [[(VLCMedia*)[VLCMedia alloc] initWithURL: anURL ] autorelease];
+}
+
+- (void)release
+{
+    @synchronized(self)
+    {
+        if([self retainCount] <= 1)
+        {
+            /* We must make sure we won't receive new event after an upcoming dealloc
+             * We also may receive a -retain in some event callback that may occcur
+             * Before libvlc_event_detach. So this can't happen in dealloc */
+            libvlc_event_manager_t * p_em = libvlc_media_descriptor_event_manager( md, NULL );
+            libvlc_event_detach( p_em, libvlc_MediaDescriptorSubItemAdded, HandleMediaSubItemAdded, self, NULL );
+            libvlc_event_detach( p_em, libvlc_MediaDescriptorMetaChanged, HandleMediaMetaChanged, self, NULL );
+        }
+        [super release];
+    }
+}
+
+- (void) dealloc
+{
+    if( subitems )
+        [subitems release];
+    if( metaInformation )
+        [metaInformation release];
+    libvlc_media_descriptor_release( md );
+    [url release];
+    [super dealloc];
+}
+
+- (NSString *)url
+{
+    return [[url copy] autorelease];
+}
+
+- (VLCPlaylist *)subitems
+{
+    return subitems;
+}
+
+/* Returns a dictionary with corresponding object associated with a meta */
+- (NSDictionary *)metaInformation
+{
+    return metaInformation;
+}
+/* Not supported yet */
+- (id)delegate
+{
+    return nil;
+}
+@end
+
+@implementation VLCMedia (LibVLCBridging)
+- (id) initWithLibVLCMediaDescriptor: (libvlc_media_descriptor_t *)p_md
+{
+    if (self = [super init])
+    {
+        libvlc_exception_t ex;
+        char * p_url;
+        libvlc_exception_init( &ex );
+
+        p_url = libvlc_media_descriptor_get_mrl( p_md, &ex );
+        quit_on_exception( &ex );
+        url = [[NSString stringWithCString: p_url] retain];
+        libvlc_media_descriptor_retain( p_md );   
+        md = p_md;
+        [self initializeInternalMediaDescriptor];
+    }
+    return self;
+}
+
++ (id) mediaWithLibVLCMediaDescriptor: (libvlc_media_descriptor_t *)p_md
+{
+    return [[[VLCMedia alloc] initWithLibVLCMediaDescriptor: p_md] autorelease];
+}
+
+- (libvlc_media_descriptor_t *) libVLCMediaDescriptor
+{
+    libvlc_media_descriptor_retain( md );
+    return md;
+}
+@end

+ 110 - 0
Sources/VLCMediaDiscoverer.m

@@ -0,0 +1,110 @@
+/*****************************************************************************
+ * VLCMediaDiscoverer.m: VLC.framework VLCMediaDiscoverer implementation
+ *****************************************************************************
+ * 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/VLCMediaDiscoverer.h>
+#import "VLCLibrary.h"
+
+#include <vlc/libvlc.h>
+
+
+@implementation VLCMediaDiscoverer
+- (id)initWithName:(NSString *)aServiceName
+{
+    if (self = [super init])
+    {
+        libvlc_exception_t ex;
+        libvlc_exception_init( &ex );
+        localizedName = nil;
+        playlist = nil;
+        mdis = libvlc_media_discoverer_new_from_name( [VLCLibrary sharedInstance],
+                                                      [aServiceName cString],
+                                                      &ex );
+        quit_on_exception( &ex );       
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    if( localizedName )
+        [localizedName release];
+    if( playlist )
+        [playlist release];
+    libvlc_media_discoverer_release( mdis );
+    [super dealloc];
+}
+
+- (VLCPlaylist *) playlist
+{
+    if( playlist )
+        return playlist;
+
+    libvlc_media_list_t * p_mlist = libvlc_media_discoverer_media_list( mdis );
+    VLCPlaylist * ret = [VLCPlaylist playlistWithLibVLCMediaList: p_mlist];
+    libvlc_media_list_release( p_mlist );
+
+    /* Hack until this gets done properly upstream */
+    char * name = libvlc_media_discoverer_localized_name( mdis );
+    if( !name )
+    {
+        VLCMedia * media = [ret mediaAtIndex: 0];
+        ret = media ? (VLCPlaylist *)[media subitems] : nil;
+    }
+    free(name);
+
+    if( ret )
+    {
+        playlist = [ret retain];
+    }
+    return ret;
+}
+
+- (NSString *)localizedName
+{
+    NSString * ret = nil;
+    char * name = libvlc_media_discoverer_localized_name( mdis );
+
+    if( localizedName )
+        return localizedName;
+
+    if (name)
+    {
+        ret = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
+        free( name );
+    }
+    /* XXX: Hack until this gets done properly upstream. This is really slow. */
+    if (!ret)
+    {
+        libvlc_media_list_t * p_mlist = libvlc_media_discoverer_media_list( mdis );
+        ret = [[[[VLCPlaylist playlistWithLibVLCMediaList: p_mlist] mediaAtIndex:0] metaInformation] objectForKey: VLCMetaInformationTitle];
+        libvlc_media_list_release( p_mlist );
+    }
+    if( ret )
+    {
+        localizedName = [ret retain];
+    }
+    return localizedName;
+}
+@end

+ 87 - 0
Sources/VLCMediaLibrary.m

@@ -0,0 +1,87 @@
+/*****************************************************************************
+ * VLCMediaDiscoverer.m: VLC.framework VLCMediaDiscoverer implementation
+ *****************************************************************************
+ * 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/VLCMediaLibrary.h>
+#import "VLCLibrary.h"
+
+#include <vlc/libvlc.h>
+
+static VLCMediaLibrary * sharedMediaLibrary = NULL;
+
+@implementation VLCMediaLibrary
++ (id)sharedMediaLibrary
+{
+    if( !sharedMediaLibrary )
+    {
+        sharedMediaLibrary = [[VLCMediaLibrary alloc] init];
+    }
+    return sharedMediaLibrary;
+}
+
+- (id)init
+{
+    if (self = [super init])
+    {
+        libvlc_exception_t p_e;
+        libvlc_exception_init( &p_e );
+        mlib = libvlc_media_library_new( [VLCLibrary sharedInstance], &p_e );
+        quit_on_exception( &p_e );
+        libvlc_media_library_load( mlib, &p_e );
+        quit_on_exception( &p_e );
+        allMedia = nil;
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    if (allMedia)
+        [allMedia release];
+    libvlc_media_library_release( mlib );
+    [super dealloc];
+}
+
+- (VLCPlaylist *)allMedia
+{
+    if (!allMedia)
+    {
+        libvlc_media_list_t * p_mlist = libvlc_media_library_media_list( mlib, NULL );
+        libvlc_media_list_t * p_flat_mlist = libvlc_media_list_flat_media_list( p_mlist, NULL );
+        allMedia = [[VLCPlaylist playlistWithLibVLCMediaList: p_flat_mlist] retain];
+        libvlc_media_list_release( p_flat_mlist );
+        libvlc_media_list_release( p_mlist );
+    }
+    return allMedia;
+}
+
+- (NSArray *) playlists
+{
+    libvlc_media_list_t * p_mlist = libvlc_media_library_media_list( mlib, NULL );
+    VLCPlaylist * playlist = [VLCPlaylist playlistWithLibVLCMediaList: p_mlist];
+    libvlc_media_list_release( p_mlist );
+    NSArray * ret = [playlist sublists];
+    return ret;
+}
+@end

+ 355 - 0
Sources/VLCPlaylist.m

@@ -0,0 +1,355 @@
+/*****************************************************************************
+ * VLCPlaylist.h: VLC.framework VLCPlaylist implementation
+ *****************************************************************************
+ * 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 <VLC/VLCPlaylist.h>
+#import "VLCLibrary.h"
+#import "VLCEventManager.h"
+#import <vlc/vlc.h>
+#import <vlc/libvlc.h>
+
+/* Our notification */
+NSString * VLCPlaylistItemChanged = @"VLCPlaylistItemChanged";
+NSString * VLCPlaylistItemDeleted = @"VLCPlaylistItemDeleted";
+NSString * VLCPlaylistItemAdded   = @"VLCPlaylistItemAdded";
+
+@interface VLCPlaylist (Private)
+- (void)initializeInternalMediaList;
+
+- (void)removeObjectFromLibVLCInItemsAtIndex:(int) i;
+- (void)insertObjectFromLibVLC:(id)object inItemsAtIndex:(int) i;
+@end
+
+@interface VLCPlaylist (Binding)
+/* Bindings */
+- (unsigned int)countOfItems;
+- (id)objectInItemsAtIndex:(unsigned int)index;
+- (void)insertObject:(id)anObject inItemsAtIndex:(unsigned int)index;
+- (void)replaceObjectInItemsAtIndex:(unsigned int)index withObject:(id)anObject;
+@end
+
+/* libvlc event callback */
+static void HandleMediaListItemDeleted( const libvlc_event_t * event, void * user_data)
+{
+    id self = user_data;
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+#ifdef DONT_UPDATE_VARIABLES_FROM_NON_MAIN_THREAD_CAUSE_BINDINGS_DONT_LIKE
+    /* That would be nice to sync self's variables on non main thread, but
+     * I did experience some Bindings related crash with an NSTreeController */
+    [self removeObjectFromLibVLCInItemsAtIndex: event->u.media_list_item_deleted.index];
+#endif
+    [[VLCEventManager sharedManager] callOnMainThreadObject:self withMethod:@selector(playlistItemRemoved:) withArgumentAsObject:
+                                        [NSNumber numberWithInt: event->u.media_list_item_deleted.index] ];
+
+#ifdef DONT_SEND_NOTIFICATION_BECAUSE_WE_DONT_HAVE_TO
+    /* This was disabled to avoid non necessary overhead, but we may want to
+     * retablish that once the rest becomes more stable */
+    [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject: self
+                                     withDelegateMethod: @selector(playlistItemAdded:)
+                                     withNotificationName: VLCPlaylistItemDeleted];
+#endif
+    [pool release];
+}
+
+/* libvlc event callback */
+static void HandleMediaListItemAdded( const libvlc_event_t * event, void * user_data)
+{
+    id self = user_data;
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+#ifdef DONT_UPDATE_VARIABLES_FROM_NON_MAIN_THREAD_CAUSE_BINDINGS_DONT_LIKE
+    [self insertObjectFromLibVLC: [VLCMedia mediaWithLibVLCMediaDescriptor: event->u.media_list_item_added.item]
+          inItemsAtIndex: event->u.media_list_item_added.index ];
+#endif
+    [[VLCEventManager sharedManager] callOnMainThreadObject:self withMethod:@selector(playlistItemAdded:) withArgumentAsObject:
+                            [NSArray arrayWithObjects: [VLCMedia mediaWithLibVLCMediaDescriptor: event->u.media_list_item_added.item],
+                                                       [NSNumber numberWithInt: event->u.media_list_item_added.index], nil ] ];
+
+#ifdef DONT_SEND_NOTIFICATION_BECAUSE_WE_DONT_HAVE_TO
+    [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject: self
+                                     withDelegateMethod: @selector(playlistItemAdded:)
+                                     withNotificationName: VLCPlaylistItemAdded];
+#endif
+    [pool release];
+}
+
+@implementation VLCPlaylist (Private)
+- (void)initializeInternalMediaList
+{
+    libvlc_exception_t p_e;
+    int i;
+    [self lock];
+    items = [[NSMutableArray alloc] init];
+
+    for( i = 0; i < libvlc_media_list_count( p_mlist, NULL ); i++ )
+    {
+        libvlc_media_descriptor_t * p_md;
+        p_md = libvlc_media_list_item_at_index( p_mlist, i, NULL );
+        [items addObject:[VLCMedia mediaWithLibVLCMediaDescriptor: p_md]];
+        libvlc_media_descriptor_release( p_md );
+    }
+
+    libvlc_event_manager_t * p_em = libvlc_media_list_event_manager( p_mlist, &p_e );
+    libvlc_exception_init( &p_e );
+    libvlc_event_attach( p_em, libvlc_MediaListItemDeleted, HandleMediaListItemDeleted, self, &p_e );
+    libvlc_event_attach( p_em, libvlc_MediaListItemAdded,   HandleMediaListItemAdded,   self, &p_e );
+    [self unlock];
+    quit_on_exception( &p_e );
+}
+
+/* LibVLC callback, executed on main thread */
+- (void)playlistItemAdded:(NSArray *)args
+{
+    [self insertObjectFromLibVLC: [args objectAtIndex: 0]
+          inItemsAtIndex: [[args objectAtIndex: 1] intValue] ];
+}
+
+- (void)playlistItemRemoved:(NSNumber *)index
+{
+    [self removeObjectFromLibVLCInItemsAtIndex: [index intValue] ];
+}
+
+/* When LibVLC change its mlist's item this functions gets called */
+- (void)removeObjectFromLibVLCInItemsAtIndex:(int) i
+{
+    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:[NSIndexSet indexSetWithIndex:i] forKey:@"items"];
+    [items removeObjectAtIndex:i];
+    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:[NSIndexSet indexSetWithIndex:i] forKey:@"items"];
+}
+
+- (void)insertObjectFromLibVLC:(id)object inItemsAtIndex:(int) i
+{
+    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:i] forKey:@"items"];
+    [items insertObject:object atIndex: i];
+    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:i] forKey:@"items"];
+}
+
+@end
+
+@implementation VLCPlaylist (Binding)
+/* "items" bindings */
+- (unsigned int)countOfItems 
+{
+    return [items count];
+}
+
+- (id)objectInItemsAtIndex:(unsigned int)index 
+{
+    return [items objectAtIndex:index];
+}
+
+/* Setters go through LibVLC */
+- (void)insertObject:(id)anObject inItemsAtIndex:(unsigned int)index 
+{
+    [self insertMedia:anObject atIndex:index];
+}
+
+- (void)removeObjectFromItemsAtIndex:(unsigned int)index 
+{
+    [self removeMediaAtIndex:index];
+}
+
+- (void)replaceObjectInItemsAtIndex:(unsigned int)index withObject:(id)anObject 
+{
+    [self removeMediaAtIndex:index];
+    [self insertMedia:anObject atIndex:index];
+}
+@end
+
+
+@implementation VLCPlaylist
+- (id)init
+{
+    [VLCEventManager sharedManager];
+
+    if (self = [super init])
+    {
+        libvlc_exception_t p_e;
+        libvlc_exception_init( &p_e );
+        p_mlist = libvlc_media_list_new( [VLCLibrary sharedInstance], &p_e );
+        quit_on_exception( &p_e );
+        [self initializeInternalMediaList];
+    }
+    return self;
+}
+
+- (void)release
+{
+    @synchronized(self)
+    {
+        if([self retainCount] <= 1)
+        {
+            /* We must make sure we won't receive new event after an upcoming dealloc
+             * We also may receive a -retain in some event callback that may occcur
+             * Before libvlc_event_detach. So this can't happen in dealloc */
+            libvlc_event_manager_t * p_em = libvlc_media_list_event_manager( p_mlist, NULL );
+            libvlc_event_detach( p_em, libvlc_MediaListItemDeleted, HandleMediaListItemDeleted, self, NULL );
+            libvlc_event_detach( p_em, libvlc_MediaListItemAdded,   HandleMediaListItemAdded,   self, NULL );
+        }
+        [super release];
+    }
+}
+
+- (void)dealloc
+{
+    libvlc_media_list_release( p_mlist );
+    [items release];
+    [super dealloc];
+}
+
+- (VLCMedia *)mediaAtIndex: (int)index
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_descriptor_t * p_md = libvlc_media_list_item_at_index( p_mlist, index, &p_e );
+    quit_on_exception( &p_e );
+
+    return [VLCMedia mediaWithLibVLCMediaDescriptor: p_md];
+}
+
+- (int)countMedia
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    int count = libvlc_media_list_count( p_mlist, &p_e );
+    quit_on_exception( &p_e );
+    return count;
+}
+
+- (NSArray *)sublists
+{
+    NSMutableArray * ret = [[NSMutableArray alloc] initWithCapacity: 0];
+    int i, count;
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    count = libvlc_media_list_count( p_mlist, &p_e );
+    quit_on_exception( &p_e );
+
+    for( i = 0; i < count; i++ )
+    {
+        libvlc_media_descriptor_t * p_md;
+        libvlc_media_list_t * p_submlist;
+        p_md = libvlc_media_list_item_at_index( p_mlist, i, NULL );
+        p_submlist = libvlc_media_descriptor_subitems( p_md, NULL );
+        if( p_submlist )
+        {
+            [ret addObject: [VLCPlaylist playlistWithLibVLCMediaList: p_submlist]];
+            libvlc_media_list_release( p_submlist );
+        }
+        libvlc_media_descriptor_release( p_md );
+    }
+    return [ret autorelease];
+}
+
+- (VLCPlaylist *)flatPlaylist
+{
+    VLCPlaylist * flatPlaylist;
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_list_t * p_flat_mlist = libvlc_media_list_flat_media_list( p_mlist, &p_e );
+    quit_on_exception( &p_e );
+    flatPlaylist = [VLCPlaylist playlistWithLibVLCMediaList: p_flat_mlist];
+    libvlc_media_list_release( p_flat_mlist );
+    return flatPlaylist;
+}
+
+- (VLCMedia *)providerMedia
+{
+    VLCMedia * ret;
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_descriptor_t * p_md = libvlc_media_list_media_descriptor( p_mlist, &p_e );
+    ret = [VLCMedia mediaWithLibVLCMediaDescriptor: p_md];
+    libvlc_media_descriptor_release( p_md );
+    quit_on_exception( &p_e );
+    return ret;
+}
+
+- (void)addMedia: (VLCMedia *)item
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_descriptor_t * p_md = [item libVLCMediaDescriptor];
+    libvlc_media_list_add_media_descriptor( p_mlist, p_md, &p_e );
+    libvlc_media_descriptor_release( p_md );
+    quit_on_exception( &p_e );
+}
+
+- (void)insertMedia: (VLCMedia *)item atIndex: (int)index
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_descriptor_t * p_md = [item libVLCMediaDescriptor];
+    libvlc_media_list_insert_media_descriptor( p_mlist, p_md, index, &p_e );
+    libvlc_media_descriptor_release( p_md );
+    quit_on_exception( &p_e );
+
+}
+
+- (void)removeMediaAtIndex: (int)index
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_list_remove_index( p_mlist, index, &p_e );
+    quit_on_exception( &p_e );
+}
+
+- (void)lock
+{
+    libvlc_media_list_lock( p_mlist );
+}
+
+- (void)unlock
+{
+    libvlc_media_list_unlock( p_mlist );
+}
+
+- (id)delegate
+{
+    /* No delegate supported */
+    return nil;
+}
+@end
+
+@implementation VLCPlaylist (LibVLCBridging)
+- (id) initWithLibVLCMediaList: (libvlc_media_list_t *)p_new_mlist;
+{
+    if( self = [super init] )
+    {
+        p_mlist = p_new_mlist;
+        libvlc_media_list_retain( p_mlist );
+        [self initializeInternalMediaList];
+    }
+    return self;
+}
+
++ (id) playlistWithLibVLCMediaList: (libvlc_media_list_t *)p_new_mlist;
+{
+    return [[[VLCPlaylist alloc] initWithLibVLCMediaList: p_new_mlist] autorelease];
+}
+
+- (libvlc_media_list_t *) libVLCMediaList
+{
+    libvlc_media_list_retain( p_mlist );
+    return p_mlist;
+}
+@end

+ 178 - 0
Sources/VLCPlaylistDataSource.m

@@ -0,0 +1,178 @@
+/*****************************************************************************
+ * VLCPlaylistDataSource.m: VLC.framework VLCPlaylistDataSource implementation
+ *****************************************************************************
+ * 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 <VLC/VLCPlaylistDataSource.h>
+#import "VLCEventManager.h"
+
+@implementation VLCPlaylistDataSource
+
+- (id)init
+{
+    if (self = [super init])
+    {
+        playlist = nil;
+        videoView = nil;
+    }
+    return self;
+}
+
+- (id)initWithPlaylist:(VLCPlaylist *)aPlaylist
+{
+    if (self = [super init])
+    {
+
+        playlist = [aPlaylist retain];
+
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(playlistDidChange:) name:VLCPlaylistItemAdded  object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(itemDidAddSubitem:) name:VLCMediaSubItemAdded  object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(itemDidChange:) name:VLCPlaylistItemChanged   object:nil];
+        videoView = nil;
+        outlineView = nil;
+
+    }
+    return self;
+}
+
+- (id)initWithPlaylist:(VLCPlaylist *)aPlaylist videoView:(VLCVideoView *)aVideoView;
+{
+    if (self = [super init])
+    {
+        playlist = [aPlaylist retain];
+
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(playlistDidChange:) name:VLCPlaylistItemAdded object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(itemDidAddSubitem:) name:VLCMediaSubItemAdded object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(itemDidChange:) name:VLCPlaylistItemChanged   object:nil];
+
+        videoView = [aVideoView retain];
+        /* Will be automatically set if an outline view ask us data,
+         * be careful not to connect two outlineView to this object or this goes wrong. */
+        outlineView = nil;
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+
+    if (playlist)
+        [playlist release];
+    if (videoView)
+        [videoView release];
+
+    [super dealloc];
+}
+
+- (VLCPlaylist *)playlist
+{
+    return playlist;
+}
+
+- (VLCVideoView *)videoView
+{
+    return videoView;
+}
+@end
+
+
+
+@implementation VLCPlaylistDataSource (OutlineViewDataSource)
+- (BOOL)  outlineView: (NSOutlineView *)ov isItemExpandable: (id)item { return NO; }
+- (int)   outlineView: (NSOutlineView *)ov numberOfChildrenOfItem:(id)item { return 0; }
+- (id)    outlineView: (NSOutlineView *)ov child:(int)index ofItem:(id)item { return nil; }
+- (id)    outlineView: (NSOutlineView *)ov objectValueForTableColumn:(NSTableColumn*)col byItem:(id)item { return nil; }
+@end
+
+@implementation VLCPlaylistDataSource (TableViewDropping)
+/* Dummy implementation cause we need them */
+- (int)numberOfRowsInTableView:(NSTableView *)aTableView { return 0; }
+- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex {return nil;}
+
+- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op
+{
+    return NSDragOperationEvery; /* This is for now */
+}
+
+- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info
+            row:(int)row dropOperation:(NSTableViewDropOperation)operation
+{
+    int i;
+    NSArray  * droppedItems = [[info draggingPasteboard] propertyListForType: NSFilenamesPboardType];
+ 
+    for (i = 0; i < [droppedItems count]; i++)
+    {
+        NSString * filename = [droppedItems objectAtIndex:i];
+        
+        [[self playlist] insertMedia:[VLCMedia mediaWithURL:filename] atIndex:row+i];
+    }
+
+}
+@end
+
+@interface NSObject (UnknownBindingsObject)
+/* OutlineViewDataSourceDropping and bindings hack */
+- (id)observedObject;
+@end
+
+@implementation VLCPlaylistDataSource (OutlineViewDataSourceDropping)
+- (BOOL)outlineView:(NSOutlineView *)aOutlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
+{
+    NSArray  * droppedItems = [[info draggingPasteboard] propertyListForType: NSFilenamesPboardType];
+    VLCPlaylist * aPlaylist;
+    int i;
+
+    if (!item)
+        item = [self playlist]; /* The root object is our playlist */
+    else
+        item = [item observedObject];
+
+    if (![item  isMemberOfClass:[VLCPlaylist class]])
+        return NO;
+
+    if (index < 0) /* No precise item given, put it as the first one */
+        index = 0;
+
+    aPlaylist = item;
+
+    if (!droppedItems)
+    {
+        /* XXX: localization */
+        NSRunCriticalAlertPanelRelativeToWindow(@"Error", @"Unable to drop the provided item.", @"OK", nil, nil, [outlineView window]);
+        return NO;
+    }
+
+    for (i = 0; i < [droppedItems count]; i++)
+    {
+        NSString * filename = [droppedItems objectAtIndex:i];
+        
+        [aPlaylist insertMedia:[VLCMedia mediaWithURL:filename] atIndex:index+i];
+    }
+    return YES;
+}
+
+- (NSDragOperation)outlineView:(NSOutlineView *)aOutlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
+{
+    return NSDragOperationEvery;
+}
+@end

+ 60 - 0
Sources/VLCServicesDiscoverer.m

@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * VLCMediaDiscoverer.m: VLC.framework VLCMediaDiscoverer implementation
+ *****************************************************************************
+ * 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/VLCServicesDiscoverer.h>
+#import <VLC/VLCMediaDiscoverer.h>
+#import "VLCLibrary.h"
+
+#include <vlc/libvlc.h>
+
+static VLCServicesDiscoverer * sharedDiscoverer = NULL;
+
+@implementation VLCServicesDiscoverer
++ (id)sharedDiscoverer
+{
+    if (!sharedDiscoverer)
+    {
+        sharedDiscoverer = [[self alloc] init];
+    }
+    return sharedDiscoverer;
+}
+
+- (id) init
+{
+    if( self = [super init] )
+    {
+        services = [[NSArray arrayWithObjects:
+                        [[[VLCMediaDiscoverer alloc] initWithName:@"sap"] autorelease],
+                        [[[VLCMediaDiscoverer alloc] initWithName:@"shoutcast"] autorelease],
+                        [[[VLCMediaDiscoverer alloc] initWithName:@"shoutcasttv"] autorelease], nil] retain];
+    }
+    return self;
+}
+
+- (NSArray *) services
+{
+    return [[services copy] autorelease];
+}
+@end

+ 56 - 0
Sources/VLCTime.m

@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * VLCTime.h: VLC.framework VLCTime implementation
+ *****************************************************************************
+ * 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 <VLC/VLCTime.h>
+
+@implementation VLCTime
+- (id)initWithNumber:(NSNumber *)aNumber
+{
+    if (self = [super init])
+    {
+        value = [aNumber copy];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    [value release];
+    [super dealloc];
+}
+
+- (NSNumber *)numberRepresentation
+{
+    [[value copy] autorelease];
+}
+
+- (NSString *)stringRepresentation
+{
+    int hours = [value intValue] / (3600*1000);
+    int minutes = ([value intValue] - hours * 3600) / (60*1000);
+    int seconds = ([value intValue] - hours * 3600 * 1000 - minutes * 60 * 1000)/1000;
+
+    return [NSString stringWithFormat:@"%02d:%02d:%02d", hours, minutes, seconds];
+}
+@end

+ 272 - 0
Sources/VLCVideoView.m

@@ -0,0 +1,272 @@
+/*****************************************************************************
+ * VLCVideoView.h: VLC.framework VLCVideoView implementation
+ *****************************************************************************
+ * 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 <VLC/VLCVideoView.h>
+#import "VLCLibrary.h"
+#import "VLCEventManager.h"
+
+/* Libvlc */
+#include <vlc/vlc.h>
+#include <vlc/libvlc.h>
+
+/* Notification */
+NSString * VLCVideoDidChangeVolume                  = @"VLCVideoDidChangeVolume";
+NSString * VLCVideoDidChangeTime                    = @"VLCVideoDidChangeTime";
+NSString * VLCVideoDidChangeCurrentlyPlayingItem    = @"VLCVideoDidChangeCurrentlyPlayingItem";
+NSString * VLCVideoDidPause                         = @"VLCVideoDidPause";
+NSString * VLCVideoDidPlay                          = @"VLCVideoDidPlay";
+NSString * VLCVideoDidStop                          = @"VLCVideoDidStop";
+
+static void HandleMediaListPlayerCurrentPlayingItemChanged( const libvlc_event_t * event, void * self )
+{
+    [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject: self
+                                     withDelegateMethod: @selector(volumeDidChangeCurrentPlayingItem:)
+                                     withNotificationName: VLCVideoDidChangeCurrentlyPlayingItem];
+}
+
+static void HandleMediaListPlayerPaused( const libvlc_event_t * event, void * self )
+{
+    [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject: self
+                                     withDelegateMethod: @selector(videoDidPause:)
+                                     withNotificationName: VLCVideoDidPause];
+}
+
+static void HandleMediaListPlayerPlayed( const libvlc_event_t * event, void * self )
+{
+    [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject: self
+                                     withDelegateMethod: @selector(videoDidPlay:)
+                                     withNotificationName: VLCVideoDidPlay];
+}
+
+static void HandleMediaListPlayerStopped( const libvlc_event_t * event, void * self )
+{
+    [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject: self
+                                     withDelegateMethod: @selector(videoDidStop:)
+                                     withNotificationName: VLCVideoDidStop];
+}
+
+@implementation VLCVideoView
+- (id)initWithFrame:(NSRect)frameRect
+{
+    if (self = [super initWithFrame: frameRect])
+    {
+        libvlc_exception_t p_e;
+        libvlc_exception_init( &p_e );
+        p_mi = libvlc_media_instance_new( [VLCLibrary sharedInstance], &p_e );
+        quit_on_exception( &p_e );
+        p_mlp = libvlc_media_list_player_new( [VLCLibrary sharedInstance], &p_e );
+        quit_on_exception( &p_e );
+        libvlc_media_list_player_set_media_instance( p_mlp, p_mi, &p_e );
+        quit_on_exception( &p_e );
+        libvlc_media_instance_set_drawable( p_mi, (libvlc_drawable_t)self, &p_e );
+        quit_on_exception( &p_e );
+
+        libvlc_event_manager_t * p_em = libvlc_media_list_event_manager( p_mlp, &p_e );
+        //libvlc_event_attach( p_em, libvlc_MediaListPlayerCurrentPlayingItemChanged, HandleMediaListPlayerCurrentPlayingItemChanged, self, &p_e );
+        //libvlc_event_attach( p_em, libvlc_MediaListPlayerPaused,                    HandleMediaListPlayerPaused,  self, &p_e );
+        //libvlc_event_attach( p_em, libvlc_MediaListPlayerPlayed,                    HandleMediaListPlayerPlayed,  self, &p_e );
+        //libvlc_event_attach( p_em, libvlc_MediaListPlayerStopped,                   HandleMediaListPlayerStopped, self, &p_e );
+        quit_on_exception( &p_e );
+
+        delegate = nil;
+        playlist = nil;
+
+        [self setStretchesVideo: NO];
+        [self setAutoresizesSubviews: YES];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    libvlc_media_instance_release( p_mi );
+
+    if (delegate)
+    {
+        [delegate release];
+        delegate = nil;
+    }
+    [super dealloc];
+}
+
+- (void)setPlaylist: (VLCPlaylist *)newPlaylist
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+
+    if (playlist)
+        [playlist release];
+
+    playlist = [newPlaylist retain];
+
+    libvlc_media_list_player_set_media_list( p_mlp, [playlist libVLCMediaList], &p_e );
+    quit_on_exception( &p_e );
+}
+
+- (VLCPlaylist *)playlist
+{
+    return playlist;
+}
+
+/* Play */
+- (void)play
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_list_player_play( p_mlp, &p_e );
+    quit_on_exception( &p_e );
+}
+
+- (void)playItemAtIndex:(int) i
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_list_player_play_item_at_index( p_mlp, i, &p_e );
+    quit_on_exception( &p_e );
+}
+
+- (void)playMedia:(VLCMedia *) media
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    libvlc_media_list_player_play_item( p_mlp, [media libVLCMediaDescriptor], &p_e );
+    quit_on_exception( &p_e );
+}
+
+- (void)pause
+{
+    libvlc_exception_t p_e;
+    libvlc_exception_init( &p_e );
+    //libvlc_media_list_player_pause( p_mlp, &p_e );
+    quit_on_exception( &p_e );
+}
+
+- (void)setCurrentTime:(VLCTime *)timeObj
+{
+    
+}
+
+/* State */
+- (BOOL)isPlaying
+{
+    //libvlc_media_list_player_is_playing( p_mlp, &p_e );
+    //quit_on_exception( &p_e );
+    return FALSE;
+}
+
+- (BOOL)isPaused
+{
+    return FALSE;
+}
+
+- (VLCTime *)currentTime
+{
+    return NULL;
+}
+
+- (id)currentPlaylistItem
+{
+    return NULL;
+}
+
+/* Video output property */
+- (void)setStretchesVideo:(BOOL)flag
+{
+    stretchVideo = flag;
+}
+
+- (BOOL)stretchesVideo
+{
+    return stretchVideo;
+}
+
+/* Fullscreen */
+- (void)enterFullscreen
+{
+
+}
+
+- (void)leaveFullscreen
+{
+
+}
+
+/* Delegate */
+- (void)setDelegate: (id)newDelegate
+{
+    if (delegate)
+        [delegate release];
+    delegate = [newDelegate retain];
+}
+
+- (id)delegate
+{
+    return delegate;
+}
+@end
+
+@implementation VLCVideoView (NSViewSubclass)
+- (void)drawRect:(NSRect)aRect
+{
+    [self lockFocus];
+    [[NSColor blackColor] set];
+    NSRectFill(aRect);
+    [self unlockFocus];
+}
+- (BOOL)preservesContentDuringLiveResize
+{
+    return NO;//YES;
+}
+- (BOOL)isOpaque
+{
+    return YES;
+}
+@end
+
+@interface VLCOpenGLVoutView : NSView
+ /* This is part of the hack to avoid a warning in -[VLCVideoView addVoutSubview:] */
+- (void)detachFromVout;
+@end
+
+@implementation VLCVideoView (VLCOpenGLVoutEmbedding)
+/* This is called by the libvlc module 'macosx' as soon as there is one vout
+ * available */
+- (void)addVoutSubview:(id)aView
+{
+    if( [[self subviews] count] )
+    {
+        /* XXX: This is a hack until core gets fixed */
+        int i;
+        for( i = 0; i < [[self subviews] count]; i++ )
+        {
+            [[[self subviews] objectAtIndex: i] detachFromVout];
+            [[[self subviews] objectAtIndex: i] retain];
+            [[[self subviews] objectAtIndex: i] removeFromSuperview];
+        }
+    }
+    [self addSubview: aView];
+    [aView setFrame: [self bounds]];
+    [aView setAutoresizingMask:NSViewHeightSizable|NSViewWidthSizable];
+}
+@end

+ 13 - 0
Sources/test.m

@@ -0,0 +1,13 @@
+//
+//  test.m - Nothing useful yet
+//  VLC.framework
+//
+//  Created by Pierre d'Herbemont on 13/04/07.
+//  Copyright __MyCompanyName__ 2007. All rights reserved.
+//
+#include <VLC/VLC.h>
+
+int test_vlc_framework()
+{
+    return 0xbabe;
+}