diff options
author | AlTheKiller <AlTheKiller@svn> | 2009-09-23 01:49:50 +0000 |
---|---|---|
committer | AlTheKiller <AlTheKiller@svn> | 2009-09-23 01:49:50 +0000 |
commit | 45285e8a9300cd754a760560640b75b09f98035e (patch) | |
tree | ad9f093885ad5c98e9dd4156674e7691c22ed0a2 /tools |
step 3/4: Move linuxport to trunk. How'd I get roped into this?
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@23097 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
Diffstat (limited to 'tools')
485 files changed, 76464 insertions, 0 deletions
diff --git a/tools/Changelog/Changelog.cpp b/tools/Changelog/Changelog.cpp new file mode 100644 index 0000000000..e3a3a7cabd --- /dev/null +++ b/tools/Changelog/Changelog.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +// Changelog.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + +#include "tinyxml.h" +#include "../../xbmc/utils/RegExp.h" + +#ifdef _LINUX +#define _tmain main +#define _TCHAR char +#endif + +const char header[] = "*************************************************************************************************************\r\n" + "*************************************************************************************************************\r\n" + " XBMC CHANGELOG\r\n" + "*************************************************************************************************************\r\n" + "*************************************************************************************************************\r\n" + "\r\n" + "Date Rev Message\r\n" + "=============================================================================================================\r\n"; + +const char filter[][100] = {"[- ]*[0-9]+-[0-9]+-[0-9]+ *", + "\\*\\*\\* empty log message \\*\\*\\*", + "no message" }; + +std::string FilterMessage(std::string message) +{ + std::string filteredMessage = message; + CRegExp reg; + for (int i = 0; i < sizeof(filter) / 100; i++) + { + reg.RegComp(filter[i]); + int findStart = reg.RegFind(message.c_str()); + while (findStart >= 0) + { + filteredMessage = message.substr(0, findStart); + filteredMessage.append(message.substr(findStart + reg.GetFindLen(), message.length())); + message = filteredMessage; + findStart = reg.RegFind(message.c_str()); + } + } + return filteredMessage; +} + +int _tmain(int argc, _TCHAR* argv[]) +{ + std::string input = "svn_log.xml"; + std::string output = "Changelog.txt"; + int limit = 0; + + if (argc < 2) + { + // output help information + printf("usage:\n"); + printf("\n"); + printf(" Changelog input <output> <limit>\n"); + printf("\n"); + printf(" input : input .xml file generated from SVN (using svn log --xml)\n"); + printf(" DOWNLOAD to download direct from XBMC SVN\n"); + printf(" <output> : output .txt file for the changelog (defaults to Changelog.txt)\n"); + printf(" <limit> : the number of log entries for svn to fetch. (defaults to no limit)"); + printf("\n"); + return 0; + } + input = argv[1]; + if (argc > 2) + output = argv[2]; + FILE *file = fopen(output.c_str(), "wb"); + if (!file) + return 1; + fprintf(file, header); + if (input.compare("download") == 0) + { + if(argc > 3) + limit = atoi(argv[3]); + // download our input file + std::string command = "svn log -r 'HEAD':8638 "; + if (limit > 0) + { + command += "--limit "; + command += argv[3]; // the limit as a string + command += " "; + } +#ifndef _LINUX + command += "--xml https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk/XBMC > svn_log.xml"; +#else + command += "--xml https://xbmc.svn.sourceforge.net/svnroot/xbmc/branches/linuxport/XBMC > svn_log.xml"; +#endif + printf("Downloading changelog from SVN - this will take some time (around 1MB to download with no limit)\n"); + system(command.c_str()); + input = "svn_log.xml"; + printf("Downloading done - processing\n"); + } + TiXmlDocument doc; + if (!doc.LoadFile(input.c_str())) + { + return 1; + } + + TiXmlElement *root = doc.RootElement(); + if (!root) return 1; + + TiXmlElement *logitem = root->FirstChildElement("logentry"); + while (logitem) + { + int revision; + logitem->Attribute("revision", &revision); + TiXmlNode *date = logitem->FirstChild("date"); + std::string dateString; + if (date && date->FirstChild()) + dateString = date->FirstChild()->Value(); + TiXmlNode *msg = logitem->FirstChild("msg"); + if (msg && msg->FirstChild()) + { + // filter the message a bit + std::string message = FilterMessage(msg->FirstChild()->Value()); + if (message.size()) + fprintf(file, "%s %4i %s\r\n", dateString.substr(0,10).c_str(), revision, message.c_str()); + else + int breakhere = 1; + } + logitem = logitem->NextSiblingElement("logentry"); + } + fclose(file); + printf("Changelog saved as: %s\n", output.c_str()); + return 0; +} diff --git a/tools/Changelog/Changelog.exe b/tools/Changelog/Changelog.exe Binary files differnew file mode 100644 index 0000000000..5571d90375 --- /dev/null +++ b/tools/Changelog/Changelog.exe diff --git a/tools/Changelog/Changelog.py b/tools/Changelog/Changelog.py new file mode 100755 index 0000000000..74c35e9916 --- /dev/null +++ b/tools/Changelog/Changelog.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +import re, os, sys + +def usage (): + print " Changelog.py [option]" + print " -h : display this message" + print " -r <REV> : get log messages up until REV" + print " -d <DIR> : place Changelog.txt in DIR" + sys.exit() + + +header = "*************************************************************************************************************\n" \ + "*************************************************************************************************************\n" \ + " XBMC CHANGELOG\n" \ + "*************************************************************************************************************\n" \ + "*************************************************************************************************************" \ + "\nDate Rev Message\n" \ + "=============================================================================================================\n" + +xmlre = re.compile("^<logentry.*?revision=\"([0-9]{4,})\".*?<date>([0-9]{4}-[0-9]{2}-[0-9]{2})T.*?<msg>(.*?)</msg>.*?</logentry>$", re.MULTILINE | re.DOTALL) +txtre = re.compile("([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{4,5}) {1,2}(.*)") + +old = None +lastrev = 8638 +rev = 1000000 +dir = "." + +nargs = len(sys.argv) +args = sys.argv + +i = 1 +while i < nargs: + if args[i] == "-r": + i += 1 + try: + rev = int(sys.argv[i]) + except: + rev=1000000 + elif args[i] == "-d": + i+=1 + dir = args[i].replace(' ', '\ ') + elif args[i] == "-h" or args[i] == "--help": + usage() + i+=1 + +# print dir +# print rev + +try: + old = open("%s/Changelog.txt" % (dir)) +except: + old = None + +if old != None: + olddoc = old.read() + old.close() + oldmsgs = txtre.findall(olddoc) + del olddoc + if len(oldmsgs) > 0: + lastrev = int(oldmsgs[0][1]) +try: + output = open("%s/Changelog.txt" % (dir),"w") +except: + print "Can't open %s/Changelog.txt for writing." % (dir) + sys.exit() + +output.write(header) + +if rev <= lastrev: + for msg in oldmsgs: + if int(msg[1]) <= rev: + s = "%-11.11s %-5.5s %s\n" % (msg[0], msg[1], msg[2]) + output.write(s) + sys.exit() + +svncmd = "svn log --xml -r %s:HEAD" % (lastrev) +newlog = os.popen(svncmd) + +newlogdoc = newlog.read() +newlog.close() + +newmsgs = xmlre.findall(newlogdoc) + +newmsgs.reverse() + +for msg in newmsgs: + s = "%-11.11s %-5.5s %s\n" % (msg[1], msg[0], msg[2].replace('\n','')) + output.write(s) + +skip = 0 +if old != None: + for msg in oldmsgs: + if skip == 1: + s = "%-11.11s %-5.5s %s\n" % (msg[0], msg[1], msg[2]) + output.write(s) + else: + skip = 1 + +output.close() + diff --git a/tools/Changelog/Changelog.sln b/tools/Changelog/Changelog.sln new file mode 100644 index 0000000000..d322696c4f --- /dev/null +++ b/tools/Changelog/Changelog.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Changelog", "Changelog.vcproj", "{05525588-A93C-4220-8C26-A93FBCE525BD}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {05525588-A93C-4220-8C26-A93FBCE525BD}.Debug.ActiveCfg = Debug|Win32
+ {05525588-A93C-4220-8C26-A93FBCE525BD}.Debug.Build.0 = Debug|Win32
+ {05525588-A93C-4220-8C26-A93FBCE525BD}.Release.ActiveCfg = Release|Win32
+ {05525588-A93C-4220-8C26-A93FBCE525BD}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/tools/Changelog/Changelog.vcproj b/tools/Changelog/Changelog.vcproj new file mode 100644 index 0000000000..5e205f56dd --- /dev/null +++ b/tools/Changelog/Changelog.vcproj @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="Changelog"
+ ProjectGUID="{05525588-A93C-4220-8C26-A93FBCE525BD}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../guilib/tinyxml"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/Changelog.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/Changelog.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../guilib/tinyxml"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/Changelog.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath=".\Changelog.cpp">
+ </File>
+ <File
+ RelativePath="..\..\xbmc\utils\RegExp.cpp">
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\guilib\tinyXML\tinystr.cpp">
+ </File>
+ <File
+ RelativePath="..\..\guilib\tinyXML\tinyxml.cpp">
+ </File>
+ <File
+ RelativePath="..\..\guilib\tinyXML\tinyxmlerror.cpp">
+ </File>
+ <File
+ RelativePath="..\..\guilib\tinyXML\tinyxmlparser.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\xbmc\utils\RegExp.h">
+ </File>
+ <File
+ RelativePath=".\stdafx.h">
+ </File>
+ <File
+ RelativePath="..\..\guilib\tinyXML\tinystr.h">
+ </File>
+ <File
+ RelativePath="..\..\guilib\tinyXML\tinyxml.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/Changelog/Makefile b/tools/Changelog/Makefile new file mode 100644 index 0000000000..c2b5c94171 --- /dev/null +++ b/tools/Changelog/Makefile @@ -0,0 +1,2 @@ +Changelog: Changelog.cpp + g++ -D_LINUX -I../../guilib/tinyXML -o Changelog Changelog.cpp ../../guilib/tinyXML/*.o ../../xbmc/utils/RegExp.o diff --git a/tools/Changelog/stdafx.cpp b/tools/Changelog/stdafx.cpp new file mode 100644 index 0000000000..5cd322741d --- /dev/null +++ b/tools/Changelog/stdafx.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +// stdafx.cpp : source file that includes just the standard includes +// Changelog.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/tools/Changelog/stdafx.h b/tools/Changelog/stdafx.h new file mode 100644 index 0000000000..12f4e100cc --- /dev/null +++ b/tools/Changelog/stdafx.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + + +#include <iostream> +#ifndef _LINUX +#include <tchar.h> + +// TODO: reference additional headers your program requires here +#include <windows.h> +#endif diff --git a/tools/EventClients/Clients/AppleRemote/AppleRemote.cpp b/tools/EventClients/Clients/AppleRemote/AppleRemote.cpp new file mode 100644 index 0000000000..1cd8baa730 --- /dev/null +++ b/tools/EventClients/Clients/AppleRemote/AppleRemote.cpp @@ -0,0 +1,645 @@ +/* + * AppleRemote.cpp + * AppleRemote + * + * + */ + +#include <stdio.h> +#include <getopt.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <sys/errno.h> +#include <sysexits.h> +#include <mach/mach.h> +#include <mach/mach_error.h> +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/sysctl.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include "AppleRemote.h" +#include "../../lib/c++/xbmcclient.h" + +#define DEFAULT_MAX_CLICK_DURATION 0.5 + +#define LOG if (m_bVerbose) printf + +#define APPLICATION_NAME "XBMC" + +enum { + IR_Select, + IR_SelectHold, + IR_Right, + IR_Left, + IR_Up, + IR_Down, + IR_RightHold, + IR_LeftHold, + IR_Menu, + IR_MenuHold +}; +enum { + IR_Event_Term_ATV1X = 5, + IR_Event_Term_ATV20X = 5, + IR_Event_Term_ATV21 = 8, + IR_Event_Term_10_4 = 5, + IR_Event_Term_10_5 = 18 +}; +// magic HID key cookies AppleTV running r1.x (same as 10.4) +static std::string key_cookiesATV1X[] = +{ + "8_", //SelectHold = "18_" + "18_", + "9_", + "10_", + "12_", + "13_", + "4_", + "3_", + "7_", + "5_" +}; +// magic HID key cookies AppleTV running r2.0x +static std::string key_cookiesATV20X[] = +{ + "8_", //SelectHold = "18_" + "18_", + "9_", + "10_", + "12_", + "13_", + "4_", + "3_", + "5_", + "7_" +}; +// magic HID key cookies for AppleTV running r2.1 +static std::string key_cookiesATV21[] = +{ + "9_", //SelectHold = "19_" + "19_", + "10_", + "11_", + "13_", + "14_", + "5_", + "4_", + "6_", + "8_" +}; +// magic HID key cookies for 10.4 +static std::string key_cookies10_4[] = +{ + "8_", //SelectHold = "18_" + "18_", + "9_", + "10_", + "12_", + "13_", + "4_", + "3_", + "7_", + "5_" +}; + +// magic HID key cookies for 10.5 +static std::string key_cookies10_5[] = +{ + "21_", //SelectHold = "35_" + "35_", + "22_", + "23_", + "29_", + "30_", + "4_", + "3_", + "20_", + "18_" +}; + +AppleRemote::AppleRemote() :m_bVerbose(false), + m_remoteMode(REMOTE_NORMAL), + m_dMaxClickDuration(DEFAULT_MAX_CLICK_DURATION), + m_socket(-1), + m_timer(NULL) +{ + m_serverAddress = "localhost"; + m_appPath = ""; + m_appHome = ""; +} + +AppleRemote::~AppleRemote() +{ + DeInitialize(); +} + +void AppleRemote::RegisterCommand(const std::string &strSequence, CPacketBUTTON *pPacket) +{ + LOG("Registering command %s\n", strSequence.c_str()); + m_mapCommands[strSequence] = pPacket; +} + +void AppleRemote::Initialize() +{ + std::string *key; + std::string prefix; + + LOG("initializing apple remote\n"); + + DeInitialize(); + + m_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (m_socket < 0) + { + fprintf(stderr, "Error opening UDP socket! error: %d\n", errno); + exit(1); + } + + LOG("udp socket (%d) opened\n", m_socket); + + // Runtime Version Check + SInt32 MacVersion; + + Gestalt(gestaltSystemVersion, &MacVersion); + + if (MacVersion < 0x1050) + { + // OSX 10.4/AppleTV + size_t len = 512; + char buffer[512]; + std::string hw_model = "unknown"; + + if (sysctlbyname("hw.model", &buffer, &len, NULL, 0) == 0) + hw_model = buffer; + + if (hw_model == "AppleTV1,1") + { + FILE *inpipe; + bool atv_version_found = false; + char linebuf[1000]; + + //Find the build version of the AppleTV OS + inpipe = popen("sw_vers -buildVersion", "r"); + if (inpipe) + { + //get output + if(fgets(linebuf, sizeof(linebuf) - 1, inpipe)) + { + if( strstr(linebuf,"8N5107") || strstr(linebuf,"8N5239")) + { + // r1.0 or r1.1 + atv_version_found = true; + fprintf(stderr, "Using key code for AppleTV r1.x\n"); + key = key_cookiesATV1X; + m_button_event_terminator = IR_Event_Term_ATV1X; + } + else if (strstr(linebuf,"8N5400") || strstr(linebuf,"8N5455") || strstr(linebuf,"8N5461")) + { + // r2.0, r2.01 or r2.02 + atv_version_found = true; + fprintf(stderr, "Using key code for AppleTV r2.0x\n"); + key = key_cookiesATV20X; + m_button_event_terminator = IR_Event_Term_ATV20X; + } + else if( strstr(linebuf,"8N5519")) + { + // r2.10 + atv_version_found = true; + fprintf(stderr, "Using key code for AppleTV r2.1\n"); + key = key_cookiesATV21; + m_button_event_terminator = IR_Event_Term_ATV21; + + } + else if( strstr(linebuf,"8N5622")) + { + // r2.10 + atv_version_found = true; + fprintf(stderr, "Using key code for AppleTV r2.2\n"); + key = key_cookiesATV21; + m_button_event_terminator = IR_Event_Term_ATV21; + } + } + pclose(inpipe); + } + + if(!atv_version_found){ + //handle fallback or just exit + fprintf(stderr, "AppletTV software version could not be determined.\n"); + fprintf(stderr, "Defaulting to using key code for AppleTV r2.1\n"); + key = key_cookiesATV21; + m_button_event_terminator = IR_Event_Term_ATV21; + } + } + else + { + fprintf(stderr, "Using key code for OSX 10.4\n"); + key = key_cookies10_4; + m_button_event_terminator = IR_Event_Term_10_4; + } + } + else + { + // OSX 10.5 + fprintf(stderr, "Using key code for OSX 10.5\n"); + key = key_cookies10_5; + m_button_event_terminator = IR_Event_Term_10_5; + } + m_launch_xbmc_button = key[IR_MenuHold]; + + RegisterCommand(key[IR_Select], new CPacketBUTTON(5, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(key[IR_SelectHold],new CPacketBUTTON(7, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(key[IR_Right], new CPacketBUTTON(4, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(key[IR_Left], new CPacketBUTTON(3, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(key[IR_Up], new CPacketBUTTON(1, "JS0:AppleRemote", BTN_DOWN)); + RegisterCommand(key[IR_Down], new CPacketBUTTON(2, "JS0:AppleRemote", BTN_DOWN)); + RegisterCommand(key[IR_RightHold], new CPacketBUTTON(4, "JS0:AppleRemote", BTN_DOWN)); + RegisterCommand(key[IR_LeftHold], new CPacketBUTTON(3, "JS0:AppleRemote", BTN_DOWN)); + + RegisterCommand(key[IR_Menu], new CPacketBUTTON(6, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + + // Menu Hold will be used both for sending "Back" and for starting universal remote combinations (if universal mode is on) + RegisterCommand(key[IR_MenuHold], new CPacketBUTTON(8, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + + // Universal commmands: + RegisterCommand(key[IR_MenuHold] + key[IR_Down], new CPacketBUTTON("Back", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + + prefix = key[IR_MenuHold] + key[IR_Select]; + RegisterCommand(prefix + key[IR_Right], new CPacketBUTTON("Info", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(prefix + key[IR_Left], new CPacketBUTTON("Title", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(prefix + key[IR_Up], new CPacketBUTTON("PagePlus", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(prefix + key[IR_Down], new CPacketBUTTON("PageMinus", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(prefix + key[IR_Select],new CPacketBUTTON("Display", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + + prefix = key[IR_MenuHold] + key[IR_Up]; + + RegisterCommand(prefix + key[IR_Select],new CPacketBUTTON("Stop", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(prefix + key[IR_Left], new CPacketBUTTON("Power", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(prefix + key[IR_Right], new CPacketBUTTON("Zero", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(prefix + key[IR_Up], new CPacketBUTTON("Play", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + RegisterCommand(prefix + key[IR_Down], new CPacketBUTTON("Pause", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); + + // for universal mode - some keys are part of a key combination. + // when those keys are pressed, we'll wait for more to come - until a valid combination was entered or a timeout expired. + // the keys "leading" a combination are added to the prefix vector. + // all we need to do to turn universal mode off is clear the prefix vector and then every command will be sent immidiately. + if (m_remoteMode == REMOTE_UNIVERSAL) + { + LOG("universal mode on. registering prefixes: %s\n", key[IR_MenuHold].c_str()); + m_universalPrefixes.push_back( key[IR_MenuHold] ); + } + else + { + LOG("universal mode off.\n"); + m_universalPrefixes.clear(); + } + + m_strCombination.clear(); + m_bSendUpRequired = false; +} + +void AppleRemote::DeInitialize() +{ + LOG("uninitializing apple remote\n"); + + ResetTimer(); + + if (m_socket > 0) + close(m_socket); + + m_socket = -1; + + LOG("deleting commands map\n"); + std::map<std::string, CPacketBUTTON *>::iterator iter = m_mapCommands.begin(); + while (iter != m_mapCommands.end()) + { + delete iter->second; + iter++; + } + m_mapCommands.clear(); + m_strCombination.clear(); +} + +void AppleRemote::SetTimer() +{ + if (m_timer) + ResetTimer(); + + LOG("setting timer to expire in %.2f secs. \n", m_dMaxClickDuration); + CFRunLoopTimerContext context = { 0, this, 0, 0, 0 }; + m_timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + m_dMaxClickDuration, 0, 0, 0, TimerCallBack, &context); + CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_timer, kCFRunLoopCommonModes); +} + +void AppleRemote::ResetTimer() +{ + if (m_timer) + { + LOG("removing timer\n"); + + CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), m_timer, kCFRunLoopCommonModes); + CFRunLoopTimerInvalidate(m_timer); + CFRelease(m_timer); + } + + m_timer = NULL; +} + +void AppleRemote::SetMaxClickDuration(double dDuration) +{ + m_dMaxClickDuration = dDuration; + LOG("setting click max duration to %.2f seconds\n", dDuration); +} + +void AppleRemote::TimerCallBack (CFRunLoopTimerRef timer, void *info) +{ + if (!info) + { + fprintf(stderr, "Error. invalid argument to timer callback\n"); + return; + } + + AppleRemote *pRemote = (AppleRemote *)info; + pRemote->SendCommand(pRemote->m_strCombination); + pRemote->m_strCombination.clear(); + pRemote->ResetTimer(); +} + +bool AppleRemote::SendCommand(const std::string &key) +{ + CPacketBUTTON *pPacket = m_mapCommands[key]; + if (pPacket) + { + LOG("Sending command for Key (%s)\n", key.c_str()); + CAddress addr(m_serverAddress.c_str()); + pPacket->Send(m_socket, addr); + + if ( 0 == (pPacket->GetFlags() & BTN_NO_REPEAT) ) + m_bSendUpRequired = true; + else + m_bSendUpRequired = false; + } + + return pPacket != NULL; +} + +void AppleRemote::LaunchApp() +{ + // the path to xbmc.app is passed as an arg, + // use this to launch from a menu press + LOG("Trying to start XBMC: [%s]\n", m_appPath.c_str()); + if (!m_appPath.empty()) + { + std::string strCmd; + + // build a finder open command + strCmd = "XBMC_HOME="; + strCmd += m_appHome; + strCmd += " "; + strCmd += m_appPath; + strCmd += " &"; + LOG("xbmc open command: [%s]\n", strCmd.c_str()); + system(strCmd.c_str()); + } +} + +void AppleRemote::SendPacket(CPacketBUTTON &packet) +{ + CAddress addr(m_serverAddress.c_str()); + packet.Send(m_socket, addr); +} + +void AppleRemote::OnKeyDown(const std::string &key) +{ + if (!IsProgramRunning(APPLICATION_NAME) && (m_serverAddress == "localhost" || m_serverAddress == "127.0.0.1")) + { + if (key == m_launch_xbmc_button) + LaunchApp(); + + return; + } + + LOG("key down: %s\n", key.c_str()); + if (m_remoteMode == REMOTE_NORMAL) { + SendCommand(key); + } + else if (m_remoteMode == REMOTE_UNIVERSAL) + { + bool bCombinationStart = false; + bool bNeedTimer = false; + if (m_strCombination.empty()) + { + bNeedTimer = true; + for (size_t i=0; i<m_universalPrefixes.size(); i++) + { + if (m_universalPrefixes[i] == key) + { + LOG("start of combination (key=%s)\n", key.c_str()); + bCombinationStart = true; + break; + } + } + } + + m_strCombination += key; + + if (bCombinationStart) + SetTimer(); + else + { + if (SendCommand(m_strCombination)) + { + m_strCombination.clear(); + ResetTimer(); + } + else if (bNeedTimer) + SetTimer(); + } + } +} + +void AppleRemote::OnKeyUp(const std::string &key) +{ + LOG("key up: %s\n", key.c_str()); + if (m_bSendUpRequired) + { + LOG("sending key-up event\n"); + CPacketBUTTON btn; + CAddress addr(m_serverAddress.c_str()); + btn.Send(m_socket, addr); + } + else + { + LOG("no need to send UP event\n"); + } +} + +void AppleRemote::SetVerbose(bool bVerbose) +{ + m_bVerbose = bVerbose; +} + +bool AppleRemote::IsVerbose() +{ + return m_bVerbose; +} + +void AppleRemote::SetMaxClickTimeout(double dTimeout) +{ + m_dMaxClickDuration = dTimeout; +} + +void AppleRemote::SetServerAddress(const std::string &strAddress) +{ + m_serverAddress = strAddress; +} + +void AppleRemote::SetAppPath(const std::string &strAddress) +{ + m_appPath = strAddress; +} + +void AppleRemote::SetAppHome(const std::string &strAddress) +{ + m_appHome = strAddress; +} + +const std::string &AppleRemote::GetServerAddress() +{ + return m_serverAddress; +} + +void AppleRemote::SetRemoteMode(RemoteModes mode) +{ + m_remoteMode = mode; +} + +bool AppleRemote::IsProgramRunning(const char* strProgram, int ignorePid) +{ + kinfo_proc* mylist = (kinfo_proc *)malloc(sizeof(kinfo_proc)); + size_t mycount = 0; + bool ret = false; + + GetBSDProcessList(&mylist, &mycount); + for(size_t k = 0; k < mycount && ret == false; k++) + { + kinfo_proc *proc = NULL; + proc = &mylist[k]; + + //LOG("proc->kp_proc.p_comm: %s\n", proc->kp_proc.p_comm); + // Process names are at most sixteen characters long. + if (strncmp(proc->kp_proc.p_comm, strProgram, 16) == 0) + { + if (ignorePid == 0 || ignorePid != proc->kp_proc.p_pid) + { + //LOG("found: %s\n", proc->kp_proc.p_comm); + ret = true; + } + } + } + free(mylist); + return ret; +} + +int AppleRemote::GetBSDProcessList(kinfo_proc **procList, size_t *procCount) + // Returns a list of all BSD processes on the system. This routine + // allocates the list and puts it in *procList and a count of the + // number of entries in *procCount. You are responsible for freeing + // this list (use "free" from System framework). + // On success, the function returns 0. + // On error, the function returns a BSD errno value. +{ + int err; + kinfo_proc * result; + bool done; + static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; + // Declaring name as const requires us to cast it when passing it to + // sysctl because the prototype doesn't include the const modifier. + size_t length; + + assert( procList != NULL); + assert(procCount != NULL); + + *procCount = 0; + + // We start by calling sysctl with result == NULL and length == 0. + // That will succeed, and set length to the appropriate length. + // We then allocate a buffer of that size and call sysctl again + // with that buffer. If that succeeds, we're done. If that fails + // with ENOMEM, we have to throw away our buffer and loop. Note + // that the loop causes use to call sysctl with NULL again; this + // is necessary because the ENOMEM failure case sets length to + // the amount of data returned, not the amount of data that + // could have been returned. + + result = NULL; + done = false; + do { + assert(result == NULL); + + // Call sysctl with a NULL buffer. + + length = 0; + err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, + NULL, &length, + NULL, 0); + if (err == -1) { + err = errno; + } + + // Allocate an appropriately sized buffer based on the results + // from the previous call. + + if (err == 0) { + result = (kinfo_proc* )malloc(length); + if (result == NULL) { + err = ENOMEM; + } + } + + // Call sysctl again with the new buffer. If we get an ENOMEM + // error, toss away our buffer and start again. + + if (err == 0) { + err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, + result, &length, + NULL, 0); + if (err == -1) { + err = errno; + } + if (err == 0) { + done = true; + } else if (err == ENOMEM) { + assert(result != NULL); + free(result); + result = NULL; + err = 0; + } + } + } while (err == 0 && ! done); + + // Clean up and establish post conditions. + + if (err != 0 && result != NULL) { + free(result); + result = NULL; + } + *procList = result; + if (err == 0) { + *procCount = length / sizeof(kinfo_proc); + } + + assert( (err == 0) == (*procList != NULL) ); + + return err; +} + +int AppleRemote::GetButtonEventTerminator(void) +{ + return(m_button_event_terminator); +} diff --git a/tools/EventClients/Clients/AppleRemote/AppleRemote.h b/tools/EventClients/Clients/AppleRemote/AppleRemote.h new file mode 100644 index 0000000000..45e3a427bc --- /dev/null +++ b/tools/EventClients/Clients/AppleRemote/AppleRemote.h @@ -0,0 +1,80 @@ +/* + * AppleRemote.h + * AppleRemote + * + * + */ +#ifndef __APPLE__REMOTE__H__ +#define __APPLE__REMOTE__H__ + +#include <ctype.h> +#include <Carbon/Carbon.h> + +#include <vector> +#include <map> +#include <string> + +typedef enum { REMOTE_NONE, REMOTE_NORMAL, REMOTE_UNIVERSAL } RemoteModes; +typedef struct kinfo_proc kinfo_proc; + +class CPacketBUTTON; +class AppleRemote +{ +public: + AppleRemote(); + virtual ~AppleRemote(); + + void Initialize(); + void DeInitialize(); + + void ResetTimer(); + void SetTimer(); + + void OnKeyDown(const std::string &key); + void OnKeyUp(const std::string &key); + + int GetButtonEventTerminator(void); + + void SetMaxClickDuration(double dDuration); + + void SetVerbose(bool bVerbose); + bool IsVerbose(); + + void SetMaxClickTimeout(double dTimeout); + void SetServerAddress(const std::string &strAddress); + void SetAppPath(const std::string &strAddress); + void SetAppHome(const std::string &strAddress); + void SetRemoteMode(RemoteModes mode); + + const std::string &GetServerAddress(); + + static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount); + bool IsProgramRunning(const char* strProgram, int ignorePid=0); + void LaunchApp(); + + void SendPacket(CPacketBUTTON &packet); + +protected: + static void TimerCallBack (CFRunLoopTimerRef timer, void *info); + void RegisterCommand(const std::string &strSequence, CPacketBUTTON *pPacket); + bool SendCommand(const std::string &key); + void ParseConfig(); + + bool m_bVerbose; + bool m_bSendUpRequired; + RemoteModes m_remoteMode; + double m_dMaxClickDuration; + int m_socket; + std::string m_strCombination; + std::string m_serverAddress; + std::string m_appPath; + std::string m_appHome; + + std::map<std::string, CPacketBUTTON *> m_mapCommands; + std::vector<std::string> m_universalPrefixes; + std::string m_launch_xbmc_button; + int m_button_event_terminator; + CFRunLoopTimerRef m_timer; +}; + +#endif diff --git a/tools/EventClients/Clients/AppleRemote/Makefile b/tools/EventClients/Clients/AppleRemote/Makefile new file mode 100644 index 0000000000..63518afe16 --- /dev/null +++ b/tools/EventClients/Clients/AppleRemote/Makefile @@ -0,0 +1,25 @@ +CXX=g++ +CC=g++ + +CFLAGS+=-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 +CFLAGS+=-Wall +LDFLAGS+=-framework IOKit -framework Carbon -framework ForceFeedback + +OBJS = iremoted.o AppleRemote.o + +TARGET = ../../../osx/XBMCHelper +CLEAN_FILES=$(TARGET) + +all: $(TARGET) + +$(TARGET): $(OBJS) + g++ $(LDFLAGS) $(OBJS) -o $(TARGET) + +.cpp.o: + $(CXX) -c $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o ${<:.cpp=.o} + +.c.o: + $(CC) -c $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o ${<:.c=.o} + +clean: + $(RM) -rf *.o ../../../osx/XBMCHelper diff --git a/tools/EventClients/Clients/AppleRemote/XBox360.h b/tools/EventClients/Clients/AppleRemote/XBox360.h new file mode 100644 index 0000000000..88d6a0cb94 --- /dev/null +++ b/tools/EventClients/Clients/AppleRemote/XBox360.h @@ -0,0 +1,576 @@ +#ifndef __XBOX360_H__ +#define __XBOX360_H__ + +#include <IOKit/usb/IOUSBLib.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/IOCFPlugIn.h> +#include <IOKit/hid/IOHIDLib.h> +#include <IOKit/hid/IOHIDKeys.h> +#include <IOKit/hid/IOHIDUsageTables.h> + +#include <ForceFeedback/ForceFeedback.h> + +#include <pthread.h> +#include <string> +#include <list> + +#include "AppleRemote.h" +#include "../../lib/c++/xbmcclient.h" + +#define SAFELY(expr) if ((expr) != kIOReturnSuccess) { printf("ERROR: \"%s\".\n", #expr); return; } + +extern AppleRemote g_appleRemote; + +class XBox360Controller +{ + public: + + static XBox360Controller* XBox360Controller::Create(io_service_t device, int deviceNum, bool deviceWireless) + { + XBox360Controller* controller = new XBox360Controller(); + IOReturn ret; + IOCFPlugInInterface **plugInInterface; + SInt32 score=0; + + ret = IOCreatePlugInInterfaceForService(device, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); + if (ret == kIOReturnSuccess) + { + ret = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID122), (LPVOID*)&controller->hidDevice); + (*plugInInterface)->Release(plugInInterface); + if (ret == kIOReturnSuccess) + { + controller->forceFeedback=0; + FFCreateDevice(device, &controller->forceFeedback); + controller->index = deviceNum; + controller->deviceHandle = device; + controller->wireless = deviceWireless; + + char str[128]; + sprintf(str, "%s Controller %d", deviceWireless ? "Wireless" : "Wired", deviceNum); + controller->name = str; + + return controller; + } + } + + return 0; + } + + ~XBox360Controller() + { + if (deviceHandle != 0) IOObjectRelease(deviceHandle); + if (hidDevice != 0) (*hidDevice)->Release(hidDevice); + if (forceFeedback != 0) FFReleaseDevice(forceFeedback); + } + + void start() + { + int i,j; + CFRunLoopSourceRef eventSource; + + // Get serial. + FFEFFESCAPE escape; + unsigned char c; + std::string serial; + + serial = getSerialNumber(); + //printf("SERIAL: %s, forceFeedback: 0x%08lx\n", serial.c_str(), forceFeedback); + + CFArrayRef elements; + SAFELY((*hidDevice)->copyMatchingElements(hidDevice, NULL, &elements)); + + for(i=0; i<CFArrayGetCount(elements); i++) + { + CFDictionaryRef element = (CFDictionaryRef)CFArrayGetValueAtIndex(elements, i); + long usage, usagePage, longCookie; + + // Get cookie. + if (getVal(element, CFSTR(kIOHIDElementCookieKey), longCookie) && + getVal(element, CFSTR(kIOHIDElementUsageKey), usage) && + getVal(element, CFSTR(kIOHIDElementUsagePageKey), usagePage)) + { + IOHIDElementCookie cookie = (IOHIDElementCookie)longCookie; + + // Match up items + switch (usagePage) + { + case 0x01: // Generic Desktop + j=0; + switch (usage) + { + case 0x35: j++; // Right trigger + case 0x32: j++; // Left trigger + case 0x34: j++; // Right stick Y + case 0x33: j++; // Right stick X + case 0x31: j++; // Left stick Y + case 0x30: // Left stick X + axis[j] = cookie; + break; + default: + break; + } + break; + + case 0x09: // Button + if (usage >= 1 && usage <= 15) + { + // Button 1-11 + buttons[usage-1] = cookie; + } + break; + + default: + break; + } + } + } + + // Start queue. + SAFELY((*hidDevice)->open(hidDevice, 0)); + + hidQueue = (*hidDevice)->allocQueue(hidDevice); + if (hidQueue == NULL) + { + printf("Unable to allocate queue\n"); + return; + } + + // Create queue, set callback. + SAFELY((*hidQueue)->create(hidQueue, 0, 32)); + SAFELY((*hidQueue)->createAsyncEventSource(hidQueue, &eventSource)); + SAFELY((*hidQueue)->setEventCallout(hidQueue, CallbackFunction, this, NULL)); + + // Add to runloop. + CFRunLoopAddSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopCommonModes); + + // Add the elements. + for(i=0; i<6; i++) + (*hidQueue)->addElement(hidQueue, axis[i], 0); + for(i=0; i<15; i++) + (*hidQueue)->addElement(hidQueue, buttons[i], 0); + + // Start. + SAFELY((*hidQueue)->start(hidQueue)); + +#if 0 + // Read existing properties + { +// CFDictionaryRef dict=(CFDictionaryRef)IORegistryEntryCreateCFProperty(registryEntry,CFSTR("DeviceData"),NULL,0); + CFDictionaryRef dict = (CFDictionaryRef)[GetController(GetSerialNumber(registryEntry)) retain]; + if(dict!=0) { + CFBooleanRef boolValue; + CFNumberRef intValue; + + if(CFDictionaryGetValueIfPresent(dict,CFSTR("InvertLeftX"),(void*)&boolValue)) { + [leftStickInvertX setState:CFBooleanGetValue(boolValue)?NSOnState:NSOffState]; + } else NSLog(@"No value for InvertLeftX"); + if(CFDictionaryGetValueIfPresent(dict,CFSTR("InvertLeftY"),(void*)&boolValue)) { + [leftStickInvertY setState:CFBooleanGetValue(boolValue)?NSOnState:NSOffState]; + } else NSLog(@"No value for InvertLeftY"); + if(CFDictionaryGetValueIfPresent(dict,CFSTR("RelativeLeft"),(void*)&boolValue)) { + BOOL enable=CFBooleanGetValue(boolValue); + [leftLinked setState:enable?NSOnState:NSOffState]; + [leftStick setLinked:enable]; + } else NSLog(@"No value for RelativeLeft"); + if(CFDictionaryGetValueIfPresent(dict,CFSTR("DeadzoneLeft"),(void*)&intValue)) { + UInt16 i; + + CFNumberGetValue(intValue,kCFNumberShortType,&i); + [leftStickDeadzone setIntValue:i]; + [leftStick setDeadzone:i]; + } else NSLog(@"No value for DeadzoneLeft"); + if(CFDictionaryGetValueIfPresent(dict,CFSTR("InvertRightX"),(void*)&boolValue)) { + [rightStickInvertX setState:CFBooleanGetValue(boolValue)?NSOnState:NSOffState]; + } else NSLog(@"No value for InvertRightX"); + if(CFDictionaryGetValueIfPresent(dict,CFSTR("InvertRightY"),(void*)&boolValue)) { + [rightStickInvertY setState:CFBooleanGetValue(boolValue)?NSOnState:NSOffState]; + } else NSLog(@"No value for InvertRightY"); + if(CFDictionaryGetValueIfPresent(dict,CFSTR("RelativeRight"),(void*)&boolValue)) { + BOOL enable=CFBooleanGetValue(boolValue); + [rightLinked setState:enable?NSOnState:NSOffState]; + [rightStick setLinked:enable]; + } else NSLog(@"No value for RelativeRight"); + if(CFDictionaryGetValueIfPresent(dict,CFSTR("DeadzoneRight"),(void*)&intValue)) { + UInt16 i; + + CFNumberGetValue(intValue,kCFNumberShortType,&i); + [rightStickDeadzone setIntValue:i]; + [rightStick setDeadzone:i]; + } else NSLog(@"No value for DeadzoneRight"); + CFRelease(dict); + } else NSLog(@"No settings found"); + } + + // Set LED and manual motor control + // [self updateLED:0x0a]; + [self setMotorOverride:TRUE]; + [self testMotorsLarge:0 small:0]; + largeMotor=0; + smallMotor=0; + + // Battery level? + { + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + NSString *path; + CFTypeRef prop; + + path = nil; + if (IOObjectConformsTo(registryEntry, "WirelessHIDDevice")) + { + prop = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("BatteryLevel"), NULL, 0); + if (prop != nil) + { + unsigned char level; + + if (CFNumberGetValue(prop, kCFNumberCharType, &level)) + path = [bundle pathForResource:[NSString stringWithFormat:@"batt%i", level / 64] ofType:@"tif"]; + CFRelease(prop); + } + } + if (path == nil) + path = [bundle pathForResource:@"battNone" ofType:@"tif"]; + [batteryLevel setImage:[[[NSImage alloc] initByReferencingFile:path] autorelease]]; + } + } + #endif + + c = 0x0a; + if (serial.length() > 0) + { + #if 0 + for (int i = 0; i < 4; i++) + { + if ((leds[i] == nil) || ([leds[i] caseInsensitiveCompare:serial] == NSOrderedSame)) + { + c = 0x06 + i; + if (leds[i] == nil) + { + //leds[i] = [serial retain]; + printf("Added controller with LED %i\n", i); + } + break; + } + } + #endif + } + c = 0x06; + escape.dwSize = sizeof(escape); + escape.dwCommand = 0x02; + escape.cbInBuffer = sizeof(c); + escape.lpvInBuffer = &c; + escape.cbOutBuffer = 0; + escape.lpvOutBuffer = NULL; + if (FFDeviceEscape(forceFeedback, &escape) != FF_OK) + printf("Error: FF\n"); + } + + void stop() + { + if (hidQueue != 0) + { + // Stop the queue. + (*hidQueue)->stop(hidQueue); + + // Remove from the run loop. + CFRunLoopSourceRef eventSource = (*hidQueue)->getAsyncEventSource(hidQueue); + if ((eventSource != 0) && CFRunLoopContainsSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopCommonModes)) + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopCommonModes); + + // Whack. + (*hidQueue)->Release(hidQueue); + hidQueue = 0; + } + + if (hidDevice != 0) + (*hidDevice)->close(hidDevice); + } + + std::string getName() { return name; } + + private: + + XBox360Controller() + { + for (int i=0; i<15; i++) + buttons[i] = 0; + + for (int i=0; i<6; i++) + axis[i] = 0; + } + + std::string getSerialNumber() + { + CFTypeRef value = IORegistryEntrySearchCFProperty(deviceHandle, kIOServicePlane, CFSTR("SerialNumber"), kCFAllocatorDefault, kIORegistryIterateRecursively); + std::string ret = std::string(CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingMacRoman)); + CFRelease(value); + + return ret; + } + + void updateLED(int ledIndex) + { + FFEFFESCAPE escape; + unsigned char c; + + if (forceFeedback ==0 ) + return; + + c = ledIndex; + escape.dwSize = sizeof(escape); + escape.dwCommand = 0x02; + escape.cbInBuffer = sizeof(c); + escape.lpvInBuffer = &c; + escape.cbOutBuffer = 0; + escape.lpvOutBuffer = NULL; + + if (FFDeviceEscape(forceFeedback, &escape) != FF_OK) + printf("ERROR: FFDeviceEscape.\n"); + } + + static void CallbackFunction(void* me, IOReturn result, void* refCon, void* sender) + { + ((XBox360Controller* )me)->handleCallback(result, refCon, sender); + } + + void handleCallback(IOReturn result, void* refCon, void* sender) + { + AbsoluteTime zeroTime={0,0}; + IOHIDEventStruct event; + bool found = false; + int i; + + if (sender != hidQueue) + return; + + while (result == kIOReturnSuccess) + { + result = (*hidQueue)->getNextEvent(hidQueue, &event, zeroTime, 0); + if (result != kIOReturnSuccess) + continue; + + // Check axis + for (i=0, found=FALSE; (i<6) && (!found); i++) + { + if (event.elementCookie == axis[i]) + { + int amount = 0; + if (i == 4 || i == 5) + amount = event.value * (32768/256) + 32768; + else + amount = 65536 - (event.value + 32768) - 1; + + // Clip. + if (amount > 65535) + amount = 65535; + if (amount < 0) + amount = 0; + + if (g_appleRemote.IsVerbose()) + printf("Axis %d %d.\n", i+1, amount); + CPacketBUTTON btn(i+1, "JS1:Wireless 360 Controller", BTN_AXIS | BTN_NO_REPEAT | BTN_USE_AMOUNT | BTN_QUEUE, amount); + g_appleRemote.SendPacket(btn); + + found = true; + } + } + + if (found) continue; + + // Check buttons + for (i=0, found=FALSE; (i<15) && (!found); i++) + { + if (event.elementCookie == buttons[i]) + { + if (g_appleRemote.IsVerbose()) + printf("Button: %d %d.\n", i+1, (int)event.value); + + if (i+1 == 11 && !g_appleRemote.IsProgramRunning("XBMC", 0) && + (g_appleRemote.GetServerAddress() == "127.0.0.1" || g_appleRemote.GetServerAddress() == "localhost") && + event.value) + { + g_appleRemote.LaunchApp(); + return; + } + + int flags = event.value ? BTN_DOWN : BTN_UP; + CPacketBUTTON btn(i+1, "JS1:Wireless 360 Controller", flags, 0); + g_appleRemote.SendPacket(btn); + found = true; + } + } + + if (found) continue; + + // Cookie wasn't for us? + } + } + + bool getVal(CFDictionaryRef element, const CFStringRef key, long& value) + { + CFTypeRef object = CFDictionaryGetValue(element, key); + + if ((object == NULL) || (CFGetTypeID(object) != CFNumberGetTypeID())) return false; + if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &value)) return false; + + return true; + } + + IOHIDDeviceInterface122 **hidDevice; + FFDeviceObjectReference forceFeedback; + io_service_t deviceHandle; + + IOHIDQueueInterface **hidQueue; + IOHIDElementCookie axis[6]; + IOHIDElementCookie buttons[15]; + + std::string name; + int index; + bool wireless; +}; + + +class XBox360 +{ + public: + + XBox360() + { + } + + void start() + { + pthread_create(&_itsThread, NULL, Run, (void *)this); + } + + void join() + { + void* val = 0; + pthread_join(_itsThread, &val); + } + + protected: + + static void* Run(void* param) + { + ((XBox360* )param)->run(); + return 0; + } + + void run() + { + printf("XBOX360: Registering for notifications.\n"); + io_object_t object; + + // Register for wired notifications. + IONotificationPortRef notificationObject = IONotificationPortCreate(kIOMasterPortDefault); + IOServiceAddMatchingNotification(notificationObject, kIOFirstMatchNotification, IOServiceMatching(kIOUSBDeviceClassName), callbackHandleDevice, this, &_itsOnIteratorWired); + callbackHandleDevice(this, _itsOnIteratorWired); + + IOServiceAddMatchingNotification(notificationObject, kIOTerminatedNotification, IOServiceMatching(kIOUSBDeviceClassName), callbackHandleDevice, this, &_itsOffIteratorWired); + while ((object = IOIteratorNext(_itsOffIteratorWired)) != 0) + IOObjectRelease(object); + + // Wireless notifications. + IOServiceAddMatchingNotification(notificationObject, kIOFirstMatchNotification, IOServiceMatching("WirelessHIDDevice"), callbackHandleDevice, this, &_itsOnIteratorWireless); + callbackHandleDevice(this, _itsOnIteratorWireless); + + IOServiceAddMatchingNotification(notificationObject, kIOTerminatedNotification, IOServiceMatching("WirelessHIDDevice"), callbackHandleDevice, this, &_itsOffIteratorWireless); + while ((object = IOIteratorNext(_itsOffIteratorWireless)) != 0) + IOObjectRelease(object); + + // Add notifications to the run loop. + CFRunLoopSourceRef notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationObject); + CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); + + // Run. + CFRunLoopRun(); + printf("XBOX360: Exiting.\n"); + } + + private: + + // Callback for Xbox360 device notifications. + static void callbackHandleDevice(void* param, io_iterator_t iterator) + { + io_service_t object = 0; + bool update = false; + + while ((object = IOIteratorNext(iterator))!=0) + { + IOObjectRelease(object); + update = true; + } + + if (update) + ((XBox360* )param)->updateDeviceList(); + } + + void updateDeviceList() + { + io_iterator_t iterator; + io_object_t hidDevice; + + // Scrub and whack old items. + stopDevices(); + + for (std::list<XBox360Controller*>::iterator i = controllerList.begin(); i != controllerList.end(); ++i) + delete *i; + controllerList.clear(); + + // Add new items + CFMutableDictionaryRef hidDictionary = IOServiceMatching(kIOHIDDeviceKey); + IOReturn ioReturn = IOServiceGetMatchingServices(kIOMasterPortDefault, hidDictionary, &iterator); + + if ((ioReturn != kIOReturnSuccess) || (iterator==0)) + { + printf("No devices.\n"); + return; + } + + for (int count = 1; (hidDevice = IOIteratorNext(iterator)); ) + { + bool deviceWired = IOObjectConformsTo(hidDevice, "Xbox360ControllerClass"); + bool deviceWireless = IOObjectConformsTo(hidDevice, "WirelessHIDDevice"); + + if (deviceWired || deviceWireless) + { + XBox360Controller* controller = XBox360Controller::Create(hidDevice, count, deviceWireless); + if (controller) + { + // Add to list. + printf("Adding device: %s.\n", controller->getName().c_str()); + controllerList.push_back(controller); + count++; + } + } + else + { + IOObjectRelease(hidDevice); + } + } + + IOObjectRelease(iterator); + + // Make sure all devices are started. + startDevices(); + } + + void stopDevices() + { + for (std::list<XBox360Controller*>::iterator i = controllerList.begin(); i != controllerList.end(); ++i) + (*i)->stop(); + } + + void startDevices() + { + for (std::list<XBox360Controller*>::iterator i = controllerList.begin(); i != controllerList.end(); ++i) + (*i)->start(); + } + + std::list<XBox360Controller*> controllerList; + pthread_t _itsThread; + io_iterator_t _itsOnIteratorWired, _itsOffIteratorWired; + io_iterator_t _itsOnIteratorWireless, _itsOffIteratorWireless; +}; + +#endif diff --git a/tools/EventClients/Clients/AppleRemote/iremoted.c b/tools/EventClients/Clients/AppleRemote/iremoted.c new file mode 100644 index 0000000000..42b3258d03 --- /dev/null +++ b/tools/EventClients/Clients/AppleRemote/iremoted.c @@ -0,0 +1,518 @@ +/* + * iremoted.c + * Display events received from the Apple Infrared Remote. + * + * gcc -Wall -o iremoted iremoted.c -framework IOKit -framework Carbon + * + * Copyright (c) 2006-2008 Amit Singh. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define PROGNAME "iremoted" +#define PROGVERS "2.0" + +#include <stdio.h> +#include <getopt.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <sys/errno.h> +#include <sysexits.h> +#include <mach/mach.h> +#include <mach/mach_error.h> +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/sysctl.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <mach-o/dyld.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/IOCFPlugIn.h> +#include <IOKit/hid/IOHIDLib.h> +#include <IOKit/hid/IOHIDKeys.h> +#include <IOKit/hid/IOHIDUsageTables.h> + +#include <CoreFoundation/CoreFoundation.h> +#include <Carbon/Carbon.h> + +#include <iostream> +#include <fstream> +#include <map> +#include <string> +#include <iterator> +#include <sstream> +#include <set> + +#include "AppleRemote.h" +#include "XBox360.h" + +using namespace std; + +void ParseOptions(int argc, char** argv); +void ReadConfig(); + +static struct option long_options[] = { + { "help", no_argument, 0, 'h' }, + { "server", required_argument, 0, 's' }, + { "universal", no_argument, 0, 'u' }, + { "multiremote",no_argument, 0, 'm' }, + { "timeout", required_argument, 0, 't' }, + { "verbose", no_argument, 0, 'v' }, + { "externalConfig", no_argument, 0, 'x' }, + { "appPath", required_argument, 0, 'a' }, + { "appHome", required_argument, 0, 'z' }, + { 0, 0, 0, 0 }, +}; + +static const char *options = "hsumtvxaz"; + +IOHIDElementCookie buttonNextID = 0; +IOHIDElementCookie buttonPreviousID = 0; + +std::set<IOHIDElementCookie> g_registeredCookies; + +AppleRemote g_appleRemote; + +void usage(void); +inline void print_errmsg_if_io_err(int expr, char *msg); +inline void print_errmsg_if_err(int expr, char *msg); +void QueueCallbackFunction(void *target, IOReturn result, + void *refcon, void *sender); +bool addQueueCallbacks(IOHIDQueueInterface **hqi); +void processQueue(IOHIDDeviceInterface **hidDeviceInterface); +void doRun(IOHIDDeviceInterface **hidDeviceInterface); +void getHIDCookies(IOHIDDeviceInterface122 **handle); +void createHIDDeviceInterface(io_object_t hidDevice, + IOHIDDeviceInterface ***hdi); +void setupAndRun(void); + +void +usage(void) +{ + printf("%s (version %s)\n", PROGNAME, PROGVERS); + printf(" Sends Apple Remote events to XBMC.\n\n"); + printf("Usage: %s [OPTIONS...]\n\nOptions:\n", PROGNAME); + printf(" -h, --help print this help message and exit.\n"); + printf(" -s, --server <addr> send events to the specified IP.\n"); + printf(" -u, --universal runs in Universal Remote mode.\n"); + printf(" -t, --timeout <ms> timeout length for sequences (default: 500ms).\n"); + printf(" -a, --appPath path to XBMC.app (MenuPress launch support).\n"); + printf(" -z, --appHome path to XBMC.app/Content/Resources/XBMX \n"); + printf(" -v, --verbose prints lots of debugging information.\n"); +} + +inline void +print_errmsg_if_io_err(int expr, char *msg) +{ + IOReturn err = (expr); + + if (err != kIOReturnSuccess) { + fprintf(stderr, "*** %s - %s(%x, %d).\n", msg, mach_error_string(err), + err, err & 0xffffff); + fflush(stderr); + exit(EX_OSERR); + } +} + +inline void +print_errmsg_if_err(int expr, char *msg) +{ + if (expr) { + fprintf(stderr, "*** %s.\n", msg); + fflush(stderr); + exit(EX_OSERR); + } +} + +void +QueueCallbackFunction(void *target, IOReturn result, void *refcon, void *sender) +{ + HRESULT ret = kIOReturnSuccess; + AbsoluteTime zeroTime = {0,0}; + IOHIDQueueInterface **hqi; + IOHIDEventStruct event; + + std::set<int> events; + bool bKeyDown = false; + while (ret == kIOReturnSuccess) { + hqi = (IOHIDQueueInterface **)sender; + ret = (*hqi)->getNextEvent(hqi, &event, zeroTime, 0); + if (ret != kIOReturnSuccess) + continue; + + //printf("%d %d %d\n", (int)event.elementCookie, (int)event.value, (int)event.longValue); + + if (event.value > 0) + bKeyDown = true; + + events.insert((int)event.elementCookie); + } + + if (events.size() > 1) + { + std::set<int>::iterator iter = events.find( g_appleRemote.GetButtonEventTerminator() ); + if (iter != events.end()) + events.erase(iter); + } + + std::string strEvents; + std::set<int>::const_iterator iter = events.begin(); + while (iter != events.end()) + { + //printf("*iter = %d\n", *iter); + char strEvent[10]; + snprintf(strEvent, 10, "%d_", *iter); + strEvents += strEvent; + iter++; + } + + if (bKeyDown) + g_appleRemote.OnKeyDown(strEvents); + else + g_appleRemote.OnKeyUp(strEvents); +} + +bool +addQueueCallbacks(IOHIDQueueInterface **hqi) +{ + IOReturn ret; + CFRunLoopSourceRef eventSource; + IOHIDQueueInterface ***privateData; + + privateData = (IOHIDQueueInterface ***)malloc(sizeof(*privateData)); + *privateData = hqi; + + ret = (*hqi)->createAsyncEventSource(hqi, &eventSource); + if (ret != kIOReturnSuccess) + return false; + + ret = (*hqi)->setEventCallout(hqi, QueueCallbackFunction, + NULL, &privateData); + if (ret != kIOReturnSuccess) + return false; + + CFRunLoopAddSource(CFRunLoopGetCurrent(), eventSource, + kCFRunLoopDefaultMode); + return true; +} + +void +processQueue(IOHIDDeviceInterface **hidDeviceInterface) +{ + HRESULT result; + IOHIDQueueInterface **queue; + + queue = (*hidDeviceInterface)->allocQueue(hidDeviceInterface); + if (!queue) { + fprintf(stderr, "Failed to allocate event queue.\n"); + return; + } + + (void)(*queue)->create(queue, 0, 99); + + std::set<IOHIDElementCookie>::const_iterator iter = g_registeredCookies.begin(); + while (iter != g_registeredCookies.end()) + { + (void)(*queue)->addElement(queue, *iter, 0); + iter++; + } + + addQueueCallbacks(queue); + + result = (*queue)->start(queue); + + CFRunLoopRun(); + + result = (*queue)->stop(queue); + + result = (*queue)->dispose(queue); + + (*queue)->Release(queue); +} + +void +doRun(IOHIDDeviceInterface **hidDeviceInterface) +{ + IOReturn ioReturnValue; + + ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeSeizeDevice); + if (ioReturnValue == kIOReturnExclusiveAccess) { + printf("exclusive lock failed\n"); + } + + processQueue(hidDeviceInterface); + + if (ioReturnValue == KERN_SUCCESS) + ioReturnValue = (*hidDeviceInterface)->close(hidDeviceInterface); + (*hidDeviceInterface)->Release(hidDeviceInterface); +} + +void +getHIDCookies(IOHIDDeviceInterface122 **handle) +{ + IOHIDElementCookie cookie; + CFTypeRef object; + long number; + long usage; + long usagePage; + CFArrayRef elements; + CFDictionaryRef element; + IOReturn result; + + if (!handle || !(*handle)) + return ; + + result = (*handle)->copyMatchingElements(handle, NULL, &elements); + + if (result != kIOReturnSuccess) { + fprintf(stderr, "Failed to copy cookies.\n"); + exit(1); + } + + CFIndex i; + for (i = 0; i < CFArrayGetCount(elements); i++) { + element = (CFDictionaryRef)CFArrayGetValueAtIndex(elements, i); + object = (CFDictionaryGetValue(element, CFSTR(kIOHIDElementCookieKey))); + if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) + continue; + if(!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number)) + continue; + cookie = (IOHIDElementCookie)number; + object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsageKey)); + if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) + continue; + if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &number)) + continue; + usage = number; + object = CFDictionaryGetValue(element,CFSTR(kIOHIDElementUsagePageKey)); + if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) + continue; + if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &number)) + continue; + usagePage = number; + if (usagePage == 0x06 && usage == 0x22 ) // event code "39". menu+select for 5 secs + g_registeredCookies.insert(cookie); + else if (usagePage == 0xff01 && usage == 0x23 ) // event code "35". long click - select + g_registeredCookies.insert(cookie); + else if (usagePage == kHIDPage_GenericDesktop && usage >= 0x80 && usage <= 0x8d ) // regular keys + g_registeredCookies.insert(cookie); + else if (usagePage == kHIDPage_Consumer && usage >= 0xB0 && usage <= 0xBF) + g_registeredCookies.insert(cookie); + else if (usagePage == kHIDPage_Consumer && usage == kHIDUsage_Csmr_Menu ) // event code "18". long "menu" + g_registeredCookies.insert(cookie); + } +} + +void +createHIDDeviceInterface(io_object_t hidDevice, IOHIDDeviceInterface ***hdi) +{ + io_name_t className; + IOCFPlugInInterface **plugInInterface = NULL; + HRESULT plugInResult = S_OK; + SInt32 score = 0; + IOReturn ioReturnValue = kIOReturnSuccess; + + ioReturnValue = IOObjectGetClass(hidDevice, className); + print_errmsg_if_io_err(ioReturnValue, "Failed to get class name."); + + ioReturnValue = IOCreatePlugInInterfaceForService( + hidDevice, + kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &plugInInterface, + &score); + + if (ioReturnValue != kIOReturnSuccess) + return; + + plugInResult = (*plugInInterface)->QueryInterface( + plugInInterface, + CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), + (LPVOID*)hdi); + print_errmsg_if_err(plugInResult != S_OK, + "Failed to create device interface.\n"); + + (*plugInInterface)->Release(plugInInterface); +} + +void +setupAndRun(void) +{ + CFMutableDictionaryRef hidMatchDictionary = NULL; + io_service_t hidService = (io_service_t)0; + io_object_t hidDevice = (io_object_t)0; + IOHIDDeviceInterface **hidDeviceInterface = NULL; + IOReturn ioReturnValue = kIOReturnSuccess; + + //hidMatchDictionary = IOServiceNameMatching("AppleIRController"); + hidMatchDictionary = IOServiceMatching("AppleIRController"); + hidService = IOServiceGetMatchingService(kIOMasterPortDefault, + hidMatchDictionary); + + if (!hidService) { + fprintf(stderr, "Apple Infrared Remote not found.\n"); + exit(1); + } + + hidDevice = (io_object_t)hidService; + + createHIDDeviceInterface(hidDevice, &hidDeviceInterface); + getHIDCookies((IOHIDDeviceInterface122 **)hidDeviceInterface); + ioReturnValue = IOObjectRelease(hidDevice); + print_errmsg_if_io_err(ioReturnValue, "Failed to release HID."); + + if (hidDeviceInterface == NULL) { + fprintf(stderr, "No HID.\n"); + exit(1); + } + + g_appleRemote.Initialize(); + doRun(hidDeviceInterface); + + if (ioReturnValue == KERN_SUCCESS) + ioReturnValue = (*hidDeviceInterface)->close(hidDeviceInterface); + + (*hidDeviceInterface)->Release(hidDeviceInterface); +} + +void Reconfigure(int nSignal) +{ + if (nSignal == SIGHUP) { + //fprintf(stderr, "Reconfigure\n"); + ReadConfig(); + } else { + exit(0); + } +} + +void ReadConfig() +{ + // Compute filename. + string strFile = getenv("HOME"); + strFile += "/Library/Application Support/XBMC/XBMCHelper.conf"; + + // Open file. + ifstream ifs(strFile.c_str()); + if (!ifs) + return; + + // Read file. + stringstream oss; + oss << ifs.rdbuf(); + + if (!ifs && !ifs.eof()) + return; + + // Tokenize. + string strData(oss.str()); + istringstream is(strData); + vector<string> args = vector<string>(istream_iterator<string>(is), istream_iterator<string>()); + + // Convert to char**. + int argc = args.size() + 1; + char** argv = new char*[argc + 1]; + int i = 0; + argv[i++] = "XBMCHelper"; + + for (vector<string>::iterator it = args.begin(); it != args.end(); ) + argv[i++] = (char* )(*it++).c_str(); + + argv[i] = 0; + + // Parse the arguments. + ParseOptions(argc, argv); + + delete[] argv; +} + +void ParseOptions(int argc, char** argv) +{ + int c, option_index = 0; + bool readExternal = false; + + while ((c = getopt_long(argc, argv, options, long_options, &option_index)) != -1) + { + switch (c) { + case 'h': + usage(); + exit(0); + break; + case 'v': + g_appleRemote.SetVerbose(true); + break; + case 's': + g_appleRemote.SetServerAddress(optarg); + break; + case 'u': + g_appleRemote.SetRemoteMode(REMOTE_UNIVERSAL); + break; + case 'm': + break; + case 't': + if (optarg) + g_appleRemote.SetMaxClickTimeout( atof(optarg) * 0.001 ); + break; + case 'a': + g_appleRemote.SetAppPath(optarg); + break; + case 'z': + g_appleRemote.SetAppHome(optarg); + break; + case 'x': + readExternal = true; + break; + default: + usage(); + exit(1); + break; + } + } + //reset getopts state + optreset = 1; + optind = 0; + + if (readExternal == true) + ReadConfig(); +} + +int +main (int argc, char **argv) +{ + ParseOptions(argc,argv); + + signal(SIGHUP, Reconfigure); + signal(SIGINT, Reconfigure); + signal(SIGTERM, Reconfigure); + + XBox360 xbox360; + xbox360.start(); + + setupAndRun(); + + xbox360.join(); + + return 0; +} diff --git a/tools/EventClients/Clients/J2ME Client/README b/tools/EventClients/Clients/J2ME Client/README new file mode 100644 index 0000000000..ee1426812c --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/README @@ -0,0 +1,23 @@ +1. Can I use it? +To use the J2ME client only CLDC 1.0 and MIDP 1.0 is needed. +The client will also need bluetooth and must be able to initialize the connection. + +2. Compiling the client +To compile the J2ME Application some libraries are needed: + *Suns Wireless Toolkit + *Java + *Ant +Before it can be compiled the link to Suns Wireless Toolkit are needed and are in build.xml +under <property name="WTK" value=""> where the value should be the path to the toolkit. +When compiling in ubuntu all that is needed are the following command +# ant +The final jar file will end up in build/release/ +For installations on some J2ME devices a jad file is needed and it needs the correct filesize of the JAR. This is not an +automated process and thus open the build/release/XBMCRemote.jad and alter it is requiered. The filesize is in bytes +and reflects that of build/release/XBMCRemote.jar + +3. Pre Usage +To use the EventClient you'll need to run the EventClient on a computer by: +# python XBMCJ2ME.py +It depends on Pybluez (http://org.csail.mit.edu/pybluez/) and is available in repository +# sudo apt-get install python-bluetooth diff --git a/tools/EventClients/Clients/J2ME Client/build.xml b/tools/EventClients/Clients/J2ME Client/build.xml new file mode 100644 index 0000000000..4e583b21bc --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/build.xml @@ -0,0 +1,31 @@ +<project name="XBMC Remote" default="make"> + <property name="WTK" value=""/> + <property name="OUTNAME" value="XBMCRemote"/> + <property name="MIDP10_LIB" value="${WTK}/lib/midpapi10.jar"/> + <property name="CLDC10_LIB" value="${WTK}/lib/cldcapi10.jar"/> + <property name="JSR082_LIB" value="${WTK}/lib/jsr082.jar"/> + <property name="ALL_LIB" value="${MIDP10_LIB}:${CLDC10_LIB}:${JSR082_LIB}"/> + + <target name="compile"> + <tstamp/> + <mkdir dir="build/compiled"/> + <javac destdir="build/compiled" srcdir="src" bootclasspath="${ALL_LIB}" target="1.1"/> + </target> + + <target name="preverify" depends="compile"> + <mkdir dir="build/preverified"/> + <exec executable="${WTK}/bin/preverify"> + <arg line="-classpath ${ALL_LIB}"/> + <arg line="-d build/preverified"/> + <arg line="build/compiled"/> + </exec> + </target> + + <target name="make" depends="preverify"> + <mkdir dir="build/release"/> + <jar basedir="build/preverified" jarfile="build/release/${OUTNAME}.jar" manifest="manifest.mf"> + <fileset dir="icons"/> + </jar> + <copy file="src/XBMCRemote.jad" tofile="build/release/${OUTNAME}.jad"/> + </target> +</project> diff --git a/tools/EventClients/Clients/J2ME Client/icons/icon.png b/tools/EventClients/Clients/J2ME Client/icons/icon.png Binary files differnew file mode 100644 index 0000000000..812237b3ac --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/icons/icon.png diff --git a/tools/EventClients/Clients/J2ME Client/j2me_remote.py b/tools/EventClients/Clients/J2ME Client/j2me_remote.py new file mode 100755 index 0000000000..5f78f83ffd --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/j2me_remote.py @@ -0,0 +1,175 @@ +#!/usr/bin/python +# +# XBMC Media Center +# J2ME Remote +# Copyright (c) 2008 topfs2 +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import sys +try: + from xbmc.xbmcclient import * + from xbmc.bt.bt import * + from xbmc.defs import * +except: + sys.path.append('../../lib/python') + from xbmcclient import * + from bt.bt import * + ICON_PATH = "../../icons/" + +from socket import * +import os +from threading import Thread + +host = "localhost" +port = 9777 +addr = (host, port) +sock = socket(AF_INET,SOCK_DGRAM) + +def send_key(key): + packet = PacketBUTTON(map_name="JS0:J2ME", code=key, repeat=0, queue=0) + packet.send(sock, addr) + +def send_message(caption, msg): + packet = PacketNOTIFICATION(caption, + msg, + ICON_PNG, + icon_file=ICON_PATH + "/phone.png") + + packet.send(sock, addr) + +def send_ImageToBluetooth(Image): + imageData = file( Image ).read() + print "Data len ", len( imageData ) + client_sock.send( format.uint32( len( imageData) ) ) + client_sock.sendall(imageData) + print "Sent file" + +class Ping(Thread): + def __init__ (self): + Thread.__init__(self) + def run(self): + import time + while 1: # ping the server every 19s + packet = PacketPING() + packet.send(sock, addr) + time.sleep (19) + +def main(): + import time + + # connect to localhost, port 9777 using a UDP socket + # this only needs to be done once. + # by default this is where XBMC will be listening for incoming + # connections. + server_sock=bt_create_rfcomm_socket() + server_sock.listen(2) + + portBT = server_sock.getsockname()[1] + + uuid = "ACDC" + bt_advertise(socket=server_sock, name="XBMC Remote", uuid=uuid) + + print "Waiting for connection on RFCOMM channel %d" % portBT + + packet = PacketHELO(devicename="J2ME Remote", + icon_type=ICON_PNG, + icon_file=ICON_PATH + "/phone.png") + packet.send(sock, addr) + Ping().start() + while(True): + try: + client_sock, client_info = server_sock.accept() + print "Accepted connection from ", client_info + client_addr, client_port = client_info + runFlag = True + firstRun = True + print "Accepted connection from ", client_addr + except KeyboardInterrupt: + packet = PacketLOG(LOGNOTICE, "J2ME: User interrupted") + packet.send(sock, addr) + bt_stop_advertising(socket = server_sock) + server_sock.close() + sys.exit(0) + try: + while runFlag: + if firstRun: + client_name = client_sock.recv(1024) + firstRun = False + send_message("J2ME: Phone Connected", client_name) + packet = PacketLOG(LOGNOTICE, "Phone Connected") + packet.send(sock, addr) + data = client_sock.recv(3) + if(data[0] == "0"): + if(data[1] == "0"): + runFlag = False + packet = PacketLOG(LOGNOTICE, "J2ME: Recieved disconnect command") + packet.send(sock, addr) + client_sock.close() + if(data[1] == "1"): + print "Shuting down server" + client_sock.close() + bt_stop_advertising(socket = server_sock) + server_sock.close() + packet = PacketBYE() + packet.send(sock, addr) + sys.exit(0) + + elif(data[0] == "2"): + print "<button id=\"%i\">" % ord( data[1] ) + send_key(ord( data[1] ) ) + else: + print "Unkown received data [%s]" % data + except IOError: + print "Lost connection too %s" % client_name + runFlag = False + send_message("Phone Disconnected", client_name) + pass + except KeyboardInterrupt: + packet = PacketLOG(LOGNOTICE, "J2ME: User interrupted") + packet.send(sock, addr) + client_sock.close() + bt_stop_advertising(socket = server_sock) + server_sock.close() + packet = PacketBYE() # PacketPING if you want to ping + packet.send(sock, addr) + sys.exit(0) + +def usage(): + print """ +Java Bluetooth Phone Remote Control Client for XBMC v0.1 + +Usage for xbmcphone.py + --address ADDRESS (default: localhost) + --port PORT (default: 9777) + --help (Brings up this message) +""" + +if __name__=="__main__": + try: + i = 0 + while (i < len(sys.argv)): + if (sys.argv[i] == "--address"): + host = sys.argv[i + 1] + elif (sys.argv[i] == "--port"): + port = sys.argv[i + 1] + elif (sys.argv[i] == "--help"): + usage() + sys.exit(0) + i = i + 1 + main() + except: + sys.exit(0) diff --git a/tools/EventClients/Clients/J2ME Client/manifest.mf b/tools/EventClients/Clients/J2ME Client/manifest.mf new file mode 100644 index 0000000000..49cddf5c28 --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/manifest.mf @@ -0,0 +1,7 @@ +MIDlet-1: MainScreen, , MainScreen +MIDlet-Vendor: team-xbmc +MIDlet-Name: XBMC Remote +MIDlet-Icon: icon.png +MIDlet-Version: 0.1 +MicroEdition-Configuration: CLDC-1.0 +MicroEdition-Profile: MIDP-1.0 diff --git a/tools/EventClients/Clients/J2ME Client/src/BluetoothCommunicator.java b/tools/EventClients/Clients/J2ME Client/src/BluetoothCommunicator.java new file mode 100644 index 0000000000..2db3f54dd2 --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/src/BluetoothCommunicator.java @@ -0,0 +1,228 @@ +/* +* XBMC Media Center +* UDP Event Server +* Copyright (c) 2008 topfs2 +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +import javax.microedition.io.Connector; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import javax.microedition.io.StreamConnection; +import java.lang.NullPointerException; +import java.util.Vector; +import javax.bluetooth.*; +import javax.bluetooth.LocalDevice; +import javax.microedition.lcdui.Form; +import javax.microedition.lcdui.Image; +import javax.microedition.lcdui.Display; +import java.lang.*; + +public class BluetoothCommunicator extends Thread +{ + private boolean Run; + private Form Log; + private BluetoothEvent recvEvent; + + protected static String Address = null; + private static StreamConnection Connection = null; + private static DataInputStream inputStream = null; + private static DataOutputStream outputStream = null; + + public BluetoothCommunicator(BluetoothEvent recvEvent, Form Log) + { + this.recvEvent = recvEvent; + this.Log = Log; + } + + public static boolean Connect(Form Log, String addr) + { + Log.append("Going to connect\n"); + try + { + Connection = (StreamConnection)Connector.open(addr); + + if (Connection == null) + { + Log.append("Connector.open returned null\n"); + return false; + } + else + { + Log.append("Connector.open returned connection\n"); + inputStream = Connection.openDataInputStream(); + outputStream = Connection.openDataOutputStream(); + Address = addr; + return true; + } + } + catch (Exception e) + { + Log.append("Exception" + e.getMessage() + "\n"); + try + { + if (Connection != null) + Connection.close(); + } + catch (Exception ee) + { + Log.append("Exception " + ee.getMessage() + "\n"); + } + Connection = null; + return false; + } + } + + public static boolean Handshake(Form Log, Display disp) + { + if (Connection == null) + return false; + try + { + LocalDevice localDevice = LocalDevice.getLocalDevice(); + Send(localDevice.getFriendlyName()); + + return true; + } + catch(NullPointerException NPE) + { + Log.append("Null " + NPE.getMessage()); + } + catch (IndexOutOfBoundsException IOBE) + { + Log.append("IndexOutOfBounds " + IOBE.getMessage()); + } + catch (IllegalArgumentException IAE) + { + Log.append("illegalArg " + IAE.getMessage()); + } + catch(Exception e) + { + Log.append("Exception in handshake " + e.getMessage()); + } + return false; + } + public void run() + { + Run = true; + while (Run) + { + try + { + if (inputStream.available() <= 0) + sleep(10); + else + { + Log.append("run:Ava " + inputStream.available() + "\n"); + byte []b = new byte[1]; + b[0] = (byte)255; // safe thing for now + inputStream.read(b, 0, 1); + byte[] recv = null; + switch (b[0]) + { + case BluetoothEvent.RECV_SYSTEM: + recv = new byte[]{ inputStream.readByte() }; + break; + case BluetoothEvent.RECV_COMMAND: + recv = new byte[]{ inputStream.readByte() }; + break; + case BluetoothEvent.RECV_IMAGE: + Log.append("Recv_Image\n"); + recv = RecvImage(Log); + break; + } + if (recv != null) + recvEvent.Recv(b[0], recv); + } + } + catch (Exception e) + { + Log.append("RecvException " + e.getMessage()); + } + } + } + public void close() + { + Run = false; + } + public static byte[] RecvImage(Form Log) + { + try + { + int length = inputStream.readInt(); + Log.append("readUnsignedShort: " + length + "\n"); + byte[] arrayToUse = new byte[length]; + inputStream.readFully(arrayToUse, 0, length); + return arrayToUse; + } + catch (Exception e ) + { + Log.append("Exception RecvImage " + e.getMessage()); + return null; + } + } + + public static int Recv(byte[] arrayToUse, Form Log ) + { + if (Connection == null) + return -1; + try + { + return inputStream.read(arrayToUse); + } + catch (Exception e) + { + Log.append("Exception in Recv " + e.getMessage()); + return -1; + } + } + + public static boolean Send(byte[] packet) + { + if (Connection == null) + return false; + try + { + outputStream.write(packet, 0, packet.length); + return true; + } + catch (Exception e) + { + return false; + } + } + + public static boolean Send(String packet) + { + return Send(packet.getBytes()); + } + + public static void Disconnect() + { + if (Connection == null) + return; + + try + { + byte[] packet = { '0', '0' }; + Send(packet); + Connection.close(); + } + catch (Exception e) + { } + + Connection = null; + } +} diff --git a/tools/EventClients/Clients/J2ME Client/src/BluetoothEvent.java b/tools/EventClients/Clients/J2ME Client/src/BluetoothEvent.java new file mode 100644 index 0000000000..6557dca2e0 --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/src/BluetoothEvent.java @@ -0,0 +1,27 @@ +/* +* XBMC Media Center +* UDP Event Server +* Copyright (c) 2008 topfs2 +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +public interface BluetoothEvent { + public final int RECV_SYSTEM = 0; + public final int RECV_COMMAND = 1; + public final int RECV_IMAGE = 2; + + // The header is a byte IRL. 0 - 255 and tells packet type + public void Recv(int Header, byte[] Payload); +} diff --git a/tools/EventClients/Clients/J2ME Client/src/BluetoothServiceDiscovery.java b/tools/EventClients/Clients/J2ME Client/src/BluetoothServiceDiscovery.java new file mode 100644 index 0000000000..3ff71f13f2 --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/src/BluetoothServiceDiscovery.java @@ -0,0 +1,126 @@ +/* +* XBMC Media Center +* UDP Event Server +* Copyright (c) 2008 topfs2 +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +import java.util.Vector; +import javax.bluetooth.DeviceClass; +import javax.bluetooth.DiscoveryAgent; +import javax.bluetooth.DiscoveryListener; +import javax.bluetooth.LocalDevice; +import javax.bluetooth.RemoteDevice; +import javax.bluetooth.ServiceRecord; +import javax.bluetooth.UUID; + +import javax.microedition.lcdui.*; + +public class BluetoothServiceDiscovery implements DiscoveryListener +{ + private static Object lock=new Object(); + private static Vector vecDevices=new Vector(); + private static String connectionURL=null; + + public static String Scan(Form Log, String ScanForUUID) throws Exception + { + BluetoothServiceDiscovery bluetoothServiceDiscovery=new BluetoothServiceDiscovery(); + //display local device address and name + LocalDevice localDevice = LocalDevice.getLocalDevice(); + //find devices + DiscoveryAgent agent = localDevice.getDiscoveryAgent(); + + agent.startInquiry(DiscoveryAgent.GIAC, bluetoothServiceDiscovery); + try + { + synchronized(lock) + { lock.wait(); } + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + Log.append("Device Inquiry Completed. \n"); + + int deviceCount=vecDevices.size(); + if(deviceCount <= 0) + { + Log.append("No Devices Found .\n"); + return null; + } + else + { + Log.append("Bluetooth Devices: \n"); + for (int i = 0; i <deviceCount; i++) + { + RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(i); + String t = i + ": \"" + remoteDevice.getFriendlyName(true) + "\""; + Log.append(t + "\n"); + } + } + UUID[] uuidSet = new UUID[1]; + if (ScanForUUID != null) + uuidSet[0]=new UUID(ScanForUUID, true); + else + uuidSet[0]=new UUID("ACDC", true); + + for (int i = 0; i < vecDevices.capacity(); i++) + { + RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(i); + String t = remoteDevice.getFriendlyName(true); + agent.searchServices(null,uuidSet,remoteDevice,bluetoothServiceDiscovery); + try + { + synchronized(lock) + { lock.wait(); } + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + if(connectionURL != null) + return connectionURL; + } + Log.append("Couldn't find any computer that were suitable\n"); + return null; + } + + public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) + { + if(!vecDevices.contains(btDevice)) + vecDevices.addElement(btDevice); + } + + public void servicesDiscovered(int transID, ServiceRecord[] servRecord) + { + if(servRecord!=null && servRecord.length>0){ + connectionURL=servRecord[0].getConnectionURL(0,false); + } + synchronized(lock) + { lock.notify(); } + } + + public void serviceSearchCompleted(int transID, int respCode) + { + synchronized(lock) + { lock.notify(); } + } + + public void inquiryCompleted(int discType) + { + synchronized(lock) + { lock.notify(); } + } +} diff --git a/tools/EventClients/Clients/J2ME Client/src/KeyCanvas.java b/tools/EventClients/Clients/J2ME Client/src/KeyCanvas.java new file mode 100644 index 0000000000..8c2153c0d6 --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/src/KeyCanvas.java @@ -0,0 +1,66 @@ +/* +* XBMC Media Center +* UDP Event Server +* Copyright (c) 2008 topfs2 +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +import javax.microedition.lcdui.*; + +public class KeyCanvas extends Canvas +{ + private KeyHandler m_SendKey = null; + private Image Cover = null; + private boolean SetCover = false; + + public KeyCanvas(KeyHandler sendKey) + { + m_SendKey = sendKey; + try + { +// Cover = Image.createImage("home.png"); + } + catch (Exception e) + { } + } + + public void SetCover(Image newCover) + { + if (newCover != null) + { + SetCover = true; + Cover = newCover; + } + } + + public void paint(Graphics g) + { + g.drawRect(0, 0, this.getWidth(), this.getHeight()); + if (Cover != null) + g.drawImage(Cover, 0, 0, g.TOP|g.LEFT); + } + + public void keyPressed(int keyCode) + { + if (m_SendKey != null) + m_SendKey.keyPressed(keyCode); + } + + public void keyRepeated(int keyCode) + { + if (m_SendKey != null) + m_SendKey.keyPressed(keyCode); + } +} diff --git a/tools/EventClients/Clients/J2ME Client/src/KeyHandler.java b/tools/EventClients/Clients/J2ME Client/src/KeyHandler.java new file mode 100644 index 0000000000..a6a5ac10d0 --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/src/KeyHandler.java @@ -0,0 +1,23 @@ +/* +* XBMC Media Center +* UDP Event Server +* Copyright (c) 2008 topfs2 +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +public interface KeyHandler +{ + public void keyPressed(int keyCode); +} diff --git a/tools/EventClients/Clients/J2ME Client/src/MainScreen.java b/tools/EventClients/Clients/J2ME Client/src/MainScreen.java new file mode 100644 index 0000000000..2e68c7d211 --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/src/MainScreen.java @@ -0,0 +1,271 @@ +/* +* XBMC Media Center +* UDP Event Server +* Copyright (c) 2008 topfs2 +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +import java.util.Vector; +import javax.bluetooth.DeviceClass; +import javax.bluetooth.DiscoveryAgent; +import javax.bluetooth.DiscoveryListener; +import javax.bluetooth.LocalDevice; +import javax.bluetooth.RemoteDevice; +import javax.bluetooth.ServiceRecord; +import javax.bluetooth.UUID; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class MainScreen extends MIDlet implements CommandListener, KeyHandler, BluetoothEvent +{ + private boolean LogActive = true; + private final int VersionMajor = 0; + private final int VersionMinor = 1; + private final String Version = (VersionMajor + "." + VersionMinor); + + private final Command CMD_OK = new Command("OK", Command.OK, 1); + private final Command CMD_CONNECT = new Command("Connect", Command.OK, 1); + private final Command CMD_DISCONNECT = new Command("Disconnect", Command.CANCEL, 1); + private final Command CMD_EXIT = new Command("Exit", Command.CANCEL, 1); + private final Command CMD_LOG = new Command("Log", Command.OK, 1); + private final Command CMD_SHOWREMOTE = new Command("Remote", Command.OK, 1); + private Display display; + private Form MainForm; + + private KeyCanvas keyHandler; + private BluetoothCommunicator RecvThread; + + private final int CONNECTED = 1; + private final int NOT_CONNECTED = -1; + private final int CONNECTING = 0; + + private int Connect = NOT_CONNECTED; + + public MainScreen() + { + display = Display.getDisplay(this); + keyHandler = new KeyCanvas(this); + keyHandler.addCommand(CMD_LOG); + keyHandler.addCommand(CMD_DISCONNECT); + keyHandler.setCommandListener(this); + } + + + public void Disconnect() + { + RecvThread.close(); + BluetoothCommunicator.Disconnect(); + MainForm.removeCommand(CMD_DISCONNECT); + MainForm.removeCommand(CMD_SHOWREMOTE); + MainForm.addCommand(CMD_CONNECT); + Connect = NOT_CONNECTED; + } + + public void Connect() + { + if (Connect == CONNECTED) + return; + Connect = CONNECTING; + MainForm = CreateForm("Connect log"); + display.setCurrent(MainForm); + try + { + String Connectable = BluetoothServiceDiscovery.Scan(MainForm, "ACDC"); + if (Connectable != null) + { + MainForm.append("\n" + Connectable); + display.setCurrent(MainForm); + if (BluetoothCommunicator.Connect(MainForm, Connectable)) + Connect = CONNECTED; + else + Connect = NOT_CONNECTED; + + display.setCurrent(MainForm); + BluetoothCommunicator.Handshake(MainForm, display); + RecvThread = new BluetoothCommunicator(this, MainForm); + + display.setCurrent(MainForm); + } + } + catch (Exception e) + { + MainForm.append("Error: Couldn't Search"); + Connect = NOT_CONNECTED; + display.setCurrent(MainForm); + return; + } + + if (Connect == CONNECTED) + { + MainForm.addCommand(CMD_SHOWREMOTE); + MainForm.addCommand(CMD_DISCONNECT); + MainForm.append("Connected to a server now we start the receive thread\n"); + RecvThread.start(); + } + else + { + MainForm.addCommand(CMD_CONNECT); + MainForm.addCommand(CMD_EXIT); + MainForm.append("Not connected to a server"); + } + setCurrent(); + } + + public void startApp() + { + int length = ((255 << 8) | (255)); + System.out.println("Len " + length); + + + MainForm = CreateForm("XBMC Remote"); + MainForm.append("Hi and welcome to the version " + Version + " of XBMC Remote.\nPressing Connect will have this remote connect to the first available Server"); + setCurrent(); + } + + private Form CreateForm(String Title) + { + Form rtnForm = new Form(Title); + if (Connect == CONNECTED) + rtnForm.addCommand(CMD_OK); + else if (Connect == NOT_CONNECTED) + rtnForm.addCommand(CMD_CONNECT); + + if (Connect == CONNECTED) + rtnForm.addCommand(CMD_DISCONNECT); + else if (Connect == NOT_CONNECTED) + rtnForm.addCommand(CMD_EXIT); + + rtnForm.setCommandListener(this); + return rtnForm; + } + + private void setCurrent() + { + setCurrent(false); + } + private void setCurrent(boolean forceLog) + { + if (forceLog) + display.setCurrent(MainForm); + else if (Connect == CONNECTED) + { + display.setCurrent(keyHandler); + keyHandler.repaint(); + } + else + { + display.setCurrent(MainForm); + } + } + + public void pauseApp() + { + } + + public void destroyApp(boolean unconditional) + { + if (Connect == CONNECTED) + { + BluetoothCommunicator.Disconnect(); + RecvThread.close(); + } + } + + public void commandAction(Command c, Displayable d) + { + if (c.equals(CMD_LOG)) + setCurrent(true); + else if (c.equals(CMD_SHOWREMOTE)) + { + display.setCurrent(keyHandler); + keyHandler.repaint(); + } + else if (d.equals(MainForm)) + { + if (c.equals(CMD_OK)) + { + byte[] Packet = {'1', '1'}; // 48 == '0' + BluetoothCommunicator.Send(Packet); + } + else if (c.equals(CMD_CONNECT)) + { + this.Connect(); + } + else if (c.equals(CMD_EXIT)) + System.out.println("QUIT"); + else if (c.equals(CMD_DISCONNECT)) + { + this.Disconnect(); + this.RecvThread.close(); + setCurrent(); + } + } + else if (d.equals(keyHandler)) + { + if (c.equals(CMD_OK)) + { + byte[] Packet = {'2', (byte)251 }; + BluetoothCommunicator.Send(Packet); + } + else if (c.equals(CMD_DISCONNECT)) + { + this.Disconnect(); + Connect = NOT_CONNECTED; + setCurrent(); + } + } + } + + public void keyPressed(int keyCode) + { + byte[] Packet = {'2', (byte)keyCode}; + if (keyCode >= Canvas.KEY_NUM0 && keyCode <= Canvas.KEY_NUM9) + Packet[1] = (byte)keyCode; + + else if (keyCode == Canvas.UP || keyCode == -1) + Packet[1] = 'U'; + else if (keyCode == Canvas.DOWN || keyCode == -2) + Packet[1] = 'D'; + else if (keyCode == Canvas.LEFT || keyCode == -3) + Packet[1] = 'L'; + else if (keyCode == Canvas.RIGHT || keyCode == -4) + Packet[1] = 'R'; + + else if (keyCode == Canvas.KEY_STAR) + Packet[1] = '*'; + else if (keyCode == Canvas.KEY_POUND) + Packet[1] = '#'; + + BluetoothCommunicator.Send(Packet); + System.out.println("got" + keyCode + " I'll send [" + Packet[0] + "," + Packet[1] + "]"); + } + public void Recv(int Header, byte[] Payload) + { + switch(Header) + { + case BluetoothEvent.RECV_COMMAND: + break; + case BluetoothEvent.RECV_SYSTEM: + if (Payload[0] == 0) + this.Disconnect(); + break; + case BluetoothEvent.RECV_IMAGE: + keyHandler.SetCover(Image.createImage(Payload, 0, Payload.length)); + break; + } + } +} diff --git a/tools/EventClients/Clients/J2ME Client/src/XBMCRemote.jad b/tools/EventClients/Clients/J2ME Client/src/XBMCRemote.jad new file mode 100644 index 0000000000..bd283d8903 --- /dev/null +++ b/tools/EventClients/Clients/J2ME Client/src/XBMCRemote.jad @@ -0,0 +1,9 @@ +MIDlet-1: MainScreen, , MainScreen
+MIDlet-Icon: icon.png
+MIDlet-Jar-Size: 12153
+MIDlet-Jar-URL: XBMC Remote.jar
+MIDlet-Name: XBMC Remote
+MIDlet-Vendor: team-xbmc
+MIDlet-Version: 0.1
+MicroEdition-Configuration: CLDC-1.0
+MicroEdition-Profile: MIDP-1.0 diff --git a/tools/EventClients/Clients/OSXRemote/Makefile.in b/tools/EventClients/Clients/OSXRemote/Makefile.in new file mode 100644 index 0000000000..4b66f568db --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/Makefile.in @@ -0,0 +1,18 @@ +#convenience makefile to allow headless osx build + +DEBUG_FLAGS=@DEBUG_FLAGS@ + +#check for debug build +ifneq (,$(findstring _DEBUG, $(DEBUG_FLAGS))) + CONFIGURATION=Debug +else + CONFIGURATION=Release +endif + +all: + xcodebuild -sdk macosx10.4 -configuration $(CONFIGURATION) + +clean: + xcodebuild clean -configuration $(CONFIGURATION) + +.PHONY: all clean diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/AppleRemote.h b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/AppleRemote.h new file mode 100644 index 0000000000..4bb2f0998d --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/AppleRemote.h @@ -0,0 +1,44 @@ +/***************************************************************************** + * RemoteControlWrapper.h + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> +#import "HIDRemoteControlDevice.h" + +/* Interacts with the Apple Remote Control HID device + The class is not thread safe + */ +@interface AppleRemote : HIDRemoteControlDevice { + int deviceID; +} + +//AppleRemote supports different device IDs (as long they are not paired) +//the deviceID of last sent button can be queried with - (int) deviceID +- (int) deviceID; + +//overwritten from baseclass to get notified of device changes +- (eCookieModifier) handleCookie: (long)f_cookie value:(int) f_value; +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/AppleRemote.m b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/AppleRemote.m new file mode 100644 index 0000000000..152e755aa5 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/AppleRemote.m @@ -0,0 +1,108 @@ +/***************************************************************************** + * RemoteControlWrapper.m + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import "AppleRemote.h" + +#import <mach/mach.h> +#import <mach/mach_error.h> +#import <IOKit/IOKitLib.h> +#import <IOKit/IOCFPlugIn.h> +#import <IOKit/hid/IOHIDKeys.h> + +const char* AppleRemoteDeviceName = "AppleIRController"; + +// the WWDC 07 Leopard Build is missing the constant +#ifndef NSAppKitVersionNumber10_4 +#define NSAppKitVersionNumber10_4 824 +#endif + +@implementation AppleRemote + ++ (const char*) remoteControlDeviceName { + return AppleRemoteDeviceName; +} + +- (void) setCookieMappingInDictionary: (NSMutableDictionary*) _cookieToButtonMapping { + if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_4) { + // 10.4.x Tiger + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlus] forKey:@"14_12_11_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMinus] forKey:@"14_13_11_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu] forKey:@"14_7_6_14_7_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay] forKey:@"14_8_6_14_8_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight] forKey:@"14_9_6_14_9_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft] forKey:@"14_10_6_14_10_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight_Hold] forKey:@"14_6_4_2_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft_Hold] forKey:@"14_6_3_2_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu_Hold] forKey:@"14_6_14_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay_Hold] forKey:@"18_14_6_18_14_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteControl_Switched] forKey:@"19_"]; + } else { + // 10.5.x Leopard + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlus] forKey:@"31_29_28_19_18_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMinus] forKey:@"31_30_28_19_18_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu] forKey:@"31_20_19_18_31_20_19_18_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay] forKey:@"31_21_19_18_31_21_19_18_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight] forKey:@"31_22_19_18_31_22_19_18_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft] forKey:@"31_23_19_18_31_23_19_18_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight_Hold] forKey:@"31_19_18_4_2_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft_Hold] forKey:@"31_19_18_3_2_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu_Hold] forKey:@"31_19_18_31_19_18_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay_Hold] forKey:@"35_31_19_18_35_31_19_18_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteControl_Switched] forKey:@"19_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteControl_Switched] forKey:@"39_"]; + } +} + +- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown { + if (pressedDown == NO && event == kRemoteButtonMenu_Hold) { + // There is no seperate event for pressed down on menu hold. We are simulating that event here + [super sendRemoteButtonEvent:event pressedDown:YES]; + } + + [super sendRemoteButtonEvent:event pressedDown:pressedDown]; + + if (pressedDown && (event == kRemoteButtonRight || event == kRemoteButtonLeft || event == kRemoteButtonPlay || event == kRemoteButtonMenu || event == kRemoteButtonPlay_Hold)) { + // There is no seperate event when the button is being released. We are simulating that event here + [super sendRemoteButtonEvent:event pressedDown:NO]; + } +} + +- (eCookieModifier) handleCookie: (long)f_cookie value:(int) f_value { + switch(f_cookie) + { + case 39: + deviceID = f_value; + return PASS_COOKIE; + default: + return [super handleCookie:f_cookie value:f_value]; + } +} + +- (int) deviceID { + return deviceID; +} +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/GlobalKeyboardDevice.h b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/GlobalKeyboardDevice.h new file mode 100644 index 0000000000..bcb11b4245 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/GlobalKeyboardDevice.h @@ -0,0 +1,49 @@ +/***************************************************************************** + * GlobalKeyboardDevice.h + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> +#import <Carbon/Carbon.h> + +#import "RemoteControl.h" + +/* + This class registers for a number of global keyboard shortcuts to simulate a remote control + */ +@interface GlobalKeyboardDevice : RemoteControl { + + NSMutableDictionary* hotKeyRemoteEventMapping; + EventHandlerRef eventHandlerRef; + +} + +- (void) mapRemoteButton: (RemoteControlEventIdentifier) remoteButtonIdentifier defaultKeycode: (unsigned int) defaultKeycode defaultModifiers: (unsigned int) defaultModifiers; + +- (BOOL)registerHotKeyCode: (unsigned int) keycode modifiers: (unsigned int) modifiers remoteEventIdentifier: (RemoteControlEventIdentifier) identifier; + +static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* refCon ); + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/GlobalKeyboardDevice.m b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/GlobalKeyboardDevice.m new file mode 100644 index 0000000000..f568d1f1a3 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/GlobalKeyboardDevice.m @@ -0,0 +1,241 @@ +/***************************************************************************** + * GlobalKeyboardDevice.m + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + + +#import "GlobalKeyboardDevice.h" + +#define F1 122 +#define F2 120 +#define F3 99 +#define F4 118 +#define F5 96 +#define F6 97 +#define F7 98 + +/* + the following default keys are read and shall be used to change the keyboard mapping + + mac.remotecontrols.GlobalKeyboardDevice.plus_modifiers + mac.remotecontrols.GlobalKeyboardDevice.plus_keycode + mac.remotecontrols.GlobalKeyboardDevice.minus_modifiers + mac.remotecontrols.GlobalKeyboardDevice.minus_keycode + mac.remotecontrols.GlobalKeyboardDevice.play_modifiers + mac.remotecontrols.GlobalKeyboardDevice.play_keycode + mac.remotecontrols.GlobalKeyboardDevice.left_modifiers + mac.remotecontrols.GlobalKeyboardDevice.left_keycode + mac.remotecontrols.GlobalKeyboardDevice.right_modifiers + mac.remotecontrols.GlobalKeyboardDevice.right_keycode + mac.remotecontrols.GlobalKeyboardDevice.menu_modifiers + mac.remotecontrols.GlobalKeyboardDevice.menu_keycode + mac.remotecontrols.GlobalKeyboardDevice.playhold_modifiers + mac.remotecontrols.GlobalKeyboardDevice.playhold_keycode + */ + + +@implementation GlobalKeyboardDevice + +- (id) initWithDelegate: (id) _remoteControlDelegate { + if (self = [super initWithDelegate: _remoteControlDelegate]) { + hotKeyRemoteEventMapping = [[NSMutableDictionary alloc] init]; + + unsigned int modifiers = cmdKey + shiftKey /*+ optionKey*/ + controlKey; + + [self mapRemoteButton:kRemoteButtonPlus defaultKeycode:F1 defaultModifiers:modifiers]; + [self mapRemoteButton:kRemoteButtonMinus defaultKeycode:F2 defaultModifiers:modifiers]; + [self mapRemoteButton:kRemoteButtonPlay defaultKeycode:F3 defaultModifiers:modifiers]; + [self mapRemoteButton:kRemoteButtonLeft defaultKeycode:F4 defaultModifiers:modifiers]; + [self mapRemoteButton:kRemoteButtonRight defaultKeycode:F5 defaultModifiers:modifiers]; + [self mapRemoteButton:kRemoteButtonMenu defaultKeycode:F6 defaultModifiers:modifiers]; + [self mapRemoteButton:kRemoteButtonPlay_Hold defaultKeycode:F7 defaultModifiers:modifiers]; + } + return self; +} + +- (void) dealloc { + [hotKeyRemoteEventMapping release]; + [super dealloc]; +} + +- (void) mapRemoteButton: (RemoteControlEventIdentifier) remoteButtonIdentifier defaultKeycode: (unsigned int) defaultKeycode defaultModifiers: (unsigned int) defaultModifiers { + NSString* defaultsKey; + + switch(remoteButtonIdentifier) { + case kRemoteButtonPlus: + defaultsKey = @"plus"; + break; + case kRemoteButtonMinus: + defaultsKey = @"minus"; + break; + case kRemoteButtonMenu: + defaultsKey = @"menu"; + break; + case kRemoteButtonPlay: + defaultsKey = @"play"; + break; + case kRemoteButtonRight: + defaultsKey = @"right"; + break; + case kRemoteButtonLeft: + defaultsKey = @"left"; + break; + case kRemoteButtonPlay_Hold: + defaultsKey = @"playhold"; + break; + default: + NSLog(@"Unknown global keyboard defaults key for remote button identifier %d", remoteButtonIdentifier); + } + + NSNumber* modifiersCfg = [[NSUserDefaults standardUserDefaults] objectForKey: [NSString stringWithFormat: @"mac.remotecontrols.GlobalKeyboardDevice.%@_modifiers", defaultsKey]]; + NSNumber* keycodeCfg = [[NSUserDefaults standardUserDefaults] objectForKey: [NSString stringWithFormat: @"mac.remotecontrols.GlobalKeyboardDevice.%@_keycode", defaultsKey]]; + + unsigned int modifiers = defaultModifiers; + if (modifiersCfg) modifiers = [modifiersCfg unsignedIntValue]; + + unsigned int keycode = defaultKeycode; + if (keycodeCfg) keycode = [keycodeCfg unsignedIntValue]; + + [self registerHotKeyCode: keycode modifiers: modifiers remoteEventIdentifier: remoteButtonIdentifier]; +} + +- (void) setListeningToRemote: (BOOL) value { + if (value == [self isListeningToRemote]) return; + if (value) { + [self startListening: self]; + } else { + [self stopListening: self]; + } +} +- (BOOL) isListeningToRemote { + return (eventHandlerRef!=NULL); +} + +- (IBAction) startListening: (id) sender { + + if (eventHandlerRef) return; + + EventTypeSpec eventSpec[2] = { + { kEventClassKeyboard, kEventHotKeyPressed }, + { kEventClassKeyboard, kEventHotKeyReleased } + }; + + InstallEventHandler( GetEventDispatcherTarget(), + (EventHandlerProcPtr)hotKeyEventHandler, + 2, eventSpec, self, &eventHandlerRef); +} +- (IBAction) stopListening: (id) sender { + RemoveEventHandler(eventHandlerRef); + eventHandlerRef = NULL; +} + +- (BOOL) sendsEventForButtonIdentifier: (RemoteControlEventIdentifier) identifier { + NSEnumerator* values = [hotKeyRemoteEventMapping objectEnumerator]; + NSNumber* remoteIdentifier; + while( (remoteIdentifier = [values nextObject]) ) { + if ([remoteIdentifier unsignedIntValue] == identifier) return YES; + } + return NO; +} + ++ (const char*) remoteControlDeviceName { + return "Keyboard"; +} + +- (BOOL)registerHotKeyCode: (unsigned int) keycode modifiers: (unsigned int) modifiers remoteEventIdentifier: (RemoteControlEventIdentifier) identifier { + OSStatus err; + EventHotKeyID hotKeyID; + EventHotKeyRef carbonHotKey; + + hotKeyID.signature = 'PTHk'; + hotKeyID.id = (long)keycode; + + err = RegisterEventHotKey(keycode, modifiers, hotKeyID, GetEventDispatcherTarget(), (int)nil, &carbonHotKey ); + + if( err ) + return NO; + + [hotKeyRemoteEventMapping setObject: [NSNumber numberWithInt:identifier] forKey: [NSNumber numberWithUnsignedInt: hotKeyID.id]]; + + return YES; +} +/* + - (void)unregisterHotKey: (PTHotKey*)hotKey + { + OSStatus err; + EventHotKeyRef carbonHotKey; + NSValue* key; + + if( [[self allHotKeys] containsObject: hotKey] == NO ) + return; + + carbonHotKey = [self _carbonHotKeyForHotKey: hotKey]; + NSAssert( carbonHotKey != nil, @"" ); + + err = UnregisterEventHotKey( carbonHotKey ); + //Watch as we ignore 'err': + + key = [NSValue valueWithPointer: carbonHotKey]; + [mHotKeys removeObjectForKey: key]; + + [self _updateEventHandler]; + + //See that? Completely ignored + } + */ + +- (RemoteControlEventIdentifier) remoteControlEventIdentifierForID: (unsigned int) id { + NSNumber* remoteEventIdentifier = [hotKeyRemoteEventMapping objectForKey:[NSNumber numberWithUnsignedInt: id]]; + return [remoteEventIdentifier unsignedIntValue]; +} + +- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown { + [delegate sendRemoteButtonEvent: event pressedDown: pressedDown remoteControl:self]; +} + +static RemoteControlEventIdentifier lastEvent; + +static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* userData ) +{ + GlobalKeyboardDevice* keyboardDevice = (GlobalKeyboardDevice*) userData; + EventHotKeyID hkCom; + GetEventParameter(inEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,sizeof(hkCom),NULL,&hkCom); + + RemoteControlEventIdentifier identifier = [keyboardDevice remoteControlEventIdentifierForID:hkCom.id]; + if (identifier == 0) return noErr; + + BOOL pressedDown = YES; + if (identifier != lastEvent) { + lastEvent = identifier; + } else { + lastEvent = 0; + pressedDown = NO; + } + [keyboardDevice sendRemoteButtonEvent: identifier pressedDown: pressedDown]; + + return noErr; +} + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/HIDRemoteControlDevice.h b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/HIDRemoteControlDevice.h new file mode 100644 index 0000000000..1bd3dff60a --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/HIDRemoteControlDevice.h @@ -0,0 +1,77 @@ +/***************************************************************************** + * HIDRemoteControlDevice.h + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> +#import <Carbon/Carbon.h> +#import <IOKit/hid/IOHIDLib.h> + +#import "RemoteControl.h" + +typedef enum _eCookieModifier{ + DISCARD_COOKIE = 0, + PASS_COOKIE +} eCookieModifier; + +/* + Base class for HID based remote control devices + */ +@interface HIDRemoteControlDevice : RemoteControl { + IOHIDDeviceInterface** hidDeviceInterface; + IOHIDQueueInterface** queue; + NSMutableArray* allCookies; + NSMutableDictionary* cookieToButtonMapping; + CFRunLoopSourceRef eventSource; + + BOOL fixSecureEventInputBug; + BOOL openInExclusiveMode; + BOOL processesBacklog; + + int supportedButtonEvents; + + EventHandlerUPP appSwitchedHandlerUPP; + EventHandlerRef appSwitchedHandlerRef; +} + +// When your application needs to much time on the main thread when processing an event other events +// may already be received which are put on a backlog. As soon as your main thread +// has some spare time this backlog is processed and may flood your delegate with calls. +// Backlog processing is turned off by default. +- (BOOL) processesBacklog; +- (void) setProcessesBacklog: (BOOL) value; + +// methods that should be overwritten by subclasses +- (void) setCookieMappingInDictionary: (NSMutableDictionary*) cookieToButtonMapping; + +- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown; + +//overwrite this to be able to interact with cookie handling +//by default (f_cookie == 5) is discarded +- (eCookieModifier) handleCookie: (long)f_cookie value:(int) f_value; + ++ (BOOL) isRemoteAvailable; + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/HIDRemoteControlDevice.m b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/HIDRemoteControlDevice.m new file mode 100644 index 0000000000..5fa61c46b5 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/HIDRemoteControlDevice.m @@ -0,0 +1,547 @@ +/***************************************************************************** + * HIDRemoteControlDevice.m + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import "HIDRemoteControlDevice.h" + +#import <mach/mach.h> +#import <mach/mach_error.h> +#import <IOKit/IOKitLib.h> +#import <IOKit/IOCFPlugIn.h> +#import <IOKit/hid/IOHIDKeys.h> +#import "XBMCDebugHelpers.h" + +@interface HIDRemoteControlDevice (PrivateMethods) +- (NSDictionary*) cookieToButtonMapping; +- (IOHIDQueueInterface**) queue; +- (IOHIDDeviceInterface**) hidDeviceInterface; +- (void) removeNotifcationObserver; +- (void) remoteControlAvailable:(NSNotification *)notification; +- (void) enableSecureInputFix; +- (void) disableSecureInputFix; +@end + +@interface HIDRemoteControlDevice (IOKitMethods) ++ (io_object_t) findRemoteDevice; +- (IOHIDDeviceInterface**) createInterfaceForDevice: (io_object_t) hidDevice; +- (BOOL) initializeCookies; +- (BOOL) openDevice; +@end + +//handler to regrab device if openend in exclusive mode on app-switches +//installed in startListening and removed in stopListening +pascal OSStatus appSwitchedEventHandler(EventHandlerCallRef nextHandler, + EventRef switchEvent, + void* userData); + +@implementation HIDRemoteControlDevice + ++ (const char*) remoteControlDeviceName { + return ""; +} + ++ (BOOL) isRemoteAvailable { + io_object_t hidDevice = [self findRemoteDevice]; + if (hidDevice != 0) { + IOObjectRelease(hidDevice); + return YES; + } else { + return NO; + } +} + +- (id) initWithDelegate: (id) _remoteControlDelegate { + if ([[self class] isRemoteAvailable] == NO) return nil; + + if ( self = [super initWithDelegate: _remoteControlDelegate] ) { + openInExclusiveMode = YES; + queue = NULL; + hidDeviceInterface = NULL; + cookieToButtonMapping = [[NSMutableDictionary alloc] init]; + + [self setCookieMappingInDictionary: cookieToButtonMapping]; + + NSEnumerator* enumerator = [cookieToButtonMapping objectEnumerator]; + NSNumber* identifier; + supportedButtonEvents = 0; + while(identifier = [enumerator nextObject]) { + supportedButtonEvents |= [identifier intValue]; + } + + fixSecureEventInputBug = [[NSUserDefaults standardUserDefaults] boolForKey: @"remoteControlWrapperFixSecureEventInputBug"]; + appSwitchedHandlerUPP = NewEventHandlerUPP(appSwitchedEventHandler); + } + + return self; +} + +- (void) dealloc { + [self removeNotifcationObserver]; + [self stopListening:self]; + [cookieToButtonMapping release]; + [super dealloc]; +} + +- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown { + [delegate sendRemoteButtonEvent: event pressedDown: pressedDown remoteControl:self]; +} + +- (void) setCookieMappingInDictionary: (NSMutableDictionary*) cookieToButtonMapping { +} +- (int) remoteIdSwitchCookie { + return 0; +} + +- (BOOL) sendsEventForButtonIdentifier: (RemoteControlEventIdentifier) identifier { + return (supportedButtonEvents & identifier) == identifier; +} + +- (BOOL) isListeningToRemote { + return (hidDeviceInterface != NULL && allCookies != NULL && queue != NULL); +} + +- (void) setListeningToRemote: (BOOL) value { + if (value == NO) { + [self stopListening:self]; + } else { + [self startListening:self]; + } +} + +- (BOOL) isOpenInExclusiveMode { + return openInExclusiveMode; +} +- (void) setOpenInExclusiveMode: (BOOL) value { + openInExclusiveMode = value; +} + +- (BOOL) processesBacklog { + return processesBacklog; +} +- (void) setProcessesBacklog: (BOOL) value { + processesBacklog = value; +} + +//handler to regrab device if openend in exclusive mode on app-switches +//installed in startListening and removed in stopListening +pascal OSStatus appSwitchedEventHandler(EventHandlerCallRef nextHandler, + EventRef switchEvent, + void* userData) +{ + HIDRemoteControlDevice* p_this = (HIDRemoteControlDevice*)userData; + if (p_this->hidDeviceInterface) + { + if ((*(p_this->hidDeviceInterface))->close(p_this->hidDeviceInterface) != KERN_SUCCESS) + ELOG("failed closing Apple Remote device\n"); + + if ((*(p_this->hidDeviceInterface))->open(p_this->hidDeviceInterface, kIOHIDOptionsTypeSeizeDevice) != KERN_SUCCESS) + ELOG("failed opening Apple Remote device\n"); + } + //DLOG("Reopened Apple Remote in exclusive mode\n"); + return 0; +} + +- (IBAction) startListening: (id) sender { + if ([self isListeningToRemote]) return; + + // 4th July 2007 + // + // A security update in february of 2007 introduced an odd behavior. + // Whenever SecureEventInput is activated or deactivated the exclusive access + // to the remote control device is lost. This leads to very strange behavior where + // a press on the Menu button activates FrontRow while your app still gets the event. + // A great number of people have complained about this. + // + // Enabling the SecureEventInput and keeping it enabled does the trick. + // + // I'm pretty sure this is a kind of bug at Apple and I'm in contact with the responsible + // Apple Engineer. This solution is not a perfect one - I know. + // One of the side effects is that applications that listen for special global keyboard shortcuts (like Quicksilver) + // may get into problems as they no longer get the events. + // As there is no official Apple Remote API from Apple I also failed to open a technical incident on this. + // + // Note that there is a corresponding DisableSecureEventInput in the stopListening method below. + // + [self enableSecureInputFix]; + + [self removeNotifcationObserver]; + + io_object_t hidDevice = [[self class] findRemoteDevice]; + if (hidDevice == 0) return; + + if ([self createInterfaceForDevice:hidDevice] == NULL) { + goto error; + } + + if ([self initializeCookies]==NO) { + goto error; + } + + if ([self openDevice]==NO) { + goto error; + } + // be KVO friendly + [self willChangeValueForKey:@"listeningToRemote"]; + [self didChangeValueForKey:@"listeningToRemote"]; + goto cleanup; + +error: + [self stopListening:self]; + [self disableSecureInputFix]; + +cleanup: + IOObjectRelease(hidDevice); +} + +- (IBAction) stopListening: (id) sender { + if ([self isListeningToRemote]==NO) return; + + BOOL sendNotification = NO; + + if (eventSource != NULL) { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopDefaultMode); + CFRelease(eventSource); + eventSource = NULL; + } + if (queue != NULL) { + (*queue)->stop(queue); + + //dispose of queue + (*queue)->dispose(queue); + + //release the queue we allocated + (*queue)->Release(queue); + + queue = NULL; + + sendNotification = YES; + } + + if (allCookies != nil) { + [allCookies autorelease]; + allCookies = nil; + } + + if (hidDeviceInterface != NULL) { + //close the device + (*hidDeviceInterface)->close(hidDeviceInterface); + + //release the interface + (*hidDeviceInterface)->Release(hidDeviceInterface); + + hidDeviceInterface = NULL; + } + [self disableSecureInputFix]; + + if ([self isOpenInExclusiveMode] && sendNotification) { + [[self class] sendFinishedNotifcationForAppIdentifier: nil]; + } + // be KVO friendly + [self willChangeValueForKey:@"listeningToRemote"]; + [self didChangeValueForKey:@"listeningToRemote"]; +} + +- (eCookieModifier) handleCookie: (long)f_cookie value:(int) f_value { + if(f_cookie == 5) + return DISCARD_COOKIE; + else + return PASS_COOKIE; +} + +@end + +@implementation HIDRemoteControlDevice (PrivateMethods) + +- (IOHIDQueueInterface**) queue { + return queue; +} + +- (IOHIDDeviceInterface**) hidDeviceInterface { + return hidDeviceInterface; +} + + +- (NSDictionary*) cookieToButtonMapping { + return cookieToButtonMapping; +} + +- (void) removeNotifcationObserver { + [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:FINISHED_USING_REMOTE_CONTROL_NOTIFICATION object:nil]; +} + +- (void) remoteControlAvailable:(NSNotification *)notification { + [self removeNotifcationObserver]; + [self startListening: self]; +} + +- (void) enableSecureInputFix { + if ([self isOpenInExclusiveMode]) { + //2 ways to fix exclusive mode, either the one mentioned above + if (fixSecureEventInputBug) + EnableSecureEventInput(); + else { + //or registering for all app-switch events and just reopening the device on each switch + const EventTypeSpec applicationEvents[] = { { kEventClassApplication, kEventAppFrontSwitched } }; + InstallApplicationEventHandler(appSwitchedHandlerUPP, + GetEventTypeCount(applicationEvents), applicationEvents, self, &appSwitchedHandlerRef); + } + } +} + +- (void) disableSecureInputFix{ + if ([self isOpenInExclusiveMode]){ + if(fixSecureEventInputBug) + DisableSecureEventInput(); + else{ + RemoveEventHandler(appSwitchedHandlerRef); + } + } +} + +@end + +/* Callback method for the device queue + Will be called for any event of any type (cookie) to which we subscribe + */ +static void QueueCallbackFunction(void* target, IOReturn result, void* refcon, void* sender) { + if (target < 0) { + NSLog(@"QueueCallbackFunction called with invalid target!"); + return; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + HIDRemoteControlDevice* remote = (HIDRemoteControlDevice*)target; + IOHIDEventStruct event; + AbsoluteTime zeroTime = {0,0}; + NSMutableString* cookieString = [NSMutableString stringWithCapacity: 10]; + SInt32 sumOfValues = 0; + NSNumber* lastSubButtonId = nil; + while (result == kIOReturnSuccess) + { + result = (*[remote queue])->getNextEvent([remote queue], &event, zeroTime, 0); + if ( result != kIOReturnSuccess ) + continue; + + //printf("%d %d %d\n", event.elementCookie, event.value, event.longValue); + if([remote handleCookie:(long)event.elementCookie value:event.value] != DISCARD_COOKIE){ + sumOfValues+=event.value; + [cookieString appendString:[NSString stringWithFormat:@"%d_", event.elementCookie]]; + } + //check if this is a valid button + NSNumber* buttonId = [[remote cookieToButtonMapping] objectForKey: cookieString]; + if (buttonId != nil){ + if([remote processesBacklog]) { + //send the button + [remote sendRemoteButtonEvent: [buttonId intValue] pressedDown: (sumOfValues>0)]; + //reset + } else { + //store button for later use + lastSubButtonId = buttonId; + } + sumOfValues = 0; + cookieString = [NSMutableString stringWithCapacity: 10]; + } + } + if ([remote processesBacklog] == NO && lastSubButtonId != nil) { + // process the last event of the backlog and assume that the button is not pressed down any longer. + // The events in the backlog do not seem to be in order and therefore (in rare cases) the last event might be + // a button pressed down event while in reality the user has released it. + // NSLog(@"processing last event of backlog"); + [remote sendRemoteButtonEvent: [lastSubButtonId intValue] pressedDown: (sumOfValues>0)]; + } + if ([cookieString length] > 0) { + NSLog(@"Unknown button for cookiestring %@", cookieString); + } + [pool release]; +} + +@implementation HIDRemoteControlDevice (IOKitMethods) + +- (IOHIDDeviceInterface**) createInterfaceForDevice: (io_object_t) hidDevice { + io_name_t className; + IOCFPlugInInterface** plugInInterface = NULL; + HRESULT plugInResult = S_OK; + SInt32 score = 0; + IOReturn ioReturnValue = kIOReturnSuccess; + + hidDeviceInterface = NULL; + + ioReturnValue = IOObjectGetClass(hidDevice, className); + + if (ioReturnValue != kIOReturnSuccess) { + NSLog(@"Error: Failed to get class name."); + return NULL; + } + + ioReturnValue = IOCreatePlugInInterfaceForService(hidDevice, + kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &plugInInterface, + &score); + if (ioReturnValue == kIOReturnSuccess) + { + //Call a method of the intermediate plug-in to create the device interface + plugInResult = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID) &hidDeviceInterface); + + if (plugInResult != S_OK) { + NSLog(@"Error: Couldn't create HID class device interface"); + } + // Release + if (plugInInterface) (*plugInInterface)->Release(plugInInterface); + } + return hidDeviceInterface; +} + +- (BOOL) initializeCookies { + IOHIDDeviceInterface122** handle = (IOHIDDeviceInterface122**)hidDeviceInterface; + IOHIDElementCookie cookie; + long usage; + long usagePage; + id object; + NSArray* elements = nil; + NSDictionary* element; + IOReturn success; + + if (!handle || !(*handle)) return NO; + + // Copy all elements, since we're grabbing most of the elements + // for this device anyway, and thus, it's faster to iterate them + // ourselves. When grabbing only one or two elements, a matching + // dictionary should be passed in here instead of NULL. + success = (*handle)->copyMatchingElements(handle, NULL, (CFArrayRef*)&elements); + + if (success == kIOReturnSuccess) { + + [elements autorelease]; + /* + cookies = calloc(NUMBER_OF_APPLE_REMOTE_ACTIONS, sizeof(IOHIDElementCookie)); + memset(cookies, 0, sizeof(IOHIDElementCookie) * NUMBER_OF_APPLE_REMOTE_ACTIONS); + */ + allCookies = [[NSMutableArray alloc] init]; + + NSEnumerator *elementsEnumerator = [elements objectEnumerator]; + + while (element = [elementsEnumerator nextObject]) { + //Get cookie + object = [element valueForKey: (NSString*)CFSTR(kIOHIDElementCookieKey) ]; + if (object == nil || ![object isKindOfClass:[NSNumber class]]) continue; + if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) continue; + cookie = (IOHIDElementCookie) [object longValue]; + + //Get usage + object = [element valueForKey: (NSString*)CFSTR(kIOHIDElementUsageKey) ]; + if (object == nil || ![object isKindOfClass:[NSNumber class]]) continue; + usage = [object longValue]; + + //Get usage page + object = [element valueForKey: (NSString*)CFSTR(kIOHIDElementUsagePageKey) ]; + if (object == nil || ![object isKindOfClass:[NSNumber class]]) continue; + usagePage = [object longValue]; + + [allCookies addObject: [NSNumber numberWithInt:(int)cookie]]; + } + } else { + return NO; + } + + return YES; +} + +- (BOOL) openDevice { + HRESULT result; + + IOHIDOptionsType openMode = kIOHIDOptionsTypeNone; + if ([self isOpenInExclusiveMode]) openMode = kIOHIDOptionsTypeSeizeDevice; + IOReturn ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, openMode); + + if (ioReturnValue == KERN_SUCCESS) { + queue = (*hidDeviceInterface)->allocQueue(hidDeviceInterface); + if (queue) { + result = (*queue)->create(queue, 0, 12); //depth: maximum number of elements in queue before oldest elements in queue begin to be lost. + + IOHIDElementCookie cookie; + NSEnumerator *allCookiesEnumerator = [allCookies objectEnumerator]; + + while (cookie = (IOHIDElementCookie)[[allCookiesEnumerator nextObject] intValue]) { + (*queue)->addElement(queue, cookie, 0); + } + + // add callback for async events + ioReturnValue = (*queue)->createAsyncEventSource(queue, &eventSource); + if (ioReturnValue == KERN_SUCCESS) { + ioReturnValue = (*queue)->setEventCallout(queue,QueueCallbackFunction, self, NULL); + if (ioReturnValue == KERN_SUCCESS) { + CFRunLoopAddSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopDefaultMode); + + //start data delivery to queue + (*queue)->start(queue); + return YES; + } else { + NSLog(@"Error when setting event callback"); + } + } else { + NSLog(@"Error when creating async event source"); + } + } else { + NSLog(@"Error when opening device"); + } + } else if (ioReturnValue == kIOReturnExclusiveAccess) { + // the device is used exclusive by another application + + // 1. we register for the FINISHED_USING_REMOTE_CONTROL_NOTIFICATION notification + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(remoteControlAvailable:) name:FINISHED_USING_REMOTE_CONTROL_NOTIFICATION object:nil]; + + // 2. send a distributed notification that we wanted to use the remote control + [[self class] sendRequestForRemoteControlNotification]; + } + return NO; +} + ++ (io_object_t) findRemoteDevice { + CFMutableDictionaryRef hidMatchDictionary = NULL; + IOReturn ioReturnValue = kIOReturnSuccess; + io_iterator_t hidObjectIterator = 0; + io_object_t hidDevice = 0; + + // Set up a matching dictionary to search the I/O Registry by class + // name for all HID class devices + hidMatchDictionary = IOServiceMatching([self remoteControlDeviceName]); + + // Now search I/O Registry for matching devices. + ioReturnValue = IOServiceGetMatchingServices(kIOMasterPortDefault, hidMatchDictionary, &hidObjectIterator); + + if ((ioReturnValue == kIOReturnSuccess) && (hidObjectIterator != 0)) { + hidDevice = IOIteratorNext(hidObjectIterator); + } + + // release the iterator + IOObjectRelease(hidObjectIterator); + + return hidDevice; +} + +@end + diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/IRKeyboardEmu.h b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/IRKeyboardEmu.h new file mode 100644 index 0000000000..8a842da8f3 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/IRKeyboardEmu.h @@ -0,0 +1,16 @@ +// +// IRKeyboardEmu.h +// XBMCHelper +// +// Created by Stephan Diederich on 14.04.09. +// Copyright 2009 __MyCompanyName__. All rights reserved. +// + +#import <Cocoa/Cocoa.h> +#import "AppleRemote.h" + +@interface IRKeyboardEmu : AppleRemote { + +} + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/IRKeyboardEmu.m b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/IRKeyboardEmu.m new file mode 100644 index 0000000000..5350e16c0c --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/IRKeyboardEmu.m @@ -0,0 +1,26 @@ +// +// IRKeyboardEmu.m +// XBMCHelper +// +// Created by Stephan Diederich on 14.04.09. +// Copyright 2009 __MyCompanyName__. All rights reserved. +// + +#import "IRKeyboardEmu.h" + + +@implementation IRKeyboardEmu + ++ (const char*) remoteControlDeviceName { + return "IRKeyboardEmu"; +} + +- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown { + if (pressedDown == NO && event == kRemoteButtonMenu_Hold) { + // There is no seperate event for pressed down on menu hold. We are simulating that event here + [super sendRemoteButtonEvent:event pressedDown:YES]; + } + + [super sendRemoteButtonEvent:event pressedDown:pressedDown]; +} +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/KeyspanFrontRowControl.h b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/KeyspanFrontRowControl.h new file mode 100644 index 0000000000..3a8224154f --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/KeyspanFrontRowControl.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * KeyspanFrontRowControl.h + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + + +#import <Cocoa/Cocoa.h> +#import "HIDRemoteControlDevice.h" + +/* Interacts with the Keyspan FrontRow Remote Control HID device + The class is not thread safe + */ +@interface KeyspanFrontRowControl : HIDRemoteControlDevice { + +} + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/KeyspanFrontRowControl.m b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/KeyspanFrontRowControl.m new file mode 100644 index 0000000000..7dbcc853ec --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/KeyspanFrontRowControl.m @@ -0,0 +1,87 @@ +/***************************************************************************** + * KeyspanFrontRowControl.m + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import "KeyspanFrontRowControl.h" +#import <mach/mach.h> +#import <mach/mach_error.h> +#import <IOKit/IOKitLib.h> +#import <IOKit/IOCFPlugIn.h> +#import <IOKit/hid/IOHIDKeys.h> + +@implementation KeyspanFrontRowControl + +- (void) setCookieMappingInDictionary: (NSMutableDictionary*) _cookieToButtonMapping { + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlus] forKey:@"11_18_99_10_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMinus] forKey:@"11_18_98_10_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu] forKey:@"11_18_58_10_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay] forKey:@"11_18_61_10_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight] forKey:@"11_18_96_10_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft] forKey:@"11_18_97_10_"]; + /* hold events are not being send by this device + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight_Hold] forKey:@"14_6_4_2_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft_Hold] forKey:@"14_6_3_2_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu_Hold] forKey:@"14_6_14_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay_Sleep] forKey:@"18_14_6_18_14_6_"]; + [_cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteControl_Switched] forKey:@"19_"]; + */ +} + ++ (io_object_t) findRemoteDevice { + CFMutableDictionaryRef hidMatchDictionary = NULL; + IOReturn ioReturnValue = kIOReturnSuccess; + io_iterator_t hidObjectIterator = 0; + io_object_t hidDevice = 0; + SInt32 idVendor = 1741; + SInt32 idProduct = 0x420; + + // Set up a matching dictionary to search the I/O Registry by class + // name for all HID class devices + hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); + + CFNumberRef numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &idVendor); + CFDictionaryAddValue(hidMatchDictionary, CFSTR(kIOHIDVendorIDKey), numberRef); + CFRelease(numberRef); + + numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &idProduct); + CFDictionaryAddValue(hidMatchDictionary, CFSTR(kIOHIDProductIDKey), numberRef); + CFRelease(numberRef); + + // Now search I/O Registry for matching devices. + ioReturnValue = IOServiceGetMatchingServices(kIOMasterPortDefault, hidMatchDictionary, &hidObjectIterator); + + if ((ioReturnValue == kIOReturnSuccess) && (hidObjectIterator != 0)) { + hidDevice = IOIteratorNext(hidObjectIterator); + } + + // release the iterator + IOObjectRelease(hidObjectIterator); + + return hidDevice; + +} + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/MultiClickRemoteBehavior.h b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/MultiClickRemoteBehavior.h new file mode 100644 index 0000000000..8b288604f7 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/MultiClickRemoteBehavior.h @@ -0,0 +1,90 @@ +/***************************************************************************** + * MultiClickRemoteBehavior.h + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + + +#import <Cocoa/Cocoa.h> +#import "RemoteControl.h" + +/** + A behavior that adds multiclick and hold events on top of a device. + Events are generated and send to a delegate + */ +@interface MultiClickRemoteBehavior : NSObject { + id delegate; + + // state for simulating plus/minus hold + BOOL simulateHoldEvents; + BOOL lastEventSimulatedHold; + RemoteControlEventIdentifier lastHoldEvent; + NSTimeInterval lastHoldEventTime; + + // state for multi click + unsigned int clickCountEnabledButtons; + NSTimeInterval maxClickTimeDifference; + NSTimeInterval lastClickCountEventTime; + RemoteControlEventIdentifier lastClickCountEvent; + unsigned int eventClickCount; +} + +- (id) init; + +// Delegates are not retained +- (void) setDelegate: (id) delegate; +- (id) delegate; + +// Simulating hold events does deactivate sending of individual requests for pressed down/released. +// Instead special hold events are being triggered when the user is pressing and holding a button for a small period. +// Simulation is activated only for those buttons and remote control that do not have a seperate event already +- (BOOL) simulateHoldEvent; +- (void) setSimulateHoldEvent: (BOOL) value; + +// click counting makes it possible to recognize if the user has pressed a button repeatedly +// click counting does delay each event as it has to wait if there is another event (second click) +// therefore there is a slight time difference (maximumClickCountTimeDifference) between a single click +// of the user and the call of your delegate method +// click counting can be enabled individually for specific buttons. Use the property clickCountEnableButtons to +// set the buttons for which click counting shall be enabled +- (BOOL) clickCountingEnabled; +- (void) setClickCountingEnabled: (BOOL) value; + +- (unsigned int) clickCountEnabledButtons; +- (void) setClickCountEnabledButtons: (unsigned int)value; + +// the maximum time difference till which clicks are recognized as multi clicks +- (NSTimeInterval) maximumClickCountTimeDifference; +- (void) setMaximumClickCountTimeDifference: (NSTimeInterval) timeDiff; + +@end + +/* + * Method definitions for the delegate of the MultiClickRemoteBehavior class + */ +@interface NSObject(MultiClickRemoteBehaviorDelegate) + +- (void) remoteButton: (RemoteControlEventIdentifier)buttonIdentifier pressedDown: (BOOL) pressedDown clickCount: (unsigned int) count; + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/MultiClickRemoteBehavior.m b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/MultiClickRemoteBehavior.m new file mode 100644 index 0000000000..4b40fb3df8 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/MultiClickRemoteBehavior.m @@ -0,0 +1,210 @@ +/***************************************************************************** + * MultiClickRemoteBehavior.m + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import "MultiClickRemoteBehavior.h" + +const NSTimeInterval DEFAULT_MAXIMUM_CLICK_TIME_DIFFERENCE=0.35; +const NSTimeInterval HOLD_RECOGNITION_TIME_INTERVAL=0.4; + +@implementation MultiClickRemoteBehavior + +- (id) init { + if (self = [super init]) { + maxClickTimeDifference = DEFAULT_MAXIMUM_CLICK_TIME_DIFFERENCE; + } + return self; +} + +// Delegates are not retained! +// http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/chapter_6_section_4.html +// Delegating objects do not (and should not) retain their delegates. +// However, clients of delegating objects (applications, usually) are responsible for ensuring that their delegates are around +// to receive delegation messages. To do this, they may have to retain the delegate. +- (void) setDelegate: (id) _delegate { + if (_delegate && [_delegate respondsToSelector:@selector(remoteButton:pressedDown:clickCount:)]==NO) return; + + delegate = _delegate; +} +- (id) delegate { + return delegate; +} + +- (BOOL) simulateHoldEvent { + return simulateHoldEvents; +} +- (void) setSimulateHoldEvent: (BOOL) value { + simulateHoldEvents = value; +} + +- (BOOL) simulatesHoldForButtonIdentifier: (RemoteControlEventIdentifier) identifier remoteControl: (RemoteControl*) remoteControl { + // we do that check only for the normal button identifiers as we would check for hold support for hold events instead + if (identifier > (1 << EVENT_TO_HOLD_EVENT_OFFSET)) return NO; + + return [self simulateHoldEvent] && [remoteControl sendsEventForButtonIdentifier: (identifier << EVENT_TO_HOLD_EVENT_OFFSET)]==NO; +} + +- (BOOL) clickCountingEnabled { + return clickCountEnabledButtons != 0; +} +- (void) setClickCountingEnabled: (BOOL) value { + if (value) { + [self setClickCountEnabledButtons: kRemoteButtonPlus | kRemoteButtonMinus | kRemoteButtonPlay | kRemoteButtonLeft | kRemoteButtonRight | kRemoteButtonMenu]; + } else { + [self setClickCountEnabledButtons: 0]; + } +} + +- (unsigned int) clickCountEnabledButtons { + return clickCountEnabledButtons; +} +- (void) setClickCountEnabledButtons: (unsigned int)value { + clickCountEnabledButtons = value; +} + +- (NSTimeInterval) maximumClickCountTimeDifference { + return maxClickTimeDifference; +} +- (void) setMaximumClickCountTimeDifference: (NSTimeInterval) timeDiff { + maxClickTimeDifference = timeDiff; +} + +- (void) sendSimulatedHoldEvent: (id) time { + BOOL startSimulateHold = NO; + RemoteControlEventIdentifier event = lastHoldEvent; + @synchronized(self) { + startSimulateHold = (lastHoldEvent>0 && lastHoldEventTime == [time doubleValue]); + } + if (startSimulateHold) { + lastEventSimulatedHold = YES; + event = (event << EVENT_TO_HOLD_EVENT_OFFSET); + [delegate remoteButton:event pressedDown: YES clickCount: 1]; + } +} + +- (void) executeClickCountEvent: (NSArray*) values { + RemoteControlEventIdentifier event = [[values objectAtIndex: 0] unsignedIntValue]; + NSTimeInterval eventTimePoint = [[values objectAtIndex: 1] doubleValue]; + + BOOL finishedClicking = NO; + int finalClickCount = eventClickCount; + + @synchronized(self) { + finishedClicking = (event != lastClickCountEvent || eventTimePoint == lastClickCountEventTime); + if (finishedClicking) { + eventClickCount = 0; + lastClickCountEvent = 0; + lastClickCountEventTime = 0; + } + } + + if (finishedClicking) { + [delegate remoteButton:event pressedDown: YES clickCount:finalClickCount]; + // trigger a button release event, too + [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow:0.1]]; + [delegate remoteButton:event pressedDown: NO clickCount:finalClickCount]; + } +} + +- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown remoteControl: (RemoteControl*) remoteControl { + if (!delegate) return; + + BOOL clickCountingForEvent = ([self clickCountEnabledButtons] & event) == event; + + if ([self simulatesHoldForButtonIdentifier: event remoteControl: remoteControl] && lastClickCountEvent==0) { + if (pressedDown) { + // wait to see if it is a hold + lastHoldEvent = event; + lastHoldEventTime = [NSDate timeIntervalSinceReferenceDate]; + [self performSelector:@selector(sendSimulatedHoldEvent:) + withObject:[NSNumber numberWithDouble:lastHoldEventTime] + afterDelay:HOLD_RECOGNITION_TIME_INTERVAL]; + return; + } else { + if (lastEventSimulatedHold) { + // it was a hold + // send an event for "hold release" + event = (event << EVENT_TO_HOLD_EVENT_OFFSET); + lastHoldEvent = 0; + lastEventSimulatedHold = NO; + + [delegate remoteButton:event pressedDown: pressedDown clickCount:1]; + return; + } else { + RemoteControlEventIdentifier previousEvent = lastHoldEvent; + @synchronized(self) { + lastHoldEvent = 0; + } + + // in case click counting is enabled we have to setup the state for that, too + if (clickCountingForEvent) { + lastClickCountEvent = previousEvent; + lastClickCountEventTime = lastHoldEventTime; + NSNumber* eventNumber; + NSNumber* timeNumber; + eventClickCount = 1; + timeNumber = [NSNumber numberWithDouble:lastClickCountEventTime]; + eventNumber= [NSNumber numberWithUnsignedInt:previousEvent]; + NSTimeInterval diffTime = maxClickTimeDifference-([NSDate timeIntervalSinceReferenceDate]-lastHoldEventTime); + [self performSelector: @selector(executeClickCountEvent:) + withObject: [NSArray arrayWithObjects:eventNumber, timeNumber, nil] + afterDelay: diffTime]; + // we do not return here because we are still in the press-release event + // that will be consumed below + } else { + // trigger the pressed down event that we consumed first + [delegate remoteButton:event pressedDown: YES clickCount:1]; + } + } + } + } + + if (clickCountingForEvent) { + if (pressedDown == NO) return; + + NSNumber* eventNumber; + NSNumber* timeNumber; + @synchronized(self) { + lastClickCountEventTime = [NSDate timeIntervalSinceReferenceDate]; + if (lastClickCountEvent == event) { + eventClickCount = eventClickCount + 1; + } else { + eventClickCount = 1; + } + lastClickCountEvent = event; + timeNumber = [NSNumber numberWithDouble:lastClickCountEventTime]; + eventNumber= [NSNumber numberWithUnsignedInt:event]; + } + [self performSelector: @selector(executeClickCountEvent:) + withObject: [NSArray arrayWithObjects:eventNumber, timeNumber, nil] + afterDelay: maxClickTimeDifference]; + } else { + [delegate remoteButton:event pressedDown: pressedDown clickCount:1]; + } + +} + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControl.h b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControl.h new file mode 100644 index 0000000000..34e9d5e19d --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControl.h @@ -0,0 +1,102 @@ +/***************************************************************************** + * RemoteControl.h + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> + +// notifaction names that are being used to signal that an application wants to +// have access to the remote control device or if the application has finished +// using the remote control device +extern NSString* REQUEST_FOR_REMOTE_CONTROL_NOTIFCATION; +extern NSString* FINISHED_USING_REMOTE_CONTROL_NOTIFICATION; + +// keys used in user objects for distributed notifications +extern NSString* kRemoteControlDeviceName; +extern NSString* kApplicationIdentifier; +extern NSString* kTargetApplicationIdentifier; + +// we have a 6 bit offset to make a hold event out of a normal event +#define EVENT_TO_HOLD_EVENT_OFFSET 6 + +@class RemoteControl; + +typedef enum _RemoteControlEventIdentifier { + // normal events + kRemoteButtonPlus =1<<1, + kRemoteButtonMinus =1<<2, + kRemoteButtonMenu =1<<3, + kRemoteButtonPlay =1<<4, + kRemoteButtonRight =1<<5, + kRemoteButtonLeft =1<<6, + + // hold events + kRemoteButtonPlus_Hold =1<<7, + kRemoteButtonMinus_Hold =1<<8, + kRemoteButtonMenu_Hold =1<<9, + kRemoteButtonPlay_Hold =1<<10, + kRemoteButtonRight_Hold =1<<11, + kRemoteButtonLeft_Hold =1<<12, + + // special events (not supported by all devices) + kRemoteControl_Switched =1<<13, +} RemoteControlEventIdentifier; + +@interface NSObject(RemoteControlDelegate) + +- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown remoteControl: (RemoteControl*) remoteControl; + +@end + +/* + Base Interface for Remote Control devices + */ +@interface RemoteControl : NSObject { + id delegate; +} + +// returns nil if the remote control device is not available +- (id) initWithDelegate: (id) remoteControlDelegate; + +- (void) setListeningToRemote: (BOOL) value; +- (BOOL) isListeningToRemote; + +- (BOOL) isOpenInExclusiveMode; +- (void) setOpenInExclusiveMode: (BOOL) value; + +- (IBAction) startListening: (id) sender; +- (IBAction) stopListening: (id) sender; + +// is this remote control sending the given event? +- (BOOL) sendsEventForButtonIdentifier: (RemoteControlEventIdentifier) identifier; + +// sending of notifications between applications ++ (void) sendFinishedNotifcationForAppIdentifier: (NSString*) identifier; ++ (void) sendRequestForRemoteControlNotification; + +// name of the device ++ (const char*) remoteControlDeviceName; + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControl.m b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControl.m new file mode 100644 index 0000000000..bf224dd1d8 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControl.m @@ -0,0 +1,102 @@ +/***************************************************************************** + * RemoteControl.m + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import "RemoteControl.h" + +// notifaction names that are being used to signal that an application wants to +// have access to the remote control device or if the application has finished +// using the remote control device +NSString* REQUEST_FOR_REMOTE_CONTROL_NOTIFCATION = @"mac.remotecontrols.RequestForRemoteControl"; +NSString* FINISHED_USING_REMOTE_CONTROL_NOTIFICATION = @"mac.remotecontrols.FinishedUsingRemoteControl"; + +// keys used in user objects for distributed notifications +NSString* kRemoteControlDeviceName = @"RemoteControlDeviceName"; +NSString* kApplicationIdentifier = @"CFBundleIdentifier"; +// bundle identifier of the application that should get access to the remote control +// this key is being used in the FINISHED notification only +NSString* kTargetApplicationIdentifier = @"TargetBundleIdentifier"; + + +@implementation RemoteControl + +// returns nil if the remote control device is not available +- (id) initWithDelegate: (id) _remoteControlDelegate { + if (self = [super init]) { + delegate = _remoteControlDelegate; + } + return self; +} + +- (void) dealloc { + [super dealloc]; +} + +- (void) setListeningToRemote: (BOOL) value { +} +- (BOOL) isListeningToRemote { + return NO; +} + +- (IBAction) startListening: (id) sender { +} +- (IBAction) stopListening: (id) sender { + +} + +- (BOOL) isOpenInExclusiveMode { + return YES; +} +- (void) setOpenInExclusiveMode: (BOOL) value { +} + +- (BOOL) sendsEventForButtonIdentifier: (RemoteControlEventIdentifier) identifier { + return YES; +} + ++ (void) sendDistributedNotification: (NSString*) notificationName targetBundleIdentifier: (NSString*) targetIdentifier { + NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys: [NSString stringWithCString:[self remoteControlDeviceName] encoding:NSASCIIStringEncoding], + kRemoteControlDeviceName, [[NSBundle mainBundle] bundleIdentifier], kApplicationIdentifier, + targetIdentifier, kTargetApplicationIdentifier, nil]; + + [[NSDistributedNotificationCenter defaultCenter] postNotificationName:notificationName + object:nil + userInfo:userInfo + deliverImmediately:YES]; +} + ++ (void) sendFinishedNotifcationForAppIdentifier: (NSString*) identifier { + [self sendDistributedNotification:FINISHED_USING_REMOTE_CONTROL_NOTIFICATION targetBundleIdentifier:identifier]; +} ++ (void) sendRequestForRemoteControlNotification { + [self sendDistributedNotification:REQUEST_FOR_REMOTE_CONTROL_NOTIFCATION targetBundleIdentifier:nil]; +} + ++ (const char*) remoteControlDeviceName { + return NULL; +} + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControlContainer.h b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControlContainer.h new file mode 100644 index 0000000000..e665ae1eab --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControlContainer.h @@ -0,0 +1,38 @@ +/***************************************************************************** + * RemoteControlContainer.h + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> +#import "RemoteControl.h" + +@interface RemoteControlContainer : RemoteControl { + NSMutableArray* remoteControls; +} + +- (BOOL) instantiateAndAddRemoteControlDeviceWithClass: (Class) clazz; +- (unsigned int) count; + +@end diff --git a/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControlContainer.m b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControlContainer.m new file mode 100644 index 0000000000..8517ea733e --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/RemoteControlWrapper/RemoteControlContainer.m @@ -0,0 +1,114 @@ +/***************************************************************************** + * RemoteControlContainer.m + * RemoteControlWrapper + * + * Created by Martin Kahr on 11.03.06 under a MIT-style license. + * Copyright (c) 2006 martinkahr.com. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *****************************************************************************/ + +#import "RemoteControlContainer.h" + + +@implementation RemoteControlContainer + +- (id) initWithDelegate: (id) _remoteControlDelegate { + if (self = [super initWithDelegate:_remoteControlDelegate]) { + remoteControls = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void) dealloc { + [self stopListening: self]; + [remoteControls release]; + [super dealloc]; +} + +- (BOOL) instantiateAndAddRemoteControlDeviceWithClass: (Class) clazz { + RemoteControl* remoteControl = [[clazz alloc] initWithDelegate: delegate]; + if (remoteControl) { + [remoteControls addObject: remoteControl]; + [remoteControl addObserver: self forKeyPath:@"listeningToRemote" options:NSKeyValueObservingOptionNew context:nil]; + return YES; + } + return NO; +} + +- (unsigned int) count { + return [remoteControls count]; +} + +- (void) reset { + [self willChangeValueForKey:@"listeningToRemote"]; + [self didChangeValueForKey:@"listeningToRemote"]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + [self reset]; +} + +- (void) setListeningToRemote: (BOOL) value { + int i; + for(i=0; i < [remoteControls count]; i++) { + [[remoteControls objectAtIndex: i] setListeningToRemote: value]; + } + if (value && value != [self isListeningToRemote]) [self performSelector:@selector(reset) withObject:nil afterDelay:0.01]; +} +- (BOOL) isListeningToRemote { + int i; + for(i=0; i < [remoteControls count]; i++) { + if ([[remoteControls objectAtIndex: i] isListeningToRemote]) { + return YES; + } + } + return NO; +} + +- (IBAction) startListening: (id) sender { + int i; + for(i=0; i < [remoteControls count]; i++) { + [[remoteControls objectAtIndex: i] startListening: sender]; + } +} +- (IBAction) stopListening: (id) sender { + int i; + for(i=0; i < [remoteControls count]; i++) { + [[remoteControls objectAtIndex: i] stopListening: sender]; + } +} + +- (BOOL) isOpenInExclusiveMode { + BOOL mode = YES; + int i; + for(i=0; i < [remoteControls count]; i++) { + mode = mode && ([[remoteControls objectAtIndex: i] isOpenInExclusiveMode]); + } + return mode; +} +- (void) setOpenInExclusiveMode: (BOOL) value { + int i; + for(i=0; i < [remoteControls count]; i++) { + [[remoteControls objectAtIndex: i] setOpenInExclusiveMode:value]; + } +} + +@end diff --git a/tools/EventClients/Clients/OSXRemote/XBMCDebugHelpers.h b/tools/EventClients/Clients/OSXRemote/XBMCDebugHelpers.h new file mode 100644 index 0000000000..8650f87412 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/XBMCDebugHelpers.h @@ -0,0 +1,45 @@ +// +// XBMCDebugHelpers.h +// xbmclauncher +// +// Created by Stephan Diederich on 21.09.08. +// Copyright 2008 University Heidelberg. All rights reserved. +// +// 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 3 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, see <http://www.gnu.org/licenses/>. + +#import <Cocoa/Cocoa.h> + +/* + * Stuff below was taken from LoggingUtils.h of ATVFiles + * + * Just some utility macros for logging... + * + * Created by Eric Steil III on 4/1/07. + // Copyright (C) 2007-2008 Eric Steil III + * + */ + +#ifdef DEBUG +#define LOG(s, ...) NSLog(@"[DEBUG] " s, ##__VA_ARGS__) +#define ILOG(s, ...) NSLog(@"[INFO] " s, ##__VA_ARGS__) +#define ELOG(s, ...) NSLog(@"[ERROR] " s, ##__VA_ARGS__) +#define DLOG(s, ...) LOG(s, ##__VA_ARGS__) +#else +#define LOG(s, ...) +#define ILOG(s, ...) NSLog(@"[INFO] " s, ##__VA_ARGS__) +#define ELOG(s, ...) NSLog(@"[ERROR] " s, ##__VA_ARGS__) +#define DLOG(s, ...) LOG(s, ##__VA_ARGS__) +#endif + +#define PRINT_SIGNATURE() LOG(@"%s", __PRETTY_FUNCTION__) diff --git a/tools/EventClients/Clients/OSXRemote/XBMCHelper.h b/tools/EventClients/Clients/OSXRemote/XBMCHelper.h new file mode 100644 index 0000000000..9b194a9fd7 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/XBMCHelper.h @@ -0,0 +1,29 @@ +// +// XBMCHelper.h +// xbmchelper +// +// Created by Stephan Diederich on 11/12/08. +// Copyright 2008 University Heidelberg. All rights reserved. +// + +#import <Cocoa/Cocoa.h> +#import "xbmcclientwrapper.h" + +@class AppleRemote, MultiClickRemoteBehavior; + +@interface XBMCHelper : NSObject { + AppleRemote* mp_remote_control; + XBMCClientWrapper* mp_wrapper; + NSString* mp_app_path; + NSString* mp_home_path; + bool m_verbose; +} + +- (void) enableVerboseMode:(bool) f_really; + +- (void) setApplicationPath:(NSString*) fp_app_path; +- (void) setApplicationHome:(NSString*) fp_home_path; + +- (void) connectToServer:(NSString*) fp_server withMode:(eRemoteMode) f_mode withTimeout:(double) f_timeout; +- (void) disconnect; +@end diff --git a/tools/EventClients/Clients/OSXRemote/XBMCHelper.m b/tools/EventClients/Clients/OSXRemote/XBMCHelper.m new file mode 100644 index 0000000000..5e0223e11a --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/XBMCHelper.m @@ -0,0 +1,222 @@ +// +// XBMCHelper.m +// xbmchelper +// +// Created by Stephan Diederich on 11/12/08. +// Copyright 2008 University Heidelberg. All rights reserved. +// + +#import "XBMCHelper.h" +#import "remotecontrolwrapper/AppleRemote.h" +#import "XBMCDebugHelpers.h" +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +@implementation XBMCHelper +- (id) init{ + PRINT_SIGNATURE(); + if( ![super init] ){ + return nil; + } + mp_wrapper = nil; + mp_remote_control = [[[AppleRemote alloc] initWithDelegate: self] retain]; + [mp_remote_control setProcessesBacklog:true]; + [mp_remote_control setOpenInExclusiveMode:true]; + if( ! mp_remote_control ){ + NSException* myException = [NSException + exceptionWithName:@"AppleRemoteInitExecption" + reason:@"AppleRemote could not be initialized" + userInfo:nil]; + @throw myException; + } + [mp_remote_control startListening: self]; + if(![mp_remote_control isListeningToRemote]){ + ELOG(@"Warning: XBMCHelper could not open the IR-Device in exclusive mode. Other remote control apps running?"); + } + return self; +} + +- (void) dealloc{ + PRINT_SIGNATURE(); + [mp_remote_control stopListening: self]; + [mp_remote_control release]; + [mp_wrapper release]; + [mp_app_path release]; + [mp_home_path release]; + [super dealloc]; +} + +//---------------------------------------------------------------------------- +- (void) checkAndLaunchApp +{ + if(!mp_app_path || ![mp_app_path length]){ + ELOG(@"No executable set. Nothing to launch"); + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + if(![fileManager fileExistsAtPath:mp_app_path]){ + ELOG(@"Path does not exist: %@. Cannot launch executable", mp_app_path); + return; + } + if(mp_home_path && [mp_home_path length]) + setenv("XBMC_HOME", [mp_home_path cString], 1); + //launch or activate xbmc + if(![[NSWorkspace sharedWorkspace] launchApplication:mp_app_path]){ + ELOG(@"Error launching %@", mp_app_path); + } +} + +//---------------------------------------------------------------------------- +- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown remoteControl: (RemoteControl*) remoteControl; +{ + if(m_verbose) { + //do some logging here + //[self logButton: event press; + } + + switch(event){ + case kRemoteButtonPlay: + if(pressedDown) [mp_wrapper handleEvent:ATV_BUTTON_PLAY]; + break; + case kRemoteButtonPlay_Hold: + if(pressedDown) [mp_wrapper handleEvent:ATV_BUTTON_PLAY_H]; + break; + case kRemoteButtonRight: + if(pressedDown) + [mp_wrapper handleEvent:ATV_BUTTON_RIGHT]; + else + [mp_wrapper handleEvent:ATV_BUTTON_RIGHT_RELEASE]; + break; + case kRemoteButtonRight_Hold: + if(pressedDown) + [mp_wrapper handleEvent:ATV_BUTTON_RIGHT_H]; + else + [mp_wrapper handleEvent:ATV_BUTTON_RIGHT_H_RELEASE]; + break; + case kRemoteButtonLeft: + if(pressedDown) + [mp_wrapper handleEvent:ATV_BUTTON_LEFT]; + else + [mp_wrapper handleEvent:ATV_BUTTON_LEFT_RELEASE]; + break; + case kRemoteButtonLeft_Hold: + if(pressedDown) + [mp_wrapper handleEvent:ATV_BUTTON_LEFT_H]; + else + [mp_wrapper handleEvent:ATV_BUTTON_LEFT_H_RELEASE]; + break; + case kRemoteButtonPlus: + if(pressedDown) + [mp_wrapper handleEvent:ATV_BUTTON_UP]; + else + [mp_wrapper handleEvent:ATV_BUTTON_UP_RELEASE]; + break; + case kRemoteButtonMinus: + if(pressedDown) + [mp_wrapper handleEvent:ATV_BUTTON_DOWN]; + else + [mp_wrapper handleEvent:ATV_BUTTON_DOWN_RELEASE]; + break; + case kRemoteButtonMenu: + if(pressedDown){ + [self checkAndLaunchApp]; //launch mp_app_path if it's not running + [mp_wrapper handleEvent:ATV_BUTTON_MENU]; + } + break; + case kRemoteButtonMenu_Hold: + if(pressedDown) [mp_wrapper handleEvent:ATV_BUTTON_MENU_H]; + break; + case kRemoteControl_Switched: + if(pressedDown) [mp_wrapper switchRemote: [mp_remote_control deviceID]]; + break; + default: + NSLog(@"Oha, remote button not recognized %i pressed/released %i", event, pressedDown); + } +} + +//---------------------------------------------------------------------------- +- (void) connectToServer:(NSString*) fp_server withMode:(eRemoteMode) f_mode withTimeout:(double) f_timeout{ + if(mp_wrapper) + [self disconnect]; + mp_wrapper = [[XBMCClientWrapper alloc] initWithMode:f_mode serverAddress:fp_server verbose:m_verbose]; + [mp_wrapper setUniversalModeTimeout:f_timeout]; +} + +//---------------------------------------------------------------------------- +- (void) disconnect{ + [mp_wrapper release]; + mp_wrapper = nil; +} + +//---------------------------------------------------------------------------- +- (void) enableVerboseMode:(bool) f_really{ + m_verbose = f_really; + [mp_wrapper enableVerboseMode:f_really]; +} + +//---------------------------------------------------------------------------- +- (void) setApplicationPath:(NSString*) fp_app_path{ + if (mp_app_path != fp_app_path) { + [mp_app_path release]; + mp_app_path = [[fp_app_path stringByStandardizingPath] retain]; + } +} + +//---------------------------------------------------------------------------- +- (void) setApplicationHome:(NSString*) fp_home_path{ + if (mp_home_path != fp_home_path) { + [mp_home_path release]; + mp_home_path = [[fp_home_path stringByStandardizingPath] retain]; + } +} +// NSString* pressed; +// NSString* buttonName; +// if (pressedDown) pressed = @"(pressed)"; else pressed = @"(released)"; +// +// switch(event) { +// case kRemoteButtonPlus: +// buttonName = @"Volume up"; +// break; +// case kRemoteButtonMinus: +// buttonName = @"Volume down"; +// break; +// case kRemoteButtonMenu: +// buttonName = @"Menu"; +// break; +// case kRemoteButtonPlay: +// buttonName = @"Play"; +// break; +// case kRemoteButtonRight: +// buttonName = @"Right"; +// break; +// case kRemoteButtonLeft: +// buttonName = @"Left"; +// break; +// case kRemoteButtonRight_Hold: +// buttonName = @"Right holding"; +// break; +// case kRemoteButtonLeft_Hold: +// buttonName = @"Left holding"; +// break; +// case kRemoteButtonPlus_Hold: +// buttonName = @"Volume up holding"; +// break; +// case kRemoteButtonMinus_Hold: +// buttonName = @"Volume down holding"; +// break; +// case kRemoteButtonPlay_Hold: +// buttonName = @"Play (sleep mode)"; +// break; +// case kRemoteButtonMenu_Hold: +// buttonName = @"Menu holding"; +// break; +// case kRemoteControl_Switched: +// buttonName = @"Remote Control Switched"; +// break; +// default: +// break; +// } +// NSLog(@"%@ %@", pressed, buttonName); +// } + +@end diff --git a/tools/EventClients/Clients/OSXRemote/XBMCHelper.xcodeproj/project.pbxproj b/tools/EventClients/Clients/OSXRemote/XBMCHelper.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..0c6c5ef7c9 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/XBMCHelper.xcodeproj/project.pbxproj @@ -0,0 +1,305 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + E45F2B1C0F95191E007BCC0B /* IRKeyboardEmu.m in Sources */ = {isa = PBXBuildFile; fileRef = E45F2B1B0F95191E007BCC0B /* IRKeyboardEmu.m */; }; + E4E62F370F83DB760066AF9D /* xbmchelper_main.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F340F83DB760066AF9D /* xbmchelper_main.mm */; }; + E4E62F380F83DB760066AF9D /* XBMCHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F360F83DB760066AF9D /* XBMCHelper.m */; }; + E4E62F4A0F83DB830066AF9D /* AppleRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F3D0F83DB830066AF9D /* AppleRemote.m */; }; + E4E62F4B0F83DB830066AF9D /* GlobalKeyboardDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F3F0F83DB830066AF9D /* GlobalKeyboardDevice.m */; }; + E4E62F4C0F83DB830066AF9D /* HIDRemoteControlDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F410F83DB830066AF9D /* HIDRemoteControlDevice.m */; }; + E4E62F4D0F83DB830066AF9D /* KeyspanFrontRowControl.m in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F430F83DB830066AF9D /* KeyspanFrontRowControl.m */; }; + E4E62F4E0F83DB830066AF9D /* MultiClickRemoteBehavior.m in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F450F83DB830066AF9D /* MultiClickRemoteBehavior.m */; }; + E4E62F4F0F83DB830066AF9D /* RemoteControl.m in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F470F83DB830066AF9D /* RemoteControl.m */; }; + E4E62F500F83DB830066AF9D /* RemoteControlContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = E4E62F490F83DB830066AF9D /* RemoteControlContainer.m */; }; + E4E62F600F83FB8C0066AF9D /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4E62F5F0F83FB8C0066AF9D /* IOKit.framework */; }; + E4E62F690F83FBB40066AF9D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4E62F680F83FBB40066AF9D /* Carbon.framework */; }; + E4E62FD40F83FD7C0066AF9D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4E62FD30F83FD7C0066AF9D /* Cocoa.framework */; }; + E4E62FE80F83FDD90066AF9D /* xbmcclientwrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4E62FE60F83FDD90066AF9D /* xbmcclientwrapper.mm */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F7B0486A8DE00D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; }; + 8DD76F7E0486A8DE00D96B5E /* XBMCHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = XBMCHelper; sourceTree = BUILT_PRODUCTS_DIR; }; + E45F2B1A0F95191E007BCC0B /* IRKeyboardEmu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRKeyboardEmu.h; sourceTree = "<group>"; }; + E45F2B1B0F95191E007BCC0B /* IRKeyboardEmu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IRKeyboardEmu.m; sourceTree = "<group>"; }; + E4E62F340F83DB760066AF9D /* xbmchelper_main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = xbmchelper_main.mm; sourceTree = "<group>"; }; + E4E62F350F83DB760066AF9D /* XBMCHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBMCHelper.h; sourceTree = "<group>"; }; + E4E62F360F83DB760066AF9D /* XBMCHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XBMCHelper.m; sourceTree = "<group>"; }; + E4E62F3C0F83DB830066AF9D /* AppleRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleRemote.h; sourceTree = "<group>"; }; + E4E62F3D0F83DB830066AF9D /* AppleRemote.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppleRemote.m; sourceTree = "<group>"; }; + E4E62F3E0F83DB830066AF9D /* GlobalKeyboardDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlobalKeyboardDevice.h; sourceTree = "<group>"; }; + E4E62F3F0F83DB830066AF9D /* GlobalKeyboardDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GlobalKeyboardDevice.m; sourceTree = "<group>"; }; + E4E62F400F83DB830066AF9D /* HIDRemoteControlDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HIDRemoteControlDevice.h; sourceTree = "<group>"; }; + E4E62F410F83DB830066AF9D /* HIDRemoteControlDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HIDRemoteControlDevice.m; sourceTree = "<group>"; }; + E4E62F420F83DB830066AF9D /* KeyspanFrontRowControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyspanFrontRowControl.h; sourceTree = "<group>"; }; + E4E62F430F83DB830066AF9D /* KeyspanFrontRowControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeyspanFrontRowControl.m; sourceTree = "<group>"; }; + E4E62F440F83DB830066AF9D /* MultiClickRemoteBehavior.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MultiClickRemoteBehavior.h; sourceTree = "<group>"; }; + E4E62F450F83DB830066AF9D /* MultiClickRemoteBehavior.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MultiClickRemoteBehavior.m; sourceTree = "<group>"; }; + E4E62F460F83DB830066AF9D /* RemoteControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteControl.h; sourceTree = "<group>"; }; + E4E62F470F83DB830066AF9D /* RemoteControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteControl.m; sourceTree = "<group>"; }; + E4E62F480F83DB830066AF9D /* RemoteControlContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteControlContainer.h; sourceTree = "<group>"; }; + E4E62F490F83DB830066AF9D /* RemoteControlContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteControlContainer.m; sourceTree = "<group>"; }; + E4E62F5F0F83FB8C0066AF9D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + E4E62F680F83FBB40066AF9D /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; + E4E62FD30F83FD7C0066AF9D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + E4E62FE50F83FDD90066AF9D /* xbmcclientwrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbmcclientwrapper.h; sourceTree = "<group>"; }; + E4E62FE60F83FDD90066AF9D /* xbmcclientwrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = xbmcclientwrapper.mm; sourceTree = "<group>"; }; + E4E62FE70F83FDD90066AF9D /* XBMCDebugHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBMCDebugHelpers.h; sourceTree = "<group>"; }; + E4E630030F8406900066AF9D /* xbmcclient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xbmcclient.h; path = "../../lib/c++/xbmcclient.h"; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F780486A8DE00D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E4E62F600F83FB8C0066AF9D /* IOKit.framework in Frameworks */, + E4E62F690F83FBB40066AF9D /* Carbon.framework in Frameworks */, + E4E62FD40F83FD7C0066AF9D /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* XBMCHelper */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + C6859E96029091FE04C91782 /* Documentation */, + 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */, + 19C28FBDFE9D53C911CA2CBB /* Products */, + E4E62F5F0F83FB8C0066AF9D /* IOKit.framework */, + E4E62F680F83FBB40066AF9D /* Carbon.framework */, + E4E62FD30F83FD7C0066AF9D /* Cocoa.framework */, + ); + name = XBMCHelper; + sourceTree = "<group>"; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + E4E62F3B0F83DB830066AF9D /* RemoteControlWrapper */, + E4E630030F8406900066AF9D /* xbmcclient.h */, + E4E62F340F83DB760066AF9D /* xbmchelper_main.mm */, + E4E62F350F83DB760066AF9D /* XBMCHelper.h */, + E4E62F360F83DB760066AF9D /* XBMCHelper.m */, + E4E62FE70F83FDD90066AF9D /* XBMCDebugHelpers.h */, + E4E62FE50F83FDD90066AF9D /* xbmcclientwrapper.h */, + E4E62FE60F83FDD90066AF9D /* xbmcclientwrapper.mm */, + ); + name = Source; + sourceTree = "<group>"; + }; + 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */, + ); + name = "External Frameworks and Libraries"; + sourceTree = "<group>"; + }; + 19C28FBDFE9D53C911CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F7E0486A8DE00D96B5E /* XBMCHelper */, + ); + name = Products; + sourceTree = "<group>"; + }; + C6859E96029091FE04C91782 /* Documentation */ = { + isa = PBXGroup; + children = ( + ); + name = Documentation; + sourceTree = "<group>"; + }; + E4E62F3B0F83DB830066AF9D /* RemoteControlWrapper */ = { + isa = PBXGroup; + children = ( + E4E62F3C0F83DB830066AF9D /* AppleRemote.h */, + E4E62F3D0F83DB830066AF9D /* AppleRemote.m */, + E4E62F3E0F83DB830066AF9D /* GlobalKeyboardDevice.h */, + E4E62F3F0F83DB830066AF9D /* GlobalKeyboardDevice.m */, + E4E62F400F83DB830066AF9D /* HIDRemoteControlDevice.h */, + E4E62F410F83DB830066AF9D /* HIDRemoteControlDevice.m */, + E4E62F420F83DB830066AF9D /* KeyspanFrontRowControl.h */, + E4E62F430F83DB830066AF9D /* KeyspanFrontRowControl.m */, + E4E62F440F83DB830066AF9D /* MultiClickRemoteBehavior.h */, + E4E62F450F83DB830066AF9D /* MultiClickRemoteBehavior.m */, + E4E62F460F83DB830066AF9D /* RemoteControl.h */, + E4E62F470F83DB830066AF9D /* RemoteControl.m */, + E4E62F480F83DB830066AF9D /* RemoteControlContainer.h */, + E4E62F490F83DB830066AF9D /* RemoteControlContainer.m */, + E45F2B1A0F95191E007BCC0B /* IRKeyboardEmu.h */, + E45F2B1B0F95191E007BCC0B /* IRKeyboardEmu.m */, + ); + path = RemoteControlWrapper; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F740486A8DE00D96B5E /* XBMCHelper */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB924708733DCA0010E9CD /* Build configuration list for PBXNativeTarget "XBMCHelper" */; + buildPhases = ( + 8DD76F760486A8DE00D96B5E /* Sources */, + 8DD76F780486A8DE00D96B5E /* Frameworks */, + 8DD76F7B0486A8DE00D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = XBMCHelper; + productInstallPath = "$(HOME)/bin"; + productName = XBMCHelper; + productReference = 8DD76F7E0486A8DE00D96B5E /* XBMCHelper */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB924B08733DCA0010E9CD /* Build configuration list for PBXProject "XBMCHelper" */; + compatibilityVersion = "Xcode 3.1"; + hasScannedForEncodings = 1; + mainGroup = 08FB7794FE84155DC02AAC07 /* XBMCHelper */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F740486A8DE00D96B5E /* XBMCHelper */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F760486A8DE00D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E4E62F370F83DB760066AF9D /* xbmchelper_main.mm in Sources */, + E4E62F380F83DB760066AF9D /* XBMCHelper.m in Sources */, + E4E62F4A0F83DB830066AF9D /* AppleRemote.m in Sources */, + E4E62F4B0F83DB830066AF9D /* GlobalKeyboardDevice.m in Sources */, + E4E62F4C0F83DB830066AF9D /* HIDRemoteControlDevice.m in Sources */, + E4E62F4D0F83DB830066AF9D /* KeyspanFrontRowControl.m in Sources */, + E4E62F4E0F83DB830066AF9D /* MultiClickRemoteBehavior.m in Sources */, + E4E62F4F0F83DB830066AF9D /* RemoteControl.m in Sources */, + E4E62F500F83DB830066AF9D /* RemoteControlContainer.m in Sources */, + E4E62FE80F83FDD90066AF9D /* xbmcclientwrapper.mm in Sources */, + E45F2B1C0F95191E007BCC0B /* IRKeyboardEmu.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB924808733DCA0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CONFIGURATION_BUILD_DIR = ../../../osx; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = DEBUG; + INSTALL_PATH = /usr/local/bin; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = XBMCHelper; + SDKROOT = macosx10.4; + STRIP_STYLE = debugging; + }; + name = Debug; + }; + 1DEB924908733DCA0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CONFIGURATION_BUILD_DIR = ../../../osx; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + GCC_VERSION = 4.0; + INSTALL_PATH = /usr/local/bin; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = XBMCHelper; + SDKROOT = macosx10.4; + STRIP_STYLE = debugging; + }; + name = Release; + }; + 1DEB924C08733DCA0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.4; + }; + name = Debug; + }; + 1DEB924D08733DCA0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.4; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB924708733DCA0010E9CD /* Build configuration list for PBXNativeTarget "XBMCHelper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB924808733DCA0010E9CD /* Debug */, + 1DEB924908733DCA0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB924B08733DCA0010E9CD /* Build configuration list for PBXProject "XBMCHelper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB924C08733DCA0010E9CD /* Debug */, + 1DEB924D08733DCA0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/tools/EventClients/Clients/OSXRemote/xbmcclientwrapper.h b/tools/EventClients/Clients/OSXRemote/xbmcclientwrapper.h new file mode 100644 index 0000000000..8664b2d985 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/xbmcclientwrapper.h @@ -0,0 +1,73 @@ +/* + * xbmcclient.cpp + * xbmclauncher + * + * Created by Stephan Diederich on 17.09.08. + * Copyright 2008 Stephan Diederich. All rights reserved. + * + */ +// 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 3 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, see <http://www.gnu.org/licenses/>. +#import <Cocoa/Cocoa.h> + +typedef enum{ + ATV_BUTTON_DONT_USE_THIS = 0, //don't use zero, as those enums get converted to strings later + ATV_BUTTON_PLAY=1, + ATV_BUTTON_PLAY_H, //present on ATV>=2.2 + ATV_BUTTON_RIGHT, + ATV_BUTTON_RIGHT_RELEASE, + ATV_BUTTON_RIGHT_H, //present on ATV<=2.1 and OSX v? + ATV_BUTTON_RIGHT_H_RELEASE, + ATV_BUTTON_LEFT, + ATV_BUTTON_LEFT_RELEASE, + ATV_BUTTON_LEFT_H, //present on ATV<=2.1 and OSX v? + ATV_BUTTON_LEFT_H_RELEASE, + ATV_BUTTON_UP, + ATV_BUTTON_UP_RELEASE, + ATV_BUTTON_DOWN, + ATV_BUTTON_DOWN_RELEASE, + ATV_BUTTON_MENU, + ATV_BUTTON_MENU_H, + ATV_LEARNED_PLAY, + ATV_LEARNED_PAUSE, + ATV_LEARNED_STOP, + ATV_LEARNED_PREVIOUS, + ATV_LEARNED_NEXT, + ATV_LEARNED_REWIND, //>=ATV 2.3 + ATV_LEARNED_REWIND_RELEASE, //>=ATV 2.3 + ATV_LEARNED_FORWARD, //>=ATV 2.3 + ATV_LEARNED_FORWARD_RELEASE, //>=ATV 2.3 + ATV_LEARNED_RETURN, + ATV_LEARNED_ENTER, + ATV_INVALID_BUTTON +} eATVClientEvent; + + +typedef enum { + DEFAULT_MODE, + UNIVERSAL_MODE, + MULTIREMOTE_MODE +} eRemoteMode; + + +@interface XBMCClientWrapper : NSObject{ + struct XBMCClientWrapperImpl* mp_impl; +} +- (id) initWithMode:(eRemoteMode) f_mode serverAddress:(NSString*) fp_server verbose:(bool) f_verbose; +- (void) setUniversalModeTimeout:(double) f_timeout; + +-(void) handleEvent:(eATVClientEvent) f_event; +-(void) switchRemote:(int) f_device_id; + +- (void) enableVerboseMode:(bool) f_really; +@end
\ No newline at end of file diff --git a/tools/EventClients/Clients/OSXRemote/xbmcclientwrapper.mm b/tools/EventClients/Clients/OSXRemote/xbmcclientwrapper.mm new file mode 100644 index 0000000000..ab4d0de655 --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/xbmcclientwrapper.mm @@ -0,0 +1,430 @@ +/* + * xbmcclient.cpp + * xbmclauncher + * + * Created by Stephan Diederich on 17.09.08. + * Copyright 2008 University Heidelberg. All rights reserved. + * + */ +// 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 3 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, see <http://www.gnu.org/licenses/>. + +#include "xbmcclientwrapper.h" +#include "../../lib/c++/xbmcclient.h" +#include "XBMCDebugHelpers.h" +#include <vector> +#include <map> +#include <string> +#include <sstream> + +//helper class for easy EventSequence handling +class XBMCClientEventSequence{ +public: + XBMCClientEventSequence(){} + + //implicit conversion + XBMCClientEventSequence(eATVClientEvent f_event){ + m_stream.push_back(f_event); + } + + std::string str() const{ + std::stringstream ss; + for(std::vector<eATVClientEvent>::const_iterator it = m_stream.begin(); + it != m_stream.end(); + ++it){ + ss << *it; + } + return ss.str(); + } + void clear(){ + m_stream.clear(); + } + + // + // operators + // + friend XBMCClientEventSequence operator+ (XBMCClientEventSequence f_seq, eATVClientEvent f_event){ + f_seq.m_stream.push_back(f_event); + return f_seq; + } + XBMCClientEventSequence& operator << (eATVClientEvent f_event){ + m_stream.push_back(f_event); + return *this; + } + friend bool operator <(XBMCClientEventSequence const& fcr_lhs,XBMCClientEventSequence const& fcr_rhs){ + return fcr_lhs.m_stream < fcr_rhs.m_stream; + } + friend bool operator ==(XBMCClientEventSequence const& fcr_lhs,XBMCClientEventSequence const& fcr_rhs){ + return fcr_lhs.m_stream == fcr_rhs.m_stream; + } +private: + std::vector<eATVClientEvent> m_stream; +}; + + +//typedef is here, as is seems that I can't put it into iterface declaration +//CPacketBUTTON is a pointer, as I'm not sure how well it's copy constructor is implemented +typedef std::map<eATVClientEvent, CPacketBUTTON*> tEventMap; +typedef std::map<XBMCClientEventSequence, CPacketBUTTON*> tSequenceMap; +typedef std::map<std::pair<int, eATVClientEvent>, CPacketBUTTON*> tMultiRemoteMap; + +class XBMCClientWrapperImpl{ + tEventMap m_event_map; + tSequenceMap m_sequence_map; + tMultiRemoteMap m_multiremote_map; + eRemoteMode m_mode; + int m_socket; + std::string m_address; + XBMCClientEventSequence m_sequence; + CFRunLoopTimerRef m_timer; + double m_sequence_timeout; + int m_device_id; + bool m_verbose_mode; + void populateEventMap(); + void populateSequenceMap(); + void populateMultiRemoteModeMap(); + void sendButton(eATVClientEvent f_event); + void sendSequence(); + void restartTimer(); + void resetTimer(); + bool isStartToken(eATVClientEvent f_event); + static void timerCallBack (CFRunLoopTimerRef timer, void *info); +public: + XBMCClientWrapperImpl(eRemoteMode f_mode, const std::string& fcr_address = "localhost", bool f_verbose_mode=false); + ~XBMCClientWrapperImpl(); + void setUniversalModeTimeout(double f_timeout){ + m_sequence_timeout = f_timeout; + } + void switchRemote(int f_device_id){ + m_device_id = f_device_id; + } + void handleEvent(eATVClientEvent f_event); + void enableVerboseMode(bool f_value){ + m_verbose_mode = f_value; + } +}; + +void XBMCClientWrapperImpl::timerCallBack (CFRunLoopTimerRef timer, void *info) +{ + if (!info) + { + fprintf(stderr, "Error. invalid argument to timer callback\n"); + return; + } + + XBMCClientWrapperImpl *p_impl = (XBMCClientWrapperImpl *)info; + p_impl->sendSequence(); + p_impl->resetTimer(); +} + +void XBMCClientWrapperImpl::resetTimer(){ + if (m_timer) + { + CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), m_timer, kCFRunLoopCommonModes); + CFRunLoopTimerInvalidate(m_timer); + CFRelease(m_timer); + m_timer = NULL; + } +} + +void XBMCClientWrapperImpl::restartTimer(){ + if (m_timer) + resetTimer(); + + CFRunLoopTimerContext context = { 0, this, 0, 0, 0 }; + m_timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + m_sequence_timeout, 0, 0, 0, timerCallBack, &context); + CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_timer, kCFRunLoopCommonModes); +} + +XBMCClientWrapperImpl::XBMCClientWrapperImpl(eRemoteMode f_mode, const std::string& fcr_address, bool f_verbose_mode): +m_mode(f_mode), m_address(fcr_address), m_timer(0), m_sequence_timeout(0.5), m_device_id(150), m_verbose_mode(f_verbose_mode){ + PRINT_SIGNATURE(); + + if(m_mode == MULTIREMOTE_MODE){ + if(m_verbose_mode) + NSLog(@"XBMCClientWrapperImpl started in multiremote mode sending to address %s", fcr_address.c_str()); + populateMultiRemoteModeMap(); + } else { + if(m_mode == UNIVERSAL_MODE){ + if(m_verbose_mode) + NSLog(@"XBMCClientWrapperImpl started in universal mode sending to address %s", fcr_address.c_str()); + populateSequenceMap(); + } else if(m_verbose_mode) + NSLog(@"XBMCClientWrapperImpl started in normal mode sending to address %s", fcr_address.c_str()); + populateEventMap(); + } + + //open udp port etc + m_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (m_socket < 0) + { + ELOG(@"Error opening UDP socket! error: ", errno); + //TODO What to do? + } +} + +namespace { + struct delete_second{ + template <class T> + void operator ()(T& fr_pair){ + delete fr_pair.second; + } + }; +} +XBMCClientWrapperImpl::~XBMCClientWrapperImpl(){ + PRINT_SIGNATURE(); + resetTimer(); + shutdown(m_socket, SHUT_RDWR); + std::for_each(m_event_map.begin(), m_event_map.end(), delete_second()); + std::for_each(m_sequence_map.begin(), m_sequence_map.end(), delete_second()); + std::for_each(m_multiremote_map.begin(), m_multiremote_map.end(), delete_second()); +} + +bool XBMCClientWrapperImpl::isStartToken(eATVClientEvent f_event){ + return f_event==ATV_BUTTON_MENU_H; +} + +void XBMCClientWrapperImpl::sendButton(eATVClientEvent f_event){ + CPacketBUTTON* lp_packet = 0; + if(m_mode == MULTIREMOTE_MODE){ + tMultiRemoteMap::iterator it = m_multiremote_map.find(std::make_pair(m_device_id, f_event)); + if(it == m_multiremote_map.end()){ + ELOG(@"XBMCClientWrapperImpl::sendButton: No mapping defined for remoteID: %i button %i", m_device_id, f_event); + return; + } + lp_packet = it->second; + } else { + tEventMap::iterator it = m_event_map.find(f_event); + if(it == m_event_map.end()){ + ELOG(@"XBMCClientWrapperImpl::sendButton: No mapping defined for button %i", f_event); + return; + } + lp_packet = it->second; + } + assert(lp_packet); + CAddress addr(m_address.c_str()); + if(m_verbose_mode) + NSLog(@"XBMCClientWrapperImpl::sendButton sending button %i down:%i up:%i", lp_packet->GetButtonCode(), lp_packet->GetFlags()&BTN_DOWN,lp_packet->GetFlags()&BTN_UP ); + lp_packet->Send(m_socket, addr); +} + +void XBMCClientWrapperImpl::sendSequence(){ + tSequenceMap::const_iterator it = m_sequence_map.find(m_sequence); + if(it != m_sequence_map.end()){ + CPacketBUTTON& packet = *(it->second); + CAddress addr(m_address.c_str()); + packet.Send(m_socket, addr); + if(m_verbose_mode) + NSLog(@"XBMCClientWrapperImpl::sendSequence sent sequence %i down:%i up:%i", packet.GetButtonCode(), packet.GetFlags()&BTN_DOWN,packet.GetFlags()&BTN_UP ); + } else { + ELOG(@"XBMCClientWrapperImpl::sendSequence: No mapping defined for sequence %s", m_sequence.str().c_str()); + } + m_sequence.clear(); +} + +void XBMCClientWrapperImpl::handleEvent(eATVClientEvent f_event){ + if(m_mode != UNIVERSAL_MODE){ + sendButton(f_event); + } else { + //in universal mode no keys are directly send. instead a key-sequence is assembled and a timer started + //when the timer expires, that key sequence is checked against predefined sequences and if it is a valid one, + //a button press is generated + if(m_sequence.str().empty()){ + if(isStartToken(f_event)){ + m_sequence << f_event; + DLOG(@"Starting sequence with token %s", m_sequence.str().c_str()); + restartTimer(); + } else { + sendButton(f_event); + } + } else { + //dont queue release-events but restart timer + if(f_event == ATV_BUTTON_LEFT_RELEASE || f_event == ATV_BUTTON_RIGHT_RELEASE || f_event == ATV_BUTTON_UP_RELEASE || f_event == ATV_BUTTON_DOWN_RELEASE) + DLOG(@"Discarded button up event for sequence"); + else{ + m_sequence << f_event; + DLOG(@"Extended sequence to %s", m_sequence.str().c_str()); + } + restartTimer(); + } + } +} + +void XBMCClientWrapperImpl::populateEventMap(){ + tEventMap& lr_map = m_event_map; + + lr_map.insert(std::make_pair(ATV_BUTTON_PLAY, new CPacketBUTTON(5, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_RIGHT, new CPacketBUTTON(4, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_RIGHT_RELEASE, new CPacketBUTTON(4, "JS0:AppleRemote", BTN_UP | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_LEFT, new CPacketBUTTON(3, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT| BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_LEFT_RELEASE, new CPacketBUTTON(3, "JS0:AppleRemote", BTN_UP | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_MENU, new CPacketBUTTON(6, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_MENU_H, new CPacketBUTTON(8, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_UP, new CPacketBUTTON(1, "JS0:AppleRemote", BTN_DOWN | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_UP_RELEASE, new CPacketBUTTON(1, "JS0:AppleRemote", BTN_UP | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_DOWN, new CPacketBUTTON(2, "JS0:AppleRemote", BTN_DOWN | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_DOWN_RELEASE, new CPacketBUTTON(2, "JS0:AppleRemote", BTN_UP | BTN_QUEUE))); + + // only present on ATV <= 2.1 <--- check that; OSX seems to have the release parts + lr_map.insert(std::make_pair(ATV_BUTTON_RIGHT_H, new CPacketBUTTON(10, "JS0:AppleRemote", BTN_DOWN | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_RIGHT_H_RELEASE, new CPacketBUTTON(10, "JS0:AppleRemote", BTN_UP | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_LEFT_H, new CPacketBUTTON(11, "JS0:AppleRemote", BTN_DOWN | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_BUTTON_LEFT_H_RELEASE, new CPacketBUTTON(11, "JS0:AppleRemote", BTN_UP | BTN_QUEUE))); + + // only present on atv >= 2.2 + lr_map.insert(std::make_pair(ATV_BUTTON_PLAY_H, new CPacketBUTTON(7, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + + //learned remote buttons (ATV >=2.3) + lr_map.insert(std::make_pair(ATV_LEARNED_PLAY, new CPacketBUTTON(70, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_PAUSE, new CPacketBUTTON(71, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_STOP, new CPacketBUTTON(72, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_PREVIOUS, new CPacketBUTTON(73, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_NEXT, new CPacketBUTTON(74, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_REWIND, new CPacketBUTTON(75, "JS0:AppleRemote", BTN_DOWN | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_REWIND_RELEASE, new CPacketBUTTON(75, "JS0:AppleRemote", BTN_UP | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_FORWARD, new CPacketBUTTON(76, "JS0:AppleRemote", BTN_DOWN | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_FORWARD_RELEASE, new CPacketBUTTON(76, "JS0:AppleRemote", BTN_UP | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_RETURN, new CPacketBUTTON(77, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + lr_map.insert(std::make_pair(ATV_LEARNED_ENTER, new CPacketBUTTON(78, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); +} + +void XBMCClientWrapperImpl::populateSequenceMap(){ + XBMCClientEventSequence sequence_prefix; + sequence_prefix << ATV_BUTTON_MENU_H; + m_sequence_map.insert(std::make_pair(sequence_prefix, new CPacketBUTTON(8, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_PLAY, new CPacketBUTTON(20, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_RIGHT, new CPacketBUTTON(21, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_LEFT, new CPacketBUTTON(22, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_UP, new CPacketBUTTON(23, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_DOWN, new CPacketBUTTON(24, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_MENU, new CPacketBUTTON(25, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + + sequence_prefix.clear(); + sequence_prefix << ATV_BUTTON_MENU_H << ATV_BUTTON_PLAY; + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_PLAY, new CPacketBUTTON(26, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_RIGHT, new CPacketBUTTON(27, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_LEFT, new CPacketBUTTON(28, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_UP, new CPacketBUTTON(29, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_DOWN, new CPacketBUTTON(30, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_MENU, new CPacketBUTTON(31, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + + sequence_prefix.clear(); + sequence_prefix << ATV_BUTTON_MENU_H << ATV_BUTTON_UP; + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_PLAY, new CPacketBUTTON(32, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_RIGHT, new CPacketBUTTON(33, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_LEFT, new CPacketBUTTON(34, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_UP, new CPacketBUTTON(35, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_DOWN, new CPacketBUTTON(36, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_MENU, new CPacketBUTTON(37, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + + sequence_prefix.clear(); + sequence_prefix << ATV_BUTTON_MENU_H << ATV_BUTTON_DOWN; + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_PLAY, new CPacketBUTTON(38, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_RIGHT, new CPacketBUTTON(39, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_LEFT, new CPacketBUTTON(40, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_UP, new CPacketBUTTON(41, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_DOWN, new CPacketBUTTON(42, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_MENU, new CPacketBUTTON(43, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + + sequence_prefix.clear(); + sequence_prefix << ATV_BUTTON_MENU_H << ATV_BUTTON_RIGHT; + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_PLAY, new CPacketBUTTON(44, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_RIGHT, new CPacketBUTTON(45, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_LEFT, new CPacketBUTTON(46, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_UP, new CPacketBUTTON(47, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_DOWN, new CPacketBUTTON(48, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_MENU, new CPacketBUTTON(49, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + + sequence_prefix.clear(); + sequence_prefix << ATV_BUTTON_MENU_H << ATV_BUTTON_LEFT; + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_PLAY, new CPacketBUTTON(50, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_RIGHT, new CPacketBUTTON(51, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_LEFT, new CPacketBUTTON(52, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_UP, new CPacketBUTTON(53, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_DOWN, new CPacketBUTTON(54, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_sequence_map.insert(std::make_pair( sequence_prefix + ATV_BUTTON_MENU, new CPacketBUTTON(55, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); +} + +void XBMCClientWrapperImpl::populateMultiRemoteModeMap(){ + //the example of harmony as a multi-remote uses a few key device-id's paired with the normal buttons + static int device_ids[] = {150, 151, 152, 153, 154, 155, 157, 158, 159, 160}; + int offset = 0; + for(int* device_id = device_ids; device_id != device_ids + sizeof(device_ids)/sizeof(*device_ids); ++device_id, offset += 10) + { + // keymaps for mult-apple-remote, including the device-key sent after remote-switch + // we just add them here with unique button numbers and do the real mapping in keymap.xml + // as an offset for the buttons we use the device + + // this loop should probably be replaced by a proper setting of the individual keys + // cons: currently only button-codes (aka ints) are sent + // way too lazy ;) + // pro: custom tweaks. e.g. button 1 on the harmony may be (153, ATV_BUTTON_LEFT) and this should not get a repeat + // maybe use the loop and tweak individual buttons later; plex maps here to strings, and later in keymap.xml to other strings, + // but this may need another kind of remote in XBMC source + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_UP), new CPacketBUTTON(1 + offset, "JS0:Harmony", BTN_DOWN | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_UP_RELEASE), new CPacketBUTTON(1 + offset, "JS0:Harmony", BTN_UP | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_DOWN), new CPacketBUTTON(2 + offset, "JS0:Harmony", BTN_DOWN | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_DOWN_RELEASE), new CPacketBUTTON(2 + offset, "JS0:Harmony", BTN_UP | BTN_QUEUE))); + + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_LEFT), new CPacketBUTTON(3 + offset, "JS0:Harmony", BTN_DOWN | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_LEFT_RELEASE), new CPacketBUTTON(3 + offset, "JS0:Harmony", BTN_UP | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_RIGHT), new CPacketBUTTON(4 + offset, "JS0:Harmony", BTN_DOWN | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_RIGHT_RELEASE), new CPacketBUTTON(4 + offset, "JS0:Harmony", BTN_UP | BTN_QUEUE))); + + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_PLAY), new CPacketBUTTON(5 + offset, "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_MENU), new CPacketBUTTON(6 + offset, "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_PLAY_H), new CPacketBUTTON(7 + offset, "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_MENU_H), new CPacketBUTTON(8 + offset, "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE))); + + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_RIGHT_H), new CPacketBUTTON(9 + offset, "JS0:Harmony", BTN_DOWN | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_RIGHT_H_RELEASE),new CPacketBUTTON(9 + offset, "JS0:Harmony", BTN_UP | BTN_QUEUE))); + + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_LEFT_H), new CPacketBUTTON(10 + offset, "JS0:Harmony", BTN_DOWN | BTN_QUEUE))); + m_multiremote_map.insert(std::make_pair(std::make_pair(*device_id,ATV_BUTTON_LEFT_H_RELEASE),new CPacketBUTTON(10 + offset, "JS0:Harmony", BTN_UP | BTN_QUEUE))); + } +} + +@implementation XBMCClientWrapper +- (id) init { + return [self initWithMode:DEFAULT_MODE serverAddress:@"localhost" verbose: false]; +} +- (id) initWithMode:(eRemoteMode) f_mode serverAddress:(NSString*) fp_server verbose:(bool) f_verbose{ + PRINT_SIGNATURE(); + if( ![super init] ) + return nil; + mp_impl = new XBMCClientWrapperImpl(f_mode, [fp_server UTF8String], f_verbose); + return self; +} + +- (void) setUniversalModeTimeout:(double) f_timeout{ + mp_impl->setUniversalModeTimeout(f_timeout); +} + +- (void)dealloc{ + PRINT_SIGNATURE(); + delete mp_impl; + [super dealloc]; +} + +-(void) handleEvent:(eATVClientEvent) f_event{ + mp_impl->handleEvent(f_event); +} + +-(void) switchRemote:(int) f_device_id{ + mp_impl->switchRemote(f_device_id); +} + +- (void) enableVerboseMode:(bool) f_really{ + mp_impl->enableVerboseMode(f_really); +} +@end diff --git a/tools/EventClients/Clients/OSXRemote/xbmchelper_main.mm b/tools/EventClients/Clients/OSXRemote/xbmchelper_main.mm new file mode 100644 index 0000000000..d4af31501a --- /dev/null +++ b/tools/EventClients/Clients/OSXRemote/xbmchelper_main.mm @@ -0,0 +1,210 @@ +#include "Carbon/Carbon.h" +#import "XBMCHelper.h" +#include <getopt.h> +#include <string> +#include <vector> +#include <sstream> +#include <fstream> +#include <iterator> + +using namespace std; + +//instantiate XBMCHelper which registers itself to IR handling stuff +XBMCHelper* gp_xbmchelper; +eRemoteMode g_mode = DEFAULT_MODE; +std::string g_server_address="localhost"; +std::string g_app_path = ""; +std::string g_app_home = ""; +double g_universal_timeout = 0.500; +bool g_verbose_mode = false; + +// +const char* PROGNAME="XBMCHelper"; +const char* PROGVERS="0.5"; + +void ParseOptions(int argc, char** argv); +void ReadConfig(); + +static struct option long_options[] = { +{ "help", no_argument, 0, 'h' }, +{ "server", required_argument, 0, 's' }, +{ "universal", no_argument, 0, 'u' }, +{ "multiremote", no_argument, 0, 'm' }, +{ "timeout", required_argument, 0, 't' }, +{ "verbose", no_argument, 0, 'v' }, +{ "externalConfig", no_argument, 0, 'x' }, +{ "appPath", required_argument, 0, 'a' }, +{ "appHome", required_argument, 0, 'z' }, +{ 0, 0, 0, 0 }, +}; + +static const char *options = "hs:umt:vxa:z:"; + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +void usage(void) +{ + printf("%s (version %s)\n", PROGNAME, PROGVERS); + printf(" Sends Apple Remote events to XBMC.\n\n"); + printf("Usage: %s [OPTIONS...]\n\nOptions:\n", PROGNAME); + printf(" -h, --help print this help message and exit.\n"); + printf(" -s, --server <addr> send events to the specified IP.\n"); + printf(" -u, --universal runs in Universal Remote mode.\n"); + printf(" -t, --timeout <ms> timeout length for sequences (default: 500ms).\n"); + printf(" -m, --multiremote runs in Multi-Remote mode (adds remote identifier as additional idenfier to buttons)\n"); + printf(" -a, --appPath path to XBMC.app (MenuPress launch support).\n"); + printf(" -z, --appHome path to XBMC.app/Content/Resources/XBMX \n"); + printf(" -v, --verbose prints lots of debugging information.\n"); +} + +//---------------------------------------------------------------------------- +void ReadConfig() +{ + // Compute filename. + std::string strFile = getenv("HOME"); + strFile += "/Library/Application Support/XBMC/XBMCHelper.conf"; + + // Open file. + std::ifstream ifs(strFile.c_str()); + if (!ifs) + return; + + // Read file. + stringstream oss; + oss << ifs.rdbuf(); + + if (!ifs && !ifs.eof()) + return; + + // Tokenize. + string strData(oss.str()); + istringstream is(strData); + vector<string> args = vector<string>(istream_iterator<string>(is), istream_iterator<string>()); + + // Convert to char**. + int argc = args.size() + 1; + char** argv = new char*[argc + 1]; + int i = 0; + argv[i++] = "XBMCHelper"; + + for (vector<string>::iterator it = args.begin(); it != args.end(); ){ + //fixup the arguments, here: remove '"' like bash would normally do + std::string::size_type j = 0; + while ((j = it->find("\"", j)) != std::string::npos ) + it->replace(j, 1, ""); + argv[i++] = (char* )(*it++).c_str(); + } + + argv[i] = 0; + + // Parse the arguments. + ParseOptions(argc, argv); + + delete[] argv; +} + +//---------------------------------------------------------------------------- +void ParseOptions(int argc, char** argv) +{ + int c, option_index = 0; + //set the defaults + bool readExternal = false; + g_server_address = "localhost"; + g_mode = DEFAULT_MODE; + g_app_path = ""; + g_app_home = ""; + g_universal_timeout = 0.5; + g_verbose_mode = false; + + while ((c = getopt_long(argc, argv, options, long_options, &option_index)) != -1) + { + switch (c) { + case 'h': + usage(); + exit(0); + break; + case 'v': + g_verbose_mode = true; + break; + case 's': + g_server_address = optarg; + break; + case 'u': + g_mode = UNIVERSAL_MODE; + break; + case 'm': + g_mode = MULTIREMOTE_MODE; + break; + case 't': + g_universal_timeout = atof(optarg) * 0.001; + break; + case 'x': + readExternal = true; + break; + case 'a': + g_app_path = optarg; + break; + case 'z': + g_app_home = optarg; + break; + default: + usage(); + exit(1); + break; + } + } + //reset getopts state + optreset = 1; + optind = 0; + + if (readExternal == true) + ReadConfig(); + +} + +//---------------------------------------------------------------------------- +void StartHelper(){ + [gp_xbmchelper enableVerboseMode:g_verbose_mode]; + + //set apppath to startup when pressing Menu + [gp_xbmchelper setApplicationPath:[NSString stringWithCString:g_app_path.c_str()]]; + //set apppath to startup when pressing Menu + [gp_xbmchelper setApplicationHome:[NSString stringWithCString:g_app_home.c_str()]]; + //connect to specified server + [gp_xbmchelper connectToServer:[NSString stringWithCString:g_server_address.c_str()] withMode:g_mode withTimeout: g_universal_timeout]; +} + +//---------------------------------------------------------------------------- +void Reconfigure(int nSignal) +{ + if (nSignal == SIGHUP){ + ReadConfig(); + StartHelper(); + } + else { + QuitEventLoop(GetMainEventLoop()); + } +} + +//---------------------------------------------------------------------------- +int main (int argc, char * argv[]) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSLog(@"%s %s starting up...", PROGNAME, PROGVERS); + gp_xbmchelper = [[XBMCHelper alloc] init]; + + signal(SIGHUP, Reconfigure); + signal(SIGINT, Reconfigure); + signal(SIGTERM, Reconfigure); + + ParseOptions(argc,argv); + StartHelper(); + + //run event loop in this thread + RunCurrentEventLoop(kEventDurationForever); + NSLog(@"%s %s exiting...", PROGNAME, PROGVERS); + //cleanup + [gp_xbmchelper release]; + [pool drain]; + return 0; +} diff --git a/tools/EventClients/Clients/PS3 BD Remote/ps3_remote.py b/tools/EventClients/Clients/PS3 BD Remote/ps3_remote.py new file mode 100755 index 0000000000..c6b2aea4a1 --- /dev/null +++ b/tools/EventClients/Clients/PS3 BD Remote/ps3_remote.py @@ -0,0 +1,202 @@ +#!/usr/bin/python + +# This is a quick port of brandonj's PS3 remote script to use the event server +# for sending input events. +# +# The original script and documentation regarding the remote can be found at: +# http://xbmc.org/forum/showthread.php?t=28765 +# +# +# TODO: +# 1. Send keepalive ping at least once every 60 seconds to prevent timeouts +# 2. Permanent pairing +# 3. Detect if XBMC has been restarted (non trivial until broadcasting is +# implemented, until then maybe the HELO packet could be used instead of +# PING as keepalive +# + +import sys + +try: + # try loading modules from source directory + sys.path.append("../../lib/python") + from xbmcclient import * + from ps3.keymaps import keymap_remote as g_keymap # look here to change the keymapping + from bt.bt import * + ICON_PATH = "../../icons/" +except: + # fallback to system wide modules + from xbmc.xbmcclient import * + from xbmc.ps3.keymaps import keymap_remote as g_keymap # look here to change the keymapping + from xbmc.bt.bt import * + from xbmc.defs import * + +import os +import time + +xbmc = None +bticon = ICON_PATH + "/bluetooth.png" + +def get_remote_address(remote, target_name = "BD Remote Control"): + global xbmc + target_connected = False + target_address = None + while target_connected is False: + xbmc.send_notification("Action Required!", + "Hold Start+Enter on your remote.", + bticon) + print "Searching for %s" % target_name + print "(Hold Start + Enter on remote to make it discoverable)" + time.sleep(2) + + if not target_address: + try: + nearby_devices = bt_discover_devices() + except Exception, e: + print "Error performing bluetooth discovery" + print str(e) + xbmc.send_notification("Error", "Unable to find devices.", bticon) + time.sleep(5) + continue + + for bdaddr in nearby_devices: + bname = bt_lookup_name( bdaddr ) + addr = bt_lookup_addr ( bdaddr ) + print "%s (%s) in range" % (bname,addr) + if target_name == bname: + target_address = addr + break + + if target_address is not None: + print "Found %s with address %s" % (target_name, target_address) + xbmc.send_notification("Found Device", + "Pairing %s, please wait." % target_name, + bticon) + print "Attempting to pair with remote" + + try: + remote.connect((target_address,19)) + target_connected = True + print "Remote Paired.\a" + xbmc.send_notification("Pairing Successfull", + "Your remote was successfully "\ + "paired and is ready to be used.", + bticon) + except: + del remote + remote = bt_create_socket() + target_address = None + xbmc.send_notification("Pairing Failed", + "An error occurred while attempting to "\ + "pair.", bticon) + print "ERROR - Could Not Connect. Trying again..." + time.sleep(2) + else: + xbmc.send_notification("Error", "No remotes were found.", bticon) + print "Could not find BD Remote Control. Trying again..." + time.sleep(2) + return (remote,target_address) + + +def usage(): + print """ +PS3 Blu-Ray Remote Control Client for XBMC v0.1 + +Usage: ps3_remote.py <address> [port] + + address => address of system that XBMC is running on + ("localhost" if it is this machine) + + port => port to send packets to + (default 9777) +""" + +def process_keys(remote, xbmc): + """ + Return codes: + 0 - key was processed normally + 2 - socket read timeout + 3 - PS and then Skip Plus was pressed (sequentially) + 4 - PS and then Skip Minus was pressed (sequentially) + + FIXME: move to enums + """ + done = 0 + + try: + xbmc.previous_key + except: + xbmc.previous_key = "" + + xbmc.connect() + datalen = 0 + try: + data = remote.recv(1024) + datalen = len(data) + except Exception, e: + if str(e)=="timed out": + return 2 + time.sleep(2) + + # some other read exception occured, so raise it + raise e + + if datalen == 13: + keycode = data.encode("hex")[10:12] + if keycode == "ff": + xbmc.release_button() + return done + try: + # if the user presses the PS button followed by skip + or skip - + # return different codes. + if xbmc.previous_key == "43": + xbmc.previous_key = keycode + if keycode == "31": # skip + + return 3 + elif keycode == "30": # skip - + return 4 + + # save previous key press + xbmc.previous_key = keycode + + if g_keymap[keycode]: + xbmc.send_remote_button(g_keymap[keycode]) + except Exception, e: + print "Unknown data: %s" % str(e) + return done + +def main(): + global xbmc, bticon + + host = "127.0.0.1" + port = 9777 + + if len(sys.argv)>1: + try: + host = sys.argv[1] + port = sys.argv[2] + except: + pass + else: + return usage() + + loop_forever = True + xbmc = XBMCClient("PS3 Bluetooth Remote", + icon_file=bticon) + + while loop_forever is True: + target_connected = False + remote = bt_create_socket() + xbmc.connect(host, port) + (remote,target_address) = get_remote_address(remote) + while True: + if process_keys(remote, xbmc): + break + print "Disconnected." + try: + remote.close() + except: + print "Cannot close." + +if __name__=="__main__": + main() diff --git a/tools/EventClients/Clients/PS3 Sixaxis Controller/ps3d.py b/tools/EventClients/Clients/PS3 Sixaxis Controller/ps3d.py new file mode 100755 index 0000000000..b28f9ba9da --- /dev/null +++ b/tools/EventClients/Clients/PS3 Sixaxis Controller/ps3d.py @@ -0,0 +1,433 @@ +#!/usr/bin/python + +import sys +import traceback +import time +import struct +import threading + +sys.path.append("../PS3 BD Remote") + +try: + # try loading modules from source directory + sys.path.append("../../lib/python") + from bt.hid import HID + from bt.bt import bt_lookup_name + from xbmcclient import XBMCClient + from ps3 import sixaxis + from ps3.keymaps import keymap_sixaxis + from ps3_remote import process_keys as process_remote + try: + import zeroconf + except: + zeroconf = None + ICON_PATH = "../../icons/" +except: + # fallback to system wide modules + from xbmc.bt.hid import HID + from xbmc.bt.bt import bt_lookup_name + from xbmc.xbmcclient import XBMCClient + from xbmc.ps3 import sixaxis + from xbmc.ps3.keymaps import keymap_sixaxis + from xbmc.ps3_remote import process_keys as process_remote + from xbmc.defs import * + try: + import xbmc.zeroconf as zeroconf + except: + zeroconf = None + + +event_threads = [] + +def printerr(): + trace = "" + exception = "" + exc_list = traceback.format_exception_only (sys.exc_type, sys.exc_value) + for entry in exc_list: + exception += entry + tb_list = traceback.format_tb(sys.exc_info()[2]) + for entry in tb_list: + trace += entry + print("%s\n%s" % (exception, trace), "Script Error") + + +class StoppableThread ( threading.Thread ): + def __init__(self): + threading.Thread.__init__(self) + self._stop = False + self.set_timeout(0) + + def stop_thread(self): + self._stop = True + + def stop(self): + return self._stop + + def close_sockets(self): + if self.isock: + try: + self.isock.close() + except: + pass + self.isock = None + if self.csock: + try: + self.csock.close() + except: + pass + self.csock = None + self.last_action = 0 + + def set_timeout(self, seconds): + self.timeout = seconds + + def reset_timeout(self): + self.last_action = time.time() + + def idle_time(self): + return time.time() - self.last_action + + def timed_out(self): + if (time.time() - self.last_action) > self.timeout: + return True + else: + return False + +# to make sure all combination keys are checked first +# we sort the keymap's button codes in reverse order +# this guranties that any bit combined button code +# will be processed first +keymap_sixaxis_keys = keymap_sixaxis.keys() +keymap_sixaxis_keys.sort() +keymap_sixaxis_keys.reverse() + +def getkeys(bflags): + keys = []; + for k in keymap_sixaxis_keys: + if (k & bflags) == k: + keys.append(k) + bflags = bflags & ~k + return keys; + +class PS3SixaxisThread ( StoppableThread ): + def __init__(self, csock, isock, ipaddr="127.0.0.1"): + StoppableThread.__init__(self) + self.csock = csock + self.isock = isock + self.xbmc = XBMCClient(name="PS3 Sixaxis", icon_file=ICON_PATH + "/bluetooth.png", ip=ipaddr) + self.set_timeout(600) + + def run(self): + sixaxis.initialize(self.csock, self.isock) + self.xbmc.connect() + bflags = 0 + released = set() + pressed = set() + pending = set() + held = set() + psflags = 0 + psdown = 0 + toggle_mouse = 0 + self.reset_timeout() + try: + while not self.stop(): + if self.timed_out(): + + for key in (held | pressed): + (mapname, action, amount, axis) = keymap_sixaxis[key] + self.xbmc.send_button_state(map=mapname, button=action, amount=0, down=0, axis=axis) + + raise Exception("PS3 Sixaxis powering off, timed out") + if self.idle_time() > 50: + self.xbmc.connect() + try: + data = sixaxis.read_input(self.isock) + except Exception, e: + print str(e) + break + if not data: + continue + + (bflags, psflags, pressure) = sixaxis.process_input(data, self.xbmc, toggle_mouse) + + if psflags: + self.reset_timeout() + if psdown: + if (time.time() - psdown) > 5: + + for key in (held | pressed): + (mapname, action, amount, axis) = keymap_sixaxis[key] + self.xbmc.send_button_state(map=mapname, button=action, amount=0, down=0, axis=axis) + + raise Exception("PS3 Sixaxis powering off, user request") + else: + psdown = time.time() + else: + if psdown: + toggle_mouse = 1 - toggle_mouse + psdown = 0 + + keys = set(getkeys(bflags)) + released = (pressed | held) - keys + held = (pressed | held) - released + pressed = (keys - held) & pending + pending = (keys - held) + + for key in released: + (mapname, action, amount, axis) = keymap_sixaxis[key] + self.xbmc.send_button_state(map=mapname, button=action, amount=0, down=0, axis=axis) + + for key in held: + (mapname, action, amount, axis) = keymap_sixaxis[key] + if amount > 0: + amount = pressure[amount-1] * 256 + self.xbmc.send_button_state(map=mapname, button=action, amount=amount, down=1, axis=axis) + + for key in pressed: + (mapname, action, amount, axis) = keymap_sixaxis[key] + if amount > 0: + amount = pressure[amount-1] * 256 + self.xbmc.send_button_state(map=mapname, button=action, amount=amount, down=1, axis=axis) + + if keys: + self.reset_timeout() + + + except Exception, e: + printerr() + self.close_sockets() + + +class PS3RemoteThread ( StoppableThread ): + def __init__(self, csock, isock, ipaddr="127.0.0.1"): + StoppableThread.__init__(self) + self.csock = csock + self.isock = isock + self.xbmc = XBMCClient(name="PS3 Blu-Ray Remote", icon_file=ICON_PATH + "/bluetooth.png", ip=ipaddr) + self.set_timeout(600) + self.services = [] + self.current_xbmc = 0 + + def run(self): + sixaxis.initialize(self.csock, self.isock) + self.xbmc.connect() + try: + # start the zeroconf thread if possible + try: + self.zeroconf_thread = ZeroconfThread() + self.zeroconf_thread.add_service('_xbmc-events._udp', + self.zeroconf_service_handler) + self.zeroconf_thread.start() + except Exception, e: + print str(e) + + # main thread loop + while not self.stop(): + status = process_remote(self.isock, self.xbmc) + + if status == 2: # 2 = socket read timeout + if self.timed_out(): + raise Exception("PS3 Blu-Ray Remote powering off, "\ + "timed out") + elif status == 3: # 3 = ps and skip + + self.next_xbmc() + + elif status == 4: # 4 = ps and skip - + self.previous_xbmc() + + elif not status: # 0 = keys are normally processed + self.reset_timeout() + + # process_remote() will raise an exception on read errors + except Exception, e: + print str(e) + + self.zeroconf_thread.stop() + self.close_sockets() + + def next_xbmc(self): + """ + Connect to the next XBMC instance + """ + self.current_xbmc = (self.current_xbmc + 1) % len( self.services ) + self.reconnect() + return + + def previous_xbmc(self): + """ + Connect to the previous XBMC instance + """ + self.current_xbmc -= 1 + if self.current_xbmc < 0 : + self.current_xbmc = len( self.services ) - 1 + self.reconnect() + return + + def reconnect(self): + """ + Reconnect to an XBMC instance based on self.current_xbmc + """ + try: + service = self.services[ self.current_xbmc ] + print "Connecting to %s" % service['name'] + self.xbmc.connect( service['address'], service['port'] ) + self.xbmc.send_notification("PS3 Blu-Ray Remote", "New Connection", None) + except Exception, e: + print str(e) + + def zeroconf_service_handler(self, event, service): + """ + Zeroconf event handler + """ + if event == zeroconf.SERVICE_FOUND: # new xbmc service detected + self.services.append( service ) + + elif event == zeroconf.SERVICE_LOST: # xbmc service lost + try: + # search for the service by name, since IP+port isn't available + for s in self.services: + # nuke it, if found + if service['name'] == s['name']: + self.services.remove(s) + break + except: + pass + return + + +class ZeroconfThread ( threading.Thread ): + """ + + """ + def __init__(self): + threading.Thread.__init__(self) + self._zbrowser = None + self._services = [] + + def run(self): + if zeroconf: + # create zeroconf service browser + self._zbrowser = zeroconf.Browser() + + # add the requested services + for service in self._services: + self._zbrowser.add_service( service[0], service[1] ) + + # run the event loop + self._zbrowser.run() + + return + + + def stop(self): + """ + Stop the zeroconf browser + """ + try: + self._zbrowser.stop() + except: + pass + return + + def add_service(self, type, handler): + """ + Add a new service to search for. + NOTE: Services must be added before thread starts. + """ + self._services.append( [ type, handler ] ) + + +def usage(): + print """ +PS3 Sixaxis / Blu-Ray Remote HID Server v0.1 + +Usage: ps3.py [bdaddress] [XBMC host] + + bdaddress => address of local bluetooth device to use (default: auto) + (e.g. aa:bb:cc:dd:ee:ff) + ip address => IP address or hostname of the XBMC instance (default: localhost) + (e.g. 192.168.1.110) +""" + +def start_hidd(bdaddr=None, ipaddr="127.0.0.1"): + devices = [ 'PLAYSTATION(R)3 Controller', + 'BD Remote Control' ] + hid = HID(bdaddr) + while True: + if hid.listen(): + (csock, addr) = hid.get_control_socket() + device_name = bt_lookup_name(addr[0]) + if device_name == devices[0]: + # handle PS3 controller + handle_ps3_controller(hid, ipaddr) + elif device_name == devices[1]: + # handle the PS3 remote + handle_ps3_remote(hid, ipaddr) + else: + print "Unknown Device: %s" % (device_name) + +def handle_ps3_controller(hid, ipaddr): + print "Received connection from a Sixaxis PS3 Controller" + csock = hid.get_control_socket()[0] + isock = hid.get_interrupt_socket()[0] + sixaxis = PS3SixaxisThread(csock, isock, ipaddr) + add_thread(sixaxis) + sixaxis.start() + return + +def handle_ps3_remote(hid, ipaddr): + print "Received connection from a PS3 Blu-Ray Remote" + csock = hid.get_control_socket()[0] + isock = hid.get_interrupt_socket()[0] + isock.settimeout(1) + remote = PS3RemoteThread(csock, isock, ipaddr) + add_thread(remote) + remote.start() + return + +def add_thread(thread): + global event_threads + event_threads.append(thread) + +def main(): + if len(sys.argv)>3: + return usage() + bdaddr = "" + ipaddr = "127.0.0.1" + try: + for addr in sys.argv[1:]: + try: + # ensure that the addr is of the format 'aa:bb:cc:dd:ee:ff' + if "".join([ str(len(a)) for a in addr.split(":") ]) != "222222": + raise Exception("Invalid format") + bdaddr = addr + print "Connecting to Bluetooth device: %s" % bdaddr + except Exception, e: + try: + ipaddr = addr + print "Connecting to : %s" % ipaddr + except: + print str(e) + return usage() + except Exception, e: + pass + + print "Starting HID daemon" + start_hidd(bdaddr, ipaddr) + +if __name__=="__main__": + try: + main() + finally: + for t in event_threads: + try: + print "Waiting for thread "+str(t)+" to terminate" + t.stop_thread() + if t.isAlive(): + t.join() + print "Thread "+str(t)+" terminated" + + except Exception, e: + print str(e) + pass + diff --git a/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.cpp b/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.cpp new file mode 100644 index 0000000000..08ba318f86 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.cpp @@ -0,0 +1,774 @@ +/*************************************************************************** + * Copyright (C) 2007 by Tobias Arrskog,,, * + * topfs@tobias * + * * + * 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +// Compiles with g++ WiiRemote.cpp -lcwiid -o WiiRemote +// Preferably with libcwiid >= 6.0 + +#include "CWIID_WiiRemote.h" + + +bool g_AllowReconnect = true; +bool g_AllowMouse = true; +bool g_AllowNunchuck = true; + +CPacketHELO *g_Ping = NULL; + +#ifndef ICON_PATH +#define ICON_PATH "../../" +#endif +std::string g_BluetoothIconPath = std::string(ICON_PATH) + std::string("/bluetooth.png"); + +long getTicks() +{ + long ticks; + struct timeval now; + gettimeofday(&now, NULL); + ticks = now.tv_sec * 1000l; + ticks += now.tv_usec / 1000l; + return ticks; +} + +CWiiRemote g_WiiRemote; + +#ifdef CWIID_OLD +void CWiiRemote::MessageCallback(cwiid_wiimote_t *wiiremote, int mesg_count, union cwiid_mesg mesg[]) +{ + MessageCallback(wiiremote, mesg_count, mesg, NULL); +} +#endif + +/* The MessageCallback for the Wiiremote. + This callback is used for error reports, mainly to see if the connection has been broken + This callback is also used for getting the IR sources, if this is done in update as with buttons we usually only get 1 IR source at a time wich is much harder to calculate */ +void CWiiRemote::MessageCallback(cwiid_wiimote_t *wiiremote, int mesg_count, union cwiid_mesg mesg[], struct timespec *timestamp) +{ + for (int i=0; i < mesg_count; i++) + { + int valid_source; + switch (mesg[i].type) + { + case CWIID_MESG_IR: + valid_source = 0; + for (int j = 0; j < CWIID_IR_SRC_COUNT; j++) + { + if (mesg[i].ir_mesg.src[j].valid) + valid_source++; + } + if (valid_source == 2) + { + g_WiiRemote.CalculateMousePointer(mesg[i].ir_mesg.src[0].pos[CWIID_X], + mesg[i].ir_mesg.src[0].pos[CWIID_Y], + mesg[i].ir_mesg.src[1].pos[CWIID_X], + mesg[i].ir_mesg.src[1].pos[CWIID_Y]); + } + else if (valid_source > 2) + { //TODO Make this care with the strenght of the sources + g_WiiRemote.CalculateMousePointer(mesg[i].ir_mesg.src[0].pos[CWIID_X], + mesg[i].ir_mesg.src[0].pos[CWIID_Y], + mesg[i].ir_mesg.src[1].pos[CWIID_X], + mesg[i].ir_mesg.src[1].pos[CWIID_Y]); + } + break; + case CWIID_MESG_ERROR: + g_WiiRemote.DisconnectNow(true); + break; + case CWIID_MESG_BTN: + g_WiiRemote.ProcessKey(mesg[i].btn_mesg.buttons); + break; + case CWIID_MESG_STATUS: + //Here we can figure out Extensiontypes and such + break; + case CWIID_MESG_NUNCHUK: + g_WiiRemote.ProcessNunchuck(mesg[i].nunchuk_mesg); + break; + case CWIID_MESG_CLASSIC: + //Not implemented + break; + case CWIID_MESG_ACC: + //Not implemented + break; + case CWIID_MESG_UNKNOWN: + //... + break; + } + } +#ifdef CWIID_OLD + g_WiiRemote.CheckIn(); +#endif +} + +#ifndef _DEBUG +/* This takes the errors generated at pre-connect and silence them as they are mostly not needed */ +void CWiiRemote::ErrorCallback(struct wiimote *wiiremote, const char *str, va_list ap) +{ + //Error checking +} +#endif + +//Constructor +/*This constructor is never used but it shows how one would connect to just a specific Wiiremote by Mac-Adress*/ +CWiiRemote::CWiiRemote(char *wii_btaddr) +{ + SetBluetoothAddress(wii_btaddr); + m_SamplesX = NULL; + m_SamplesY = NULL; + + m_JoyMap = NULL; +} + +//Destructor +CWiiRemote::~CWiiRemote() +{ + if (m_connected == true) + this->DisconnectNow(false); + + if (m_SamplesY != NULL) + free(m_SamplesY); + if (m_SamplesX != NULL) + free(m_SamplesX); + + if (m_JoyMap) + free(m_JoyMap); +} + +//---------------------Public------------------------------------------------------------------- +/* Basicly this just sets up standard control bits */ +void CWiiRemote::SetBluetoothAddress(const char *btaddr) +{ + if (btaddr != NULL) + str2ba(btaddr, &m_btaddr); + else + bacpy(&m_btaddr, &(*BDADDR_ANY)); +} + +void CWiiRemote::SetSensativity(float DeadX, float DeadY, int NumSamples) +{ + m_NumSamples = NumSamples; + + m_MinX = MOUSE_MAX * DeadX; + m_MinY = MOUSE_MAX * DeadY; + + m_MaxX = MOUSE_MAX * (1.0f + DeadX + DeadX); + m_MaxY = MOUSE_MAX * (1.0f + DeadY + DeadY); + + if (m_SamplesY != NULL) + delete [] m_SamplesY; + if (m_SamplesX != NULL) + delete [] m_SamplesX; + + m_SamplesY = new int[m_NumSamples]; + m_SamplesX = new int[m_NumSamples]; +} + +void CWiiRemote::SetJoystickMap(const char *JoyMap) +{ + if (m_JoyMap) + free(m_JoyMap); + if (JoyMap != NULL) + { + m_JoyMap = new char[strlen(JoyMap) + 4]; + sprintf(m_JoyMap, "JS0:%s", JoyMap); + } + else + { + m_JoyMap = new char[strlen("JS0:WiiRemote")]; + strcpy(m_JoyMap, "JS0:WiiRemote"); + } +} + +void CWiiRemote::Initialize(CAddress Addr, int Socket) +{ + m_connected = false; + m_lastKeyPressed = 0; + m_LastKey = 0; + m_buttonRepeat = false; + m_lastKeyPressedNunchuck = 0; + m_LastKeyNunchuck = 0; + m_buttonRepeatNunchuck = false; + m_useIRMouse = true; + m_rptMode = 0; + + m_Socket = Socket; + m_MyAddr = Addr; + + m_NumSamples = WIIREMOTE_SAMPLES; + + m_MaxX = WIIREMOTE_X_MAX; + m_MaxY = WIIREMOTE_Y_MAX; + m_MinX = WIIREMOTE_X_MIN; + m_MinY = WIIREMOTE_Y_MIN; +#ifdef CWIID_OLD + m_LastMsgTime = getTicks(); +#endif + + //All control bits are set to false when cwiid is started + //Report Button presses + ToggleBit(m_rptMode, CWIID_RPT_BTN); + if (g_AllowNunchuck) + ToggleBit(m_rptMode, CWIID_RPT_NUNCHUK); + + //If wiiremote is used as a mouse, then report the IR sources +#ifndef CWIID_OLD + if (m_useIRMouse) +#endif + ToggleBit(m_rptMode, CWIID_RPT_IR); + + //Have the first and fourth LED on the Wiiremote shine when connected + ToggleBit(m_ledState, CWIID_LED1_ON); + ToggleBit(m_ledState, CWIID_LED4_ON); +} + +/* Update is run regulary and we gather the state of the Wiiremote and see if the user have pressed on a button or moved the wiiremote + This could have been done with callbacks instead but it doesn't look nice in C++*/ +void CWiiRemote::Update() +{ + if (m_DisconnectWhenPossible) + {//If the user have choosen to disconnect or lost comunication + DisconnectNow(true); + m_DisconnectWhenPossible = false; + } +#ifdef CWIID_OLD + if(m_connected) + {//Here we check if the connection is suddenly broken + if (!CheckConnection()) + { + DisconnectNow(true); + return; + } + } +#endif +} + +/* Enable mouse emulation */ +void CWiiRemote::EnableMouseEmulation() +{ + if (m_useIRMouse) + return; + + m_useIRMouse = true; + +#ifndef CWIID_OLD + //We toggle IR Reporting (Save resources?) + if (!(m_rptMode & CWIID_RPT_IR)) + ToggleBit(m_rptMode, CWIID_RPT_IR); + if (m_connected) + SetRptMode(); +#endif + + CPacketLOG log(LOGDEBUG, "Enabled WiiRemote mouse emulation"); + log.Send(m_Socket, m_MyAddr); +} +/* Disable mouse emulation */ +void CWiiRemote::DisableMouseEmulation() +{ + if (!m_useIRMouse) + return; + + m_useIRMouse = false; +#ifndef CWIID_OLD + //We toggle IR Reporting (Save resources?) + if (m_rptMode & CWIID_RPT_IR) + ToggleBit(m_rptMode, CWIID_RPT_IR); + if (m_connected) + SetRptMode(); +#endif + + CPacketLOG log(LOGDEBUG, "Disabled WiiRemote mouse emulation"); + log.Send(m_Socket, m_MyAddr); +} + +/* Is a wiiremote connected*/ +bool CWiiRemote::GetConnected() +{ + return m_connected; +} + +/* Disconnect ASAP*/ +void CWiiRemote::Disconnect() +{ //This is always called from a criticalsection + if (m_connected) + m_DisconnectWhenPossible = true; +} + +#ifdef CWIID_OLD +/* This function is mostly a hack as CWIID < 6.0 doesn't report on disconnects, this function is called everytime + a message is sent to the callback (Will be once every 10 ms or so) this is to see if the connection is interupted. */ +void CWiiRemote::CheckIn() +{ //This is always called from a criticalsection + m_LastMsgTime = getTicks(); +} +#endif + +//---------------------Private------------------------------------------------------------------- +/* Connect is designed to be run in a different thread as it only + exits if wiiremote is either disabled or a connection is made*/ +bool CWiiRemote::Connect() +{ +#ifndef _DEBUG + cwiid_set_err(ErrorCallback); +#endif + while (!m_connected) + { + g_Ping->Send(m_Socket, m_MyAddr); + int flags = 0; + ToggleBit(flags, CWIID_FLAG_MESG_IFC); + ToggleBit(flags, CWIID_FLAG_REPEAT_BTN); + + m_wiiremoteHandle = cwiid_connect(&m_btaddr, flags); + if (m_wiiremoteHandle != NULL) + { + SetupWiiRemote(); + // get battery state etc. + cwiid_state wiiremote_state; + int err = cwiid_get_state(m_wiiremoteHandle, &wiiremote_state); + if (!err) + { + char Mesg[1024]; + sprintf(Mesg, "%i%% battery remaining", static_cast<int>(((float)(wiiremote_state.battery)/CWIID_BATTERY_MAX)*100.0)); + CPacketNOTIFICATION notification("Wii Remote connected", Mesg, ICON_PNG, g_BluetoothIconPath.c_str()); + notification.Send(m_Socket, m_MyAddr); + } + else + { + printf("Problem probing for status of WiiRemote; cwiid_get_state returned non-zero\n"); + CPacketLOG log(LOGNOTICE, "Problem probing for status of WiiRemote; cwiid_get_state returned non-zero"); + log.Send(m_Socket, m_MyAddr); + CPacketNOTIFICATION notification("Wii Remote connected", "", ICON_PNG, g_BluetoothIconPath.c_str()); + notification.Send(m_Socket, m_MyAddr); + } +#ifdef CWIID_OLD + /* CheckIn to say that this is the last msg, If this isn't called it could give issues if we Connects -> Disconnect and then try to connect again + the CWIID_OLD hack would automaticly disconnect the wiiremote as the lastmsg is too old. */ + CheckIn(); +#endif + m_connected = true; + + CPacketLOG log(LOGNOTICE, "Sucessfully connected a WiiRemote"); + log.Send(m_Socket, m_MyAddr); + return true; + } + //Here's a good place to have a quit flag check... + + } + return false; +} + +/* Disconnect */ +void CWiiRemote::DisconnectNow(bool startConnectThread) +{ + if (m_connected) //It shouldn't be enabled at the same time as it is connected + { + cwiid_disconnect(m_wiiremoteHandle); + + if (g_AllowReconnect) + { + CPacketNOTIFICATION notification("Wii Remote disconnected", "Press 1 and 2 to reconnect", ICON_PNG, g_BluetoothIconPath.c_str()); + notification.Send(m_Socket, m_MyAddr); + } + else + { + CPacketNOTIFICATION notification("Wii Remote disconnected", "", ICON_PNG, g_BluetoothIconPath.c_str()); + notification.Send(m_Socket, m_MyAddr); + } + + CPacketLOG log(LOGNOTICE, "Sucessfully disconnected a WiiRemote"); + log.Send(m_Socket, m_MyAddr); + } + m_connected = false; +} + +#ifdef CWIID_OLD +/* This is a harsh check if there really is a connection, It will mainly be used in CWIID < 6.0 + as it doesn't report connect error, wich is needed to see if the Wiiremote suddenly disconnected. + This could possible be done with bluetooth specific queries but I cannot find how to do it. */ +bool CWiiRemote::CheckConnection() +{ + if ((getTicks() - m_LastMsgTime) > 1000) + { + CPacketLOG log(LOGNOTICE, "Lost connection to the WiiRemote"); + log.Send(m_Socket, m_MyAddr); + return false; + } + else + return true; +} +#endif + +/* Sets rpt mode when a new wiiremote is connected */ +void CWiiRemote::SetupWiiRemote() +{ //Lights up the apropriate led and setups the rapport mode, so buttons and IR work + SetRptMode(); + SetLedState(); + + for (int i = 0; i < WIIREMOTE_SAMPLES; i++) + { + m_SamplesX[i] = 0; + m_SamplesY[i] = 0; + } + + if (cwiid_set_mesg_callback(m_wiiremoteHandle, MessageCallback)) + { + CPacketLOG log(LOGERROR, "Unable to set message callback to the WiiRemote"); + log.Send(m_Socket, m_MyAddr); + } +} + +void CWiiRemote::ProcessKey(int Key) +{ + if (Key != m_LastKey) + { + m_LastKey = Key; + m_lastKeyPressed = getTicks(); + m_buttonRepeat = false; + } + else + { + if (m_buttonRepeat) + { + if (getTicks() - m_lastKeyPressed > WIIREMOTE_BUTTON_REPEAT_TIME) + m_lastKeyPressed = getTicks(); + else + return; + } + else + { + if (getTicks() - m_lastKeyPressed > WIIREMOTE_BUTTON_DELAY_TIME) + { + m_buttonRepeat = true; + m_lastKeyPressed = getTicks(); + } + else + return; + } + } + + int RtnKey = -1; + + if (Key == CWIID_BTN_UP) + RtnKey = 1; + else if (Key == CWIID_BTN_RIGHT) + RtnKey = 4; + else if (Key == CWIID_BTN_LEFT) + RtnKey = 3; + else if (Key == CWIID_BTN_DOWN) + RtnKey = 2; + + else if (Key == CWIID_BTN_A) + RtnKey = 5; + else if (Key == CWIID_BTN_B) + RtnKey = 6; + + else if (Key == CWIID_BTN_MINUS) + RtnKey = 7; + else if (Key == CWIID_BTN_PLUS) + RtnKey = 9; + + else if (Key == CWIID_BTN_HOME) + RtnKey = 8; + + else if (Key == CWIID_BTN_1) + RtnKey = 10; + else if (Key == CWIID_BTN_2) + RtnKey = 11; + + if (RtnKey != -1) + { + CPacketBUTTON btn(RtnKey, m_JoyMap, BTN_QUEUE | BTN_NO_REPEAT); + btn.Send(m_Socket, m_MyAddr); + } +} + +void CWiiRemote::ProcessNunchuck(struct cwiid_nunchuk_mesg &Nunchuck) +{ + if (Nunchuck.stick[0] > 135) + { //R + int x = (int)((((float)Nunchuck.stick[0] - 135.0f) / 95.0f) * 65535.0f); + printf("Right: %i\n", x); + CPacketBUTTON btn(24, m_JoyMap, (BTN_QUEUE | BTN_DOWN), x); + btn.Send(m_Socket, m_MyAddr); + } + else if (Nunchuck.stick[0] < 125) + { //L + int x = (int)((((float)Nunchuck.stick[0] - 125.0f) / 90.0f) * -65535.0f); + printf("Left: %i\n", x); + CPacketBUTTON btn(23, m_JoyMap, (BTN_QUEUE | BTN_DOWN), x); + btn.Send(m_Socket, m_MyAddr); + } + + if (Nunchuck.stick[1] > 130) + { //U + int x = (int)((((float)Nunchuck.stick[1] - 130.0f) / 92.0f) * 65535.0f); + printf("Up: %i\n", x); + CPacketBUTTON btn(21, m_JoyMap, (BTN_QUEUE | BTN_DOWN), x); + btn.Send(m_Socket, m_MyAddr); + } + else if (Nunchuck.stick[1] < 120) + { //D + int x = (int)((((float)Nunchuck.stick[1] - 120.0f) / 90.0f) * -65535.0f); + printf("Down: %i\n", x); + CPacketBUTTON btn(22, m_JoyMap, (BTN_QUEUE | BTN_DOWN), x); + btn.Send(m_Socket, m_MyAddr); + } + + if (Nunchuck.buttons != m_LastKeyNunchuck) + { + m_LastKeyNunchuck = Nunchuck.buttons; + m_lastKeyPressedNunchuck = getTicks(); + m_buttonRepeatNunchuck = false; + } + else + { + if (m_buttonRepeatNunchuck) + { + if (getTicks() - m_lastKeyPressedNunchuck > WIIREMOTE_BUTTON_REPEAT_TIME) + m_lastKeyPressedNunchuck = getTicks(); + else + return; + } + else + { + if (getTicks() - m_lastKeyPressedNunchuck > WIIREMOTE_BUTTON_DELAY_TIME) + { + m_buttonRepeatNunchuck = true; + m_lastKeyPressedNunchuck = getTicks(); + } + else + return; + } + } + + int RtnKey = -1; + + if (Nunchuck.buttons == CWIID_NUNCHUK_BTN_C) + RtnKey = 25; + else if (Nunchuck.buttons == CWIID_NUNCHUK_BTN_Z) + RtnKey = 26; + + if (RtnKey != -1) + { + CPacketBUTTON btn(RtnKey, m_JoyMap, BTN_QUEUE | BTN_NO_REPEAT); + btn.Send(m_Socket, m_MyAddr); + } +} + +/* Tell cwiid wich data will be reported */ +void CWiiRemote::SetRptMode() +{ //Sets our wiiremote to report something, for example IR, Buttons +#ifdef CWIID_OLD + if (cwiid_command(m_wiiremoteHandle, CWIID_CMD_RPT_MODE, m_rptMode)) +#else + if (cwiid_set_rpt_mode(m_wiiremoteHandle, m_rptMode)) +#endif + { + CPacketLOG log(LOGERROR, "Error setting WiiRemote report mode"); + log.Send(m_Socket, m_MyAddr); + } +} +/* Tell cwiid the LED states */ +void CWiiRemote::SetLedState() +{ //Sets our leds on the wiiremote +#ifdef CWIID_OLD + if (cwiid_command(m_wiiremoteHandle, CWIID_CMD_LED, m_ledState)) +#else + if (cwiid_set_led(m_wiiremoteHandle, m_ledState)) +#endif + { + CPacketLOG log(LOGERROR, "Error setting WiiRemote LED state"); + log.Send(m_Socket, m_MyAddr); + } +} + +/* Calculate the mousepointer from 2 IR sources (Default) */ +void CWiiRemote::CalculateMousePointer(int x1, int y1, int x2, int y2) +{ + int x3, y3; + + x3 = ( (x1 + x2) / 2 ); + y3 = ( (y1 + y2) / 2 ); + + x3 = (int)( ((float)x3 / (float)CWIID_IR_X_MAX) * m_MaxX); + y3 = (int)( ((float)y3 / (float)CWIID_IR_Y_MAX) * m_MaxY); + + x3 = (int)(x3 - m_MinX); + y3 = (int)(y3 - m_MinY); + + if (x3 < MOUSE_MIN) x3 = MOUSE_MIN; + else if (x3 > MOUSE_MAX) x3 = MOUSE_MAX; + + if (y3 < MOUSE_MIN) y3 = MOUSE_MIN; + else if (y3 > MOUSE_MAX) y3 = MOUSE_MAX; + + x3 = MOUSE_MAX - x3; + + if (m_NumSamples == 1) + { + CPacketMOUSE mouse(x3, y3); + mouse.Send(m_Socket, m_MyAddr); + return; + } + else + { + for (int i = m_NumSamples; i > 0; i--) + { + m_SamplesX[i] = m_SamplesX[i-1]; + m_SamplesY[i] = m_SamplesY[i-1]; + } + + m_SamplesX[0] = x3; + m_SamplesY[0] = y3; + + long x4 = 0, y4 = 0; + + for (int i = 0; i < m_NumSamples; i++) + { + x4 += m_SamplesX[i]; + y4 += m_SamplesY[i]; + } + CPacketMOUSE mouse((x4 / m_NumSamples), (y4 / m_NumSamples)); + mouse.Send(m_Socket, m_MyAddr); + } +} + + + + + + + + + + + + + + + + +void PrintHelp(const char *Prog) +{ + printf("Commands:\n"); + printf("\t--disable-mouseemulation\n\t--disable-reconnect\n\t--disable-nunchuck\n"); + printf("\t--address ADDRESS\n\t--port PORT\n"); + printf("\t--btaddr MACADDRESS\n"); + printf("\t--deadzone-x DEADX | Number between 0 - 100 (Default: %i)\n", (int)(DEADZONE_X * 100)); + printf("\t--deadzone-y DEADY | Number between 0 - 100 (Default: %i)\n", (int)(DEADZONE_Y * 100)); + printf("\t--deadzone DEAD | Sets both X and Y too the number\n"); + printf("\t--smoothing-samples SAMPLE | Number 1 counts as Off (Default: %i)\n", WIIREMOTE_SAMPLES); + printf("\t--joystick-map JOYMAP | The string ID for the joymap (Default: WiiRemote)\n"); +} + +int main(int argc, char **argv) +{ + char *Address = NULL; + char *btaddr = NULL; + int Port = 9777; + + int NumSamples = WIIREMOTE_SAMPLES; + float DeadX = DEADZONE_X; + float DeadY = DEADZONE_Y; + + char *JoyMap = NULL; + + for (int i = 0; i < argc; i++) + { + if (strcmp(argv[i], "--help") == 0) + { + PrintHelp(argv[0]); + return 0; + } + else if (strcmp(argv[i], "--disable-mouseemulation") == 0) + g_AllowMouse = false; + else if (strcmp(argv[i], "--disable-reconnect") == 0) + g_AllowReconnect = false; + else if (strcmp(argv[i], "--disable-nunchuck") == 0) + g_AllowNunchuck = false; + else if (strcmp(argv[i], "--address") == 0 && ((i + 1) <= argc)) + Address = argv[i + 1]; + else if (strcmp(argv[i], "--port") == 0 && ((i + 1) <= argc)) + Port = atoi(argv[i + 1]); + else if (strcmp(argv[i], "--btaddr") == 0 && ((i + 1) <= argc)) + btaddr = argv[i + 1]; + else if (strcmp(argv[i], "--deadzone-x") == 0 && ((i + 1) <= argc)) + DeadX = ((float)atoi(argv[i + 1]) / 100.0f); + else if (strcmp(argv[i], "--deadzone-y") == 0 && ((i + 1) <= argc)) + DeadY = ((float)atoi(argv[i + 1]) / 100.0f); + else if (strcmp(argv[i], "--deadzone") == 0 && ((i + 1) <= argc)) + DeadX = DeadY = ((float)atoi(argv[i + 1]) / 100.0f); + else if (strcmp(argv[i], "--smoothing-samples") == 0 && ((i + 1) <= argc)) + NumSamples = atoi(argv[i + 1]); + else if (strcmp(argv[i], "--joystick-map") == 0 && ((i + 1) <= argc)) + JoyMap = argv[i + 1]; + } + + if (NumSamples < 1 || DeadX < 0 || DeadY < 0 || DeadX > 1 || DeadY > 1) + { + PrintHelp(argv[0]); + return -1; + } + + CAddress my_addr(Address, Port); // Address => localhost on 9777 + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + printf("Error creating socket\n"); + return -1; + } + + if (hci_get_route(NULL) < 0) + { + CPacketLOG log(LOGERROR, "Error No bluetooth device"); + log.Send(sockfd, my_addr); + return -1; + } + g_Ping = new CPacketHELO("WiiRemote", ICON_PNG, g_BluetoothIconPath.c_str()); + g_WiiRemote.Initialize(my_addr, sockfd); + g_WiiRemote.SetBluetoothAddress(btaddr); + g_WiiRemote.SetSensativity(DeadX, DeadY, NumSamples); + g_WiiRemote.SetSensativity(DeadX, DeadY, NumSamples); + g_WiiRemote.SetJoystickMap(JoyMap); + if (g_AllowMouse) + g_WiiRemote.EnableMouseEmulation(); + else + g_WiiRemote.DisableMouseEmulation(); + + g_Ping->Send(sockfd, my_addr); + bool HaveConnected = false; + while (true) + { + bool Connected = g_WiiRemote.GetConnected(); + + while (!Connected) + { + if (HaveConnected && !g_AllowReconnect) + exit(0); + + Connected = g_WiiRemote.Connect(); + HaveConnected = true; + } +#ifdef CWIID_OLD +// Update the state of the WiiRemote more often when we have the old lib due too it not telling when disconnected.. + sleep (5); +#else + sleep (15); +#endif + g_Ping->Send(sockfd, my_addr); + g_WiiRemote.Update(); + } +} diff --git a/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.h b/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.h new file mode 100644 index 0000000000..87e9010e6f --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.h @@ -0,0 +1,170 @@ +/*************************************************************************** + * Copyright (C) 2007 by Tobias Arrskog,,, * + * topfs@tobias * + * * + * 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef WII_REMOTE_H +#define WII_REMOTE_H + +/* Toggle one bit */ +#define ToggleBit(bf,b) (bf) = ((bf) & b) ? ((bf) & ~(b)) : ((bf) | (b)) + +//Settings +#define WIIREMOTE_SAMPLES 16 + +#define DEADZONE_Y 0.3f +#define DEADZONE_X 0.5f + +#define MOUSE_MAX 65535 +#define MOUSE_MIN 0 + +//The work area is from 0 - MAX but the one sent to XBMC is MIN - (MIN + MOUSE_MAX) +#define WIIREMOTE_X_MIN MOUSE_MAX * DEADZONE_X +#define WIIREMOTE_Y_MIN MOUSE_MAX * DEADZONE_Y + +#define WIIREMOTE_X_MAX MOUSE_MAX * (1.0f + DEADZONE_X + DEADZONE_X) +#define WIIREMOTE_Y_MAX MOUSE_MAX * (1.0f + DEADZONE_Y + DEADZONE_Y) + +#define WIIREMOTE_BUTTON_REPEAT_TIME 30 // How long between buttonpresses in repeat mode +#define WIIREMOTE_BUTTON_DELAY_TIME 500 +//#define CWIID_OLD // Uncomment if the system is running cwiid that is older than 6.0 (The one from ubuntu gutsy repository is < 6.0) + +//CWIID +#include <cwiid.h> +//Bluetooth specific +#include <sys/socket.h> +#include <bluetooth/bluetooth.h> +#include <bluetooth/hci.h> +#include <bluetooth/hci_lib.h> +// UDP Client +#ifdef DEB_PACK +#include <xbmc/xbmcclient.h> +#else +#include "../../lib/c++/xbmcclient.h" +#endif +/*#include <stdio.h>*/ +#include <stdlib.h> +#include <time.h> +#include <sys/time.h> +#include <string> + +class CWiiRemote +{ +public: + CWiiRemote(char *btaddr = NULL); + ~CWiiRemote(); + + void Initialize(CAddress Addr, int Socket); + void Disconnect(); + bool GetConnected(); + + bool EnableWiiRemote(); + bool DisableWiiRemote(); + + void Update(); + + // Mouse functions + bool HaveIRSources(); + bool isActive(); + void EnableMouseEmulation(); + void DisableMouseEmulation(); + + bool Connect(); + + void SetBluetoothAddress(const char * btaddr); + void SetSensativity(float DeadX, float DeadY, int Samples); + void SetJoystickMap(const char *JoyMap); +private: + int m_NumSamples; + int *m_SamplesX; + int *m_SamplesY; + + float m_MaxX; + float m_MaxY; + float m_MinX; + float m_MinY; +#ifdef CWIID_OLD + bool CheckConnection(); + int m_LastMsgTime; +#endif + char *m_JoyMap; + int m_lastKeyPressed; + int m_LastKey; + bool m_buttonRepeat; + + int m_lastKeyPressedNunchuck; + int m_LastKeyNunchuck; + bool m_buttonRepeatNunchuck; + + void SetRptMode(); + void SetLedState(); + + void SetupWiiRemote(); + + bool m_connected; + + bool m_DisconnectWhenPossible; + bool m_connectThreadRunning; + + //CWIID Specific + cwiid_wiimote_t *m_wiiremoteHandle; + unsigned char m_ledState; + unsigned char m_rptMode; + bdaddr_t m_btaddr; + + static void MessageCallback(cwiid_wiimote_t *wiiremote, int mesgCount, union cwiid_mesg mesg[], struct timespec *timestamp); +#ifdef CWIID_OLD + static void MessageCallback(cwiid_wiimote_t *wiiremote, int mesgCount, union cwiid_mesg mesg[]); +#endif + +#ifndef _DEBUG +/* This takes the errors generated at pre-connect and silence them as they are mostly not needed */ + static void ErrorCallback(struct wiimote *wiiremote, const char *str, va_list ap); +#endif + + int m_Socket; + CAddress m_MyAddr; + + // Mouse + bool m_haveIRSources; + bool m_isActive; + bool m_useIRMouse; + int m_lastActiveTime; + +/* The protected functions is for the static callbacks */ + protected: + //Connection + void DisconnectNow(bool startConnectThread); + + //Mouse + void CalculateMousePointer(int x1, int y1, int x2, int y2); +// void SetIR(bool set); + + //Button + void ProcessKey(int Key); + + //Nunchuck + void ProcessNunchuck(struct cwiid_nunchuk_mesg &Nunchuck); +#ifdef CWIID_OLD + //Disconnect check + void CheckIn(); +#endif +}; + +#endif // WII_REMOTE_H + +extern CWiiRemote g_WiiRemote; diff --git a/tools/EventClients/Clients/WiiRemote/Makefile b/tools/EventClients/Clients/WiiRemote/Makefile new file mode 100644 index 0000000000..4ceaa68bbb --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/Makefile @@ -0,0 +1,13 @@ +CFLAGS = -Wall -pipe -fPIC -funroll-loops +OBJ_DIR = release-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2) +OBJS = wiiuse_v0.12/src/$(OBJ_DIR)/libwiiuse.so +BIN = WiiUse_WiiRemote +VERSION = v0.12 + +all: + @$(MAKE) -C wiiuse_$(VERSION)/src $@ + g++ $(CFLAGS) WiiUse_WiiRemote.cpp $(OBJS) -o $(BIN) +wiiuse: + @$(MAKE) -C wiiuse_$(VERSION)/src +clean: + rm $(OBJS) $(BIN) diff --git a/tools/EventClients/Clients/WiiRemote/WiiUse_README b/tools/EventClients/Clients/WiiRemote/WiiUse_README new file mode 100644 index 0000000000..df67c2d7cf --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/WiiUse_README @@ -0,0 +1,18 @@ +There are two ways to make the WiiUse_WiiRemote event client. + +1) Compile manually. Requires the wiiuse library to be installed already (http://sourceforge.net/project/showfiles.php?group_id=187194) +g++ -lwiiuse WiiUse_WiiRemote.cpp -o WiiUse_WiiRemote + +2) Use the Makefile. Will make the wiiuse_v0.12 library from source. Executable must be run from this directory due to relative linking to the built library. +make + +Both methods will create a WiiUse_WiiRemote executable containing the event client. + + +The WiiUse_WiiRemote.h file contains the button number mappings for the Wii Remote (prefixed with KEYCODE). + + +TODO: +Add IR pointer support + +TheUni diff --git a/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.cpp b/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.cpp new file mode 100644 index 0000000000..bae0cf6f49 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.cpp @@ -0,0 +1,264 @@ + /* Copyright (C) 2009 by Cory Fields + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * + */ + +#include "WiiUse_WiiRemote.h" + +void CWiiController::get_keys(wiimote* wm) +{ + m_buttonHeld = 0; + m_buttonPressed = 0; + m_buttonReleased = 0; + + m_repeatableHeld = (wm->btns & (m_repeatFlags)); + m_holdableHeld = (wm->btns & (m_holdFlags)); + m_repeatableReleased = (wm->btns_released & (m_repeatFlags)); + m_holdableReleased = (wm->btns_released & (m_holdFlags)); + + for (int i = 1;i <= WIIMOTE_NUM_BUTTONS; i++) + { + if (IS_PRESSED(wm,convert_code(i))) + m_buttonPressed = i; + if (IS_RELEASED(wm,convert_code(i))) + m_buttonReleased = i; + if (IS_HELD(wm,convert_code(i))) + m_buttonHeld = i; + } +} + +void CWiiController::handleKeyPress() +{ + if ((m_holdableReleased && m_buttonDownTime < g_hold_button_timeout)) + EventClient.SendButton(m_buttonReleased, m_joyString, BTN_QUEUE | BTN_NO_REPEAT); + if (m_buttonPressed && !m_holdableHeld && !m_buttonHeld) + EventClient.SendButton(m_buttonPressed, m_joyString, BTN_QUEUE | BTN_NO_REPEAT); +} + +void CWiiController::handleRepeat() +{ + if (m_repeatableHeld) + EventClient.SendButton(m_buttonPressed, m_joyString, BTN_QUEUE | BTN_NO_REPEAT, 5); +} + +void CWiiController::handleACC(float currentRoll, float currentPitch) +{ + int rollWeight = 0; + int tiltWeight = 0; + + if (m_start_roll == 0) + m_start_roll = currentRoll; + m_abs_roll = smoothDeg(m_abs_roll, currentRoll); + m_rel_roll = m_abs_roll - m_start_roll; + rollWeight = int((m_rel_roll*m_rel_roll)); + if (rollWeight > 65000) + rollWeight = 65000; + + if (m_start_pitch == 0) + m_start_pitch = currentPitch; + m_abs_pitch = smoothDeg(m_abs_pitch, currentPitch); + m_rel_pitch = m_start_pitch - m_abs_pitch; + tiltWeight = int((m_rel_pitch*m_rel_pitch*16)); + if (tiltWeight > 65000) + tiltWeight = 65000; + + if (m_currentAction == ACTION_NONE) + { + if ((g_deadzone - (abs((int)m_rel_roll)) < 5) && (abs((int)m_abs_pitch) < (g_deadzone / 1.5))) + // crossed the roll deadzone threshhold while inside the pitch deadzone + { + m_currentAction = ACTION_ROLL; + } + else if ((g_deadzone - (abs((int)m_rel_pitch)) < 5) && (abs((int)m_abs_roll) < (g_deadzone / 1.5))) + // crossed the pitch deadzone threshhold while inside the roll deadzone + { + m_currentAction = ACTION_PITCH; + } + } + + if (m_currentAction == ACTION_ROLL) + { + if (m_rel_roll < -g_deadzone) + EventClient.SendButton(KEYCODE_ROLL_NEG, m_joyString, BTN_QUEUE | BTN_NO_REPEAT, rollWeight); + if (m_rel_roll > g_deadzone) + EventClient.SendButton(KEYCODE_ROLL_POS, m_joyString, BTN_QUEUE | BTN_NO_REPEAT, rollWeight); +// printf("Roll: %f\n",m_rel_roll); + } + + if (m_currentAction == ACTION_PITCH) + { + if (m_rel_pitch > g_deadzone) + EventClient.SendButton(KEYCODE_PITCH_POS, m_joyString, BTN_QUEUE | BTN_NO_REPEAT,tiltWeight); + if (m_rel_pitch < -g_deadzone) + EventClient.SendButton(KEYCODE_PITCH_NEG, m_joyString, BTN_QUEUE | BTN_NO_REPEAT,tiltWeight); +// printf("Pitch: %f\n",m_rel_pitch); + } +} + +void CWiiController::handleIR() +{ +//TODO +} + +int connectWiimote(wiimote** wiimotes) +{ + int found = 0; + int connected = 0; + wiimote* wm; + while(!found) + { + //Look for Wiimotes. Keep searching until one is found. Wiiuse provides no way to search forever, so search for 5 secs and repeat. + found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5); + } + connected = wiiuse_connect(wiimotes, MAX_WIIMOTES); + wm = wiimotes[0]; + if (connected) + { + EventClient.SendHELO("Wii Remote", ICON_PNG, NULL); + wiiuse_set_leds(wm, WIIMOTE_LED_1); + wiiuse_rumble(wm, 1); + wiiuse_set_orient_threshold(wm,1); + #ifndef WIN32 + usleep(200000); + #else + Sleep(200); + #endif + wiiuse_rumble(wm, 0); + + return 1; + } + return 0; +} + +int handle_disconnect(wiimote* wm) +{ + EventClient.SendNOTIFICATION("Wii Remote disconnected", "", ICON_PNG, NULL); + return 0; +} + +unsigned short convert_code(unsigned short client_code) +{ +//WIIMOTE variables are from wiiuse. We need them to be 1-11 for the eventclient. +//For that we use this ugly conversion. + + switch (client_code) + { + case KEYCODE_BUTTON_UP: return WIIMOTE_BUTTON_UP; + case KEYCODE_BUTTON_DOWN: return WIIMOTE_BUTTON_DOWN; + case KEYCODE_BUTTON_LEFT: return WIIMOTE_BUTTON_LEFT; + case KEYCODE_BUTTON_RIGHT: return WIIMOTE_BUTTON_RIGHT; + case KEYCODE_BUTTON_A: return WIIMOTE_BUTTON_A; + case KEYCODE_BUTTON_B: return WIIMOTE_BUTTON_B; + case KEYCODE_BUTTON_MINUS: return WIIMOTE_BUTTON_MINUS; + case KEYCODE_BUTTON_HOME: return WIIMOTE_BUTTON_HOME; + case KEYCODE_BUTTON_PLUS: return WIIMOTE_BUTTON_PLUS; + case KEYCODE_BUTTON_ONE: return WIIMOTE_BUTTON_ONE; + case KEYCODE_BUTTON_TWO: return WIIMOTE_BUTTON_TWO; + default : break; + } +return 0; +} + +float smoothDeg(float oldVal, float newVal) +{ +//If values go over 180 or under -180, weird things happen. This tranforms the values to -360 to 360 instead. + + if (newVal - oldVal > 300) + return (newVal - 360); + if (oldVal - newVal > 300) + return(newVal + 360); + return(newVal); +} + +long getTicks(void) +{ + long ticks; + struct timeval now; + gettimeofday(&now, NULL); + ticks = now.tv_sec * 1000l; + ticks += now.tv_usec / 1000l; + return ticks; +} + +int main(int argc, char** argv) +{ + long timeout = 0; + bool connected = 0; + wiimote** wiimotes; + wiimotes = wiiuse_init(MAX_WIIMOTES); + CWiiController controller; + wiimote* wm; + { + //Main Loop + while (1) + { + if (!connected) connected = (connectWiimote(wiimotes)); + wm = wiimotes[0]; // Only worry about 1 controller. No need for more? + controller.m_buttonDownTime = getTicks() - timeout; + +//Handle ACC, Repeat, and IR outside of the Event loop so that buttons can be continuously sent + if (timeout) + { + if ((controller.m_buttonDownTime > g_hold_button_timeout) && controller.m_holdableHeld) + controller.handleACC(wm->orient.roll, wm->orient.pitch); + if ((controller.m_buttonDownTime > g_repeat_rate) && controller.m_repeatableHeld) + controller.handleRepeat(); + } + if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) + { + for (int i = 0; i < MAX_WIIMOTES; ++i) + //MAX_WIIMOTES hardcoded at 1. + { + switch (wiimotes[i]->event) + { + case WIIUSE_EVENT: + + controller.get_keys(wm); //Load up the CWiiController + controller.handleKeyPress(); + if (!controller.m_buttonHeld && (controller.m_holdableHeld || controller.m_repeatableHeld)) + { + //Prepare to repeat or hold. Do this only once. + timeout = getTicks(); + EnableMotionSensing(wm); + controller.m_abs_roll = 0; + controller.m_abs_pitch = 0; + controller.m_start_roll = 0; + controller.m_start_pitch = 0; + } + if (controller.m_buttonReleased) + { + DisableMotionSensing(wm); + controller.m_currentAction = ACTION_NONE; + } + break; + case WIIUSE_STATUS: + break; + case WIIUSE_DISCONNECT: + case WIIUSE_UNEXPECTED_DISCONNECT: + handle_disconnect(wm); + connected = 0; + break; + case WIIUSE_READ_DATA: + break; + default: + break; + } + } + } + } + } + wiiuse_cleanup(wiimotes, MAX_WIIMOTES); + return 0; +} diff --git a/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.h b/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.h new file mode 100644 index 0000000000..b4eb749b9e --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.h @@ -0,0 +1,124 @@ + /* Copyright (C) 2009 by Cory Fields + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/time.h> +//#include <math.h> +#ifdef DEB_PACK +#include <xbmc/xbmcclient.h> +#else +#include "../../lib/c++/xbmcclient.h" +#endif +//#ifndef WIN32 +// #include <unistd.h> +//#endif +#include "wiiuse.h" +//#define ICON_PATH "../../" +#define PORT 9777 +#define MAX_WIIMOTES 1 +#define OVER_180_DEG 1 +#define UNDER_NEG_180_DEG 2 +#define WIIMOTE_BUTTON_TWO 0x0001 +#define WIIMOTE_BUTTON_ONE 0x0002 +#define WIIMOTE_BUTTON_B 0x0004 +#define WIIMOTE_BUTTON_A 0x0008 +#define WIIMOTE_BUTTON_MINUS 0x0010 +#define WIIMOTE_BUTTON_HOME 0x0080 +#define WIIMOTE_BUTTON_LEFT 0x0100 +#define WIIMOTE_BUTTON_RIGHT 0x0200 +#define WIIMOTE_BUTTON_DOWN 0x0400 +#define WIIMOTE_BUTTON_UP 0x0800 +#define WIIMOTE_BUTTON_PLUS 0x1000 + +#define WIIMOTE_NUM_BUTTONS 11 +#define KEYCODE_BUTTON_UP 1 +#define KEYCODE_BUTTON_DOWN 2 +#define KEYCODE_BUTTON_LEFT 3 +#define KEYCODE_BUTTON_RIGHT 4 +#define KEYCODE_BUTTON_A 5 +#define KEYCODE_BUTTON_B 6 +#define KEYCODE_BUTTON_MINUS 7 +#define KEYCODE_BUTTON_HOME 8 +#define KEYCODE_BUTTON_PLUS 9 +#define KEYCODE_BUTTON_ONE 10 +#define KEYCODE_BUTTON_TWO 11 +#define KEYCODE_ROLL_NEG 33 +#define KEYCODE_ROLL_POS 34 +#define KEYCODE_PITCH_NEG 35 +#define KEYCODE_PITCH_POS 36 + + +#define ACTION_NONE 0 +#define ACTION_ROLL 1 +#define ACTION_PITCH 2 + +class CWiiController{ + public: + + bool m_holdableHeld; + bool m_holdableReleased; + bool m_repeatableHeld; + bool m_repeatableReleased; + + unsigned short m_buttonPressed; + unsigned short m_buttonReleased; + unsigned short m_buttonHeld; + unsigned short m_repeatFlags; + unsigned short m_holdFlags; + unsigned short m_currentAction; + + long m_buttonDownTime; + + float m_abs_roll; + float m_abs_pitch; + float m_rel_roll; + float m_rel_pitch; + float m_start_roll; + float m_start_pitch; + char* m_joyString; + + + void get_keys(wiimote* wm); + void handleKeyPress(); + void handleRepeat(); + void handleACC(float, float); + void handleIR(); + + CWiiController() + { + m_joyString = "JS0:WiiRemote"; + m_repeatFlags = WIIMOTE_BUTTON_UP | WIIMOTE_BUTTON_DOWN | WIIMOTE_BUTTON_LEFT | WIIMOTE_BUTTON_RIGHT; + m_holdFlags = WIIMOTE_BUTTON_B; + } +}; + +unsigned short g_deadzone = 30; +unsigned short g_hold_button_timeout = 200; +unsigned short g_repeat_rate = 400; + +int handle_disconnect(wiimote* ); +int connectWiimote(wiimote** ); +long getTicks(void); +void EnableMotionSensing(wiimote* wm) {if (!WIIUSE_USING_ACC(wm)) wiiuse_motion_sensing(wm, 1);} +void DisableMotionSensing(wiimote* wm) {if (WIIUSE_USING_ACC(wm)) wiiuse_motion_sensing(wm, 0);} +unsigned short convert_code(unsigned short); +float smoothDeg(float, float); + +CXBMCClient EventClient; diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/CHANGELOG b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/CHANGELOG new file mode 100644 index 0000000000..ccb831af97 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/CHANGELOG @@ -0,0 +1,208 @@ +---------------------------
+-
+- CHANGE LOG - Wiiuse
+-
+---------------------------
+
+http://wiiuse.net/
+http://wiiuse.sourceforge.net/
+http://sourceforge.net/projects/wiiuse/
+
+---------------------------
+v0.12 -- 2 Apr 2008
+---------------------------
+
+ Added:
+ - API function wiiuse_set_ir_sensitivity()
+ - Macro WIIUSE_GET_IR_SENSITIVITY()
+ - Event type WIIUSE_READ_DATA
+ - Event type WIIUSE_UNEXPECTED_DISCONNECT
+
+ Fixed:
+ - [Linux] Ability to try to select() nothing
+ - [Linux] Changed Makefile to include debug output when compiling in debug mode
+
+ Changed:
+ - wiiuse_set_nunchuk_orient_threshold() now takes a wiimote_t pointer
+ - wiiuse_set_nunchuk_accel_threshold() now takes a wiimote_t pointer
+ - wiiuse_read_data() generates an event WIIUSE_READ_DATA rather than executing a callback
+
+---------------------------
+v0.11 -- 25 Feb 2008
+---------------------------
+
+ Added:
+ - API function wiiuse_set_nunchuk_orient_threshold()
+ - API function wiiuse_set_nunchuk_accel_threshold()
+ - Event type WIIUSE_NUNCHUK_INSERTED
+ - Event type WIIUSE_NUNCHUK_REMOVED
+ - Event type WIIUSE_CLASSIC_CTRL_INSERTED
+ - Event type WIIUSE_CLASSIC_CTRL_REMOVED
+ - Event type WIIUSE_GUITAR_HERO_3_CTRL_INSERTED
+ - Event type WIIUSE_GUITAR_HERO_3_CTRL_REMOVED
+
+ Fixed:
+ - Added some missing function prototypes to wiiuse.h
+ - [Linux] Fixed Makefile to link libmath and libbluetooth
+ - Status event is set when a status report comes in
+ - Orientation threshold not being saved in lstate
+
+---------------------------
+v0.10 -- 11 Feb 2008
+---------------------------
+
+ Added:
+ - Real dynamic linking (by noisehole)
+ - Changed from callback to SDL style
+ - Guitar Hero 3 controller support
+ - API function wiiuse_set_accel_threshold()
+ - API function wiiuse_version()
+ - Macro WIIUSE_USING_SPEAKER()
+ - Macro WIIUSE_IS_LED_SET(wm, num)
+ - wiiuse_init() now autogenerates unids
+ - orient_t::a_roll/a_pitch
+ - wiiuse_resync()
+ - wiiuse_cleanup()
+ - wiiuse_set_timeout()
+
+ Fixed:
+ - [Windows] Fixed bug where it did not detect expansions on startup
+ - Renamed INFO/WARNING/DEBUG macros to WIIUSE_* (by noisehole)
+ - Updated Makefiles (by noisehole)
+ - Fixed incorrect roll/pitch when smoothing was enabled
+ - Fixed nunchuk and classic controller flooding events when significant changes occured
+ - Fixed bug where IR was not correct on roll if IR was enabled before handshake
+
+ Removed:
+ - wiiuse_startup(), no longer needed
+
+---------------------------
+v0.9 -- 3 Nov 2007
+---------------------------
+
+ Fixed:
+ - Can now use include/wiiuse.h in C++ projects.
+ - HOME button works again.
+ - IR now functions after expansion is connected or removed.
+
+---------------------------
+v0.8 -- 27 Oct 2007
+---------------------------
+
+ - Bumped API version to 8
+ - Exported all API functions for usage with non-C/C++ languages.
+ - Changed event callback to only trigger if a significant state change occurs.
+
+ Added:
+ - wiimote_t::lstate structure
+
+ Fixed:
+ - Bug 1820140 - Buffer overflow in io_nix.c. Thanks proppy.
+
+---------------------------
+v0.7 -- 19 Oct 2007
+---------------------------
+
+ - Bumped API version to 7
+ - Renamed Linux build from wii.so to wiiuse.so
+ - Changed version representation from float to const char*.
+
+ Added:
+ - [Windows] BlueSoleil support.
+ - [Windows] Bluetooth stack auto-detection (WinXP SP2, Bluesoleil, Widdcomm tested).
+ - [Windows] API function wiiuse_set_bluetooth_stack().
+ - Calculates yaw if IR tracking is enabled.
+
+ Fixed:
+ - [Windows] Problem where a connection is made to a wiimote that does not exist.
+ - [Windows] Issue that occured while using multiple wiimotes.
+
+---------------------------
+v0.6 -- 16 Oct 2007
+---------------------------
+
+ - Bumped API version to 0.6.
+ - Ported to Microsoft Windows.
+ - Improved IR tracking.
+ - Default IR virtual screen resolutions changed depending on 16:9 or 4:3.
+
+ Added:
+ - src/msvc/ and api/msvc/ - Microsoft Visual C++ 6.0 project files.
+
+---------------------------
+v0.5 -- 13 Oct 2007
+---------------------------
+
+ - Bumped API version to 0.5.
+ - Greatly improved IR tracking.
+ - Renamed function wiiuse_set_ir_correction() to wiiuse_set_ir_position().
+
+ Added:
+ - API function wiiuse_set_aspect_ratio()
+
+ Fixed:
+ - When rolling around 180 degree rotation smoothing would not be seemless.
+
+---------------------------
+v0.4 -- 08 Oct 2007
+---------------------------
+
+ - Bumped API version to 0.4.
+ - Greatly improved classic controller joystick functionality.
+ - Changed all functions named wiimote_*() to wiiuse_*()
+ - Renamed many macros from WIIMOTE_* to WIIUSE_*
+
+ Added:
+ - IR support
+ - New WIIMOTE_CONTINUOUS flag to set continuous reporting
+ - Macro IS_JUST_PRESSED()
+ - Macro WIIUSE_USING_ACC()
+ - Macro WIIUSE_USING_EXP()
+ - Macro WIIUSE_USING_IR()
+ - API function wiiuse_set_ir()
+ - API function wiiuse_set_ir_vres()
+ - API function wiiuse_set_ir_correction()
+
+ - gfx/ - A small OpenGL example that renders IR data
+
+ Fixed:
+ - Sometimes classic controller would only report infinite angle and magnitude for joysticks.
+
+---------------------------
+v0.3 -- 10 Sept 2007
+---------------------------
+
+ - Moved license to GPLv3.
+ - Bumped API version to 0.3.
+
+ Added:
+ - Support for Classic Controller
+ - Smoothing for roll and pitch values of the wiimote and nunchuk.
+
+ - API: wiimote_set_flags() to set or disable wiimote options.
+ - API: wiimote_set_smooth_alpha() to set smoothing alpha value.
+
+ Fixed:
+ - When the wiimote accelerates the roll or pitch is unreliable and was set to 0.
+ It now remains at previous tilt value.
+ - If no event callback was specified then no events would be processed internally.
+
+---------------------------
+v0.2 -- 25 Aug 2007
+---------------------------
+
+ - Bumped API version to 0.2.
+
+ Added:
+ - Nunchuk support.
+ - Ability to write to flash memory.
+
+ Fixed:
+ - Roll and pitch rotation now ranges from -180 to 180 degrees (previously -90 to 90).
+ - Bug when reading data from flash memory would read wrong address.
+
+---------------------------
+v0.1 -- 23 Feb 2007
+---------------------------
+
+ - Initial release
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE new file mode 100644 index 0000000000..85b8e59922 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE @@ -0,0 +1,620 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE_noncommercial b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE_noncommercial new file mode 100644 index 0000000000..b556a2278c --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE_noncommercial @@ -0,0 +1,170 @@ +This license can be used for any works that this license defines +as "derived" or "combined" works that are strictly NON-COMMERCIAL. +This license prohibits the use of any source or object code +in works that are PROPRIETARY. + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/Makefile b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/Makefile new file mode 100644 index 0000000000..f63da694f8 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/Makefile @@ -0,0 +1,23 @@ +# +# wiiuse Makefile +# + +all clean install: + @$(MAKE) -C src $@ + @$(MAKE) -C example $@ + @$(MAKE) -C example-sdl $@ + +wiiuse: + @$(MAKE) -C src + +ex: + @$(MAKE) -C example + +sdl-ex: + @$(MAKE) -C example-sdl + +distclean: + @$(MAKE) -C src $@ + @$(MAKE) -C example $@ + @$(MAKE) -C example-sdl $@ + @find . -type f \( -name "*.save" -or -name "*~" -or -name gmon.out \) -delete &> /dev/null diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/README b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/README new file mode 100644 index 0000000000..12d9f71517 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/README @@ -0,0 +1,155 @@ +---------------------------
+-
+- README - Wiiuse
+-
+---------------------------
+
+http://wiiuse.net/
+http://wiiuse.sourceforge.net/
+http://sourceforge.net/projects/wiiuse/
+
+---------------------------
+
+ABOUT
+
+ Wiiuse is a library written in C that connects with several Nintendo Wii remotes.
+ Supports motion sensing, IR tracking, nunchuk, classic controller, and the Guitar Hero 3 controller.
+ Single threaded and nonblocking makes a light weight and clean API.
+
+ Distributed under the GPL and LGPL.
+
+
+AUTHORS
+
+ Michael Laforest < para >
+ Email: < thepara (--AT--) g m a i l [--DOT--] com >
+
+ The following people have contributed patches to wiiuse:
+ - dhewg
+
+
+LICENSE
+
+ There are two licenses for wiiuse. Please read them carefully before choosing which one
+ you use. You may of course at any time switch the license you are currently using to
+ the other.
+
+ Briefly, the license options are:
+
+ a) GNU LGPL (modified for non-commercial usage only)
+ b) GNU GPL
+
+ PLEASE READ THE LICENSES!
+
+
+ACKNOWLEDGEMENTS
+
+ http://wiibrew.org/
+ This site and their users have contributed an immense amount of information
+ about the wiimote and its technical details. I could not have written this program
+ without the vast amounts of reverse engineered information that was researched by them.
+
+ Nintendo
+ Of course Nintendo for designing and manufacturing the Wii and Wii remote.
+
+ BlueZ
+ Easy and intuitive bluetooth stack for Linux.
+
+ Thanks to Brent for letting me borrow his Guitar Hero 3 controller.
+
+
+DISCLAIMER AND WARNINGS
+
+ I am in no way responsible for any damages or effects, intended or not, caused by this program.
+
+ *** WARNING *** WARNING *** WARNING ***
+
+ Be aware that writing to memory may damage or destroy your wiimote or expansions.
+
+ *** WARNING *** WARNING *** WARNING ***
+
+ This program was written using reverse engineered specifications available from wiibrew.org.
+ Therefore the operation of this program may not be entirely correct.
+ Results obtained by using this program may vary.
+
+
+AUDIENCE
+
+ This project is intended for developers who wish to include support for the Nintendo Wii remote
+ with their third party application. Please be aware that by using this software you are bound
+ to the terms of the GNU GPL.
+
+
+PLATFORMS AND DEPENDENCIES
+
+ Wiiuse currently operates on both Linux and Windows.
+ You will need:
+
+ For Linux:
+ - The kernel must support bluetooth
+ - The BlueZ bluetooth drivers must be installed
+
+ For Windows:
+ - Bluetooth driver (tested with Microsoft's stack with Windows XP SP2)
+ - If compiling, Microsoft Windows Driver Development Kit (DDK)
+
+
+COMPILING
+
+ Linux:
+ You need SDL and OpenGL installed to compile the SDL example.
+
+ # make [target]
+
+ If 'target' is omitted then everything is compiled.
+
+ Where 'target' can be any of the following:
+
+ - wiiuse
+ Compiles libwiiuse.so
+
+ - ex
+ Compiles wiiuse-example
+
+ - sdl-ex
+ Compiles wiiuse-sdl
+
+ Become root.
+
+ # make install
+
+ The above command will only install the binaries that you
+ selected to compile.
+
+ wiiuse.so is installed to /usr/lib
+ wiiuse-example and wiiuse-sdl are installed to /usr/bin
+
+ Windows:
+ A Microsoft Visual C++ 6.0 project file has been included.
+
+ You need the install the Windows DDK (driver development kit)
+ to compile wiiuse. Make sure you include the inc/ and lib/
+ directories from the DDK in your IDE include and library paths.
+ You can download this from here:
+ http://www.microsoft.com/whdc/devtools/ddk/default.mspx
+
+ You need to link the following libraries (already set in the
+ included project file):
+ - Ws2_32.lib
+ - hid.lib
+ - setupapi.lib
+
+
+USING THE LIBRARY IN A THIRD PARTY APPLICATION
+
+ To use the library in your own program you must first compile wiiuse as a module.
+ Include include/wiiuse.h in any file that uses wiiuse.
+
+ For Linux you must link wiiuse.so ( -lwiiuse ).
+ For Windows you must link wiiuse.lib. When your program runs it will need wiiuse.dll.
+
+
+BUGS
+
+ On Windows using more than one wiimote (usually more than two wiimotes) may cause
+ significant latency.
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/Makefile b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/Makefile new file mode 100644 index 0000000000..c206354141 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/Makefile @@ -0,0 +1,83 @@ +# +# wiiuse Makefile +# + +# +# Change this to your GCC version. +# +CC = gcc + +#################################################### +# +# You should not need to edit below this line. +# +#################################################### + +# +# Universal cflags +# +CFLAGS = -Wall -pipe -fPIC -funroll-loops + +ifeq ($(debug),1) + OBJ_PREFIX = debug + CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG +else + OBJ_PREFIX = release + CFLAGS += -O2 +endif + +OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2) + +# +# Linking flags +# +LDFLAGS = -L../src/$(OBJ_DIR) -lm -lGL -lGLU -lglut -lSDL -lbluetooth -lwiiuse + +# +# Target binaries (always created as BIN) +# +BIN = ./$(OBJ_DIR)/wiiuse-sdl + +# +# Inclusion paths. +# +INCLUDES = -I../src/ -I/usr/include/SDL + +# +# Generate a list of object files +# +OBJS = $(OBJ_DIR)/sdl.o + +############################### +# +# Build targets. +# +############################### + +all: $(BIN) + +clean: + @-rm $(OBJS) 2> /dev/null + +distclean: clean + @-rm -r debug-* release-* 2> /dev/null + +install: + @if [ -e $(BIN) ]; then \ + cp -v $(BIN) /usr/bin ;\ + fi + +$(BIN): mkdir $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN) + +$(OBJ_DIR)/%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +mkdir: + @if [ ! -d $(OBJ_DIR) ]; then \ + mkdir $(OBJ_DIR); \ + fi + +run: all + LD_LIBRARY_PATH=`pwd`/../src/$(OBJ_DIR):$(LD_LIBRARY_PATH) $(BIN) + diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsp b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsp new file mode 100644 index 0000000000..23c4a24c2a --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="wiiusesdl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=wiiusesdl - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "wiiusesdl.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "wiiusesdl.mak" CFG="wiiusesdl - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "wiiusesdl - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "wiiusesdl - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "wiiusesdl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib opengl32.lib glu32.lib wiiuse.lib /nologo /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "wiiusesdl - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib opengl32.lib glu32.lib wiiuse.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "wiiusesdl - Win32 Release"
+# Name "wiiusesdl - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\sdl.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\wiiuse.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsw b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsw new file mode 100644 index 0000000000..630b942593 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "wiiusesdl"=".\wiiusesdl.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.opt b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.opt Binary files differnew file mode 100644 index 0000000000..fa46687ca8 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.opt diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/sdl.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/sdl.c new file mode 100644 index 0000000000..0c0cdfb993 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/sdl.c @@ -0,0 +1,439 @@ +/* + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + */ + +#include <stdlib.h> +#include <math.h> + +#ifndef WIN32 + #include <unistd.h> + #include <sys/time.h> + #include <time.h> +#else + #include <windows.h> +#endif + +#include <GL/gl.h> +#include <GL/glu.h> +#include <GL/glut.h> +#include <SDL.h> + +#include <wiiuse.h> + +#define PI 3.14159265358979323846 +#define PI_DIV_180 0.017453292519943296 +#define deg PI_DIV_180 + +#define MAX_WIIMOTES 2 + +GLint width = 1024, height = 768; +GLfloat backColor[4] = {1.0,1.0,1.0,1.0}; + +wiimote** wiimotes = NULL; + +int last_dots[4][2] = {{0}}; +int xcoord = 0; +int ycoord = 0;
+
+#ifdef WIN32
+ DWORD last_render; +#else + struct timeval last_render; + int last_sec = 0;
+ int fps = 0;
+#endif + +enum render_mode_t { + IR = 1, + TEAPOT +}; +enum render_mode_t render_mode = IR; + +/* light information */ +struct light_t { + GLfloat position[4]; + GLfloat spotDirection[3]; + GLfloat ambient[4]; + GLfloat diffuse[4]; + GLfloat specular[4]; + GLfloat spotCutoff; + GLfloat spotExponent; + GLfloat spotAttenuation[3]; /* [0] = constant, [1] = linear, [2] = quadratic */ +}; +struct light_t light = { + { 1.0, 1.0, -2.0, 1.0 }, + { -1.0, -1.0, 2.0 }, + { 0.0, 0.0, 0.0, 1.0 }, + { 1.0, 1.0, 1.0, 1.0 }, + { 1.0, 1.0, 1.0, 1.0 }, + 180.0, 0.0, + { 1.0, 0.0, 0.0 } +}; + +/* material information */ +struct material_t { + GLfloat ambient[4]; + GLfloat diffuse[4]; + GLfloat specular[4]; + GLfloat emission[4]; + GLfloat shininess; +}; +struct material_t red_plastic = { + { 0.3, 0.0, 0.0, 1.0 }, + { 0.3, 0.0, 0.0, 1.0 }, + { 0.8, 0.6, 0.6, 1.0 }, + { 0.0, 0.0, 0.0, 1.0 }, + 32.0 +}; + + +void handle_event(struct wiimote_t* wm); +void display(); +void update_light(GLenum l, struct light_t* lptr); +void set_material(struct material_t* mptr); +void resize_window(GLint new_width, GLint new_height); + +void handle_event(struct wiimote_t* wm) { + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) + wiiuse_motion_sensing(wm, 1); + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) + wiiuse_motion_sensing(wm, 0); + + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP)) + wiiuse_set_ir(wm, 1); + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) + wiiuse_set_ir(wm, 0); +
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B))
+ wiiuse_toggle_rumble(wm); + + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_ONE)) { + int level; + WIIUSE_GET_IR_SENSITIVITY(wm, &level); + wiiuse_set_ir_sensitivity(wm, level+1); + } + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_TWO)) { + int level; + WIIUSE_GET_IR_SENSITIVITY(wm, &level); + wiiuse_set_ir_sensitivity(wm, level-1); + } + + #if 0 + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_A)) { + if (render_mode == IR) + render_mode = TEAPOT; + else + render_mode = IR; + resize_window(width, height); + } + #endif +} + +#define DRAW_TRIANGLE(x, y, z, s) do { \ + glVertex3f(x, y-s, z); \ + glVertex3f(x+s, y+s, z); \ + glVertex3f(x-s, y+s, z); \ + } while (0) + +int can_render() { + /* quick fps limit to ~60fps -- not too fancy, could be better */ + #ifdef WIN32 + if (GetTickCount() < (last_render + 16)) + return 0;
+ last_render = GetTickCount();
+ return 1; + #else + struct timeval now; + long elapsed_usec = 0; + + gettimeofday(&now, NULL); + + if (now.tv_usec > 1000000) { + now.tv_usec -= 1000000; + ++now.tv_sec; + } + + if (now.tv_sec > last_render.tv_sec) + elapsed_usec = ((now.tv_sec - last_render.tv_sec) * 1000000); + + if (now.tv_usec > last_render.tv_usec) + elapsed_usec += now.tv_usec - last_render.tv_usec; + else + elapsed_usec += last_render.tv_usec - now.tv_usec; + + if (time(NULL) > last_sec) { + printf("fps: %i\n", fps); + fps = 0; + last_sec = time(NULL); + } + + if (elapsed_usec < 16000) + return 0; + + last_render = now; + ++fps; + + return 1; + #endif +} + +void display() { + int i, wm; + float size = 5; + + if (!can_render()) + return;
+ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity();
+ + if (render_mode == IR) { + /* draw the IR stuff */ +
+ glDisable(GL_LIGHTING); + + glBegin(GL_TRIANGLES);
+ /* green center */
+ glColor3f(0.0, 1.0, 0.0);
+ DRAW_TRIANGLE(width/2, height/2, 0, size);
+ glEnd();
+
+ for (wm = 0; wm < MAX_WIIMOTES; ++wm) { + glBegin(GL_TRIANGLES); + /* red ir */ + glColor3f(1.0, 0.0, 0.0); + for (i = 0; i < 4; ++i) { + if (wiimotes[wm]->ir.dot[i].visible) + DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].rx, wiimotes[wm]->ir.dot[i].ry, 0, size); + } + + /* yellow corrected ir */ + glColor3f(1.0, 1.0, 0.0); + for (i = 0; i < 4; ++i) { + if (wiimotes[wm]->ir.dot[i].visible) + DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].x, wiimotes[wm]->ir.dot[i].y, 0, size); + } + + /* blue cursor */ + glColor3f(0.0, 0.0, 1.0); + DRAW_TRIANGLE(wiimotes[wm]->ir.x, wiimotes[wm]->ir.y-size, 0, size); + glEnd(); + } + } else { + /* draw the teapot */ + gluLookAt(0.0, 0.0, -5.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + update_light(GL_LIGHT0, &light); + set_material(&red_plastic); + + glRotatef(wiimotes[0]->orient.roll, 0.0f, 0.0f, 1.0f); + glRotatef(wiimotes[0]->orient.pitch, 1.0f, 0.0f, 0.0f); + + + glutSolidTeapot(1); + }
+ + SDL_GL_SwapBuffers(); +} + + +void update_light(GLenum l, struct light_t* lptr) { + glLightfv(l, GL_POSITION, lptr->position); + glLightfv(l, GL_DIFFUSE, lptr->diffuse); + glLightfv(l, GL_SPECULAR, lptr->specular); + glLightfv(l, GL_AMBIENT, lptr->ambient); + glLightfv(l, GL_SPOT_DIRECTION, lptr->spotDirection); + glLightf(l, GL_SPOT_CUTOFF, lptr->spotCutoff); + glLightf(l, GL_SPOT_EXPONENT, lptr->spotExponent); + glLightf(l, GL_CONSTANT_ATTENUATION, lptr->spotAttenuation[0]); + glLightf(l, GL_LINEAR_ATTENUATION, lptr->spotAttenuation[1]); + glLightf(l, GL_QUADRATIC_ATTENUATION, lptr->spotAttenuation[2]); +} + + +void set_material(struct material_t* mptr) { + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mptr->ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mptr->diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mptr->specular); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mptr->shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mptr->emission); +} + + +void resize_window(GLint new_width, GLint new_height) {
+ int wm;
+ + width = new_width; + height = new_height; + + if (new_height == 0) + new_height = 1; + + SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL); + + glViewport(0, 0, new_width, new_height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + if (render_mode == IR) + gluOrtho2D(0, width, height, 0); + else + gluPerspective(60.0f, (float)new_width/(float)new_height, 0.1f, 100.0f); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + width = new_width; + height = new_height; +
+ for (wm = 0; wm < MAX_WIIMOTES; ++wm)
+ wiiuse_set_ir_vres(wiimotes[wm], width, height); +} + +#ifndef WIN32 +int main(int argc, char** argv) { +#else +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { +#endif + int found, connected;
+ int wm; + + //printf("wiiuse version = %s\n", wiiuse_version()); + + wiimotes = wiiuse_init(MAX_WIIMOTES); + found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5); + if (!found) + return 0; + connected = wiiuse_connect(wiimotes, MAX_WIIMOTES); + if (connected) + printf("Connected to %i wiimotes (of %i found).\n", connected, found); + else { + printf("Failed to connect to any wiimote.\n"); + return 0; + } + wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1 | WIIMOTE_LED_4); + wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2 | WIIMOTE_LED_4);
+ wiiuse_rumble(wiimotes[0], 1); + + #ifndef WIN32 + usleep(200000); + #else + Sleep(200); + #endif + + wiiuse_rumble(wiimotes[0], 0); +
+ /* enable IR and motion sensing for all wiimotes */
+ for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
+ wiiuse_motion_sensing(wiimotes[wm], 1); + wiiuse_set_ir(wiimotes[wm], 1);
+ }
+ + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + printf("Failed to initialize SDL: %s\n", SDL_GetError()); + return 0; + } + + SDL_WM_SetCaption("wiiuse SDL IR Example", "wiiuse SDL IR Example");
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + + /* set window size */ + width = wiimotes[0]->ir.vres[0]; + height = wiimotes[0]->ir.vres[1]; + SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
+
+ for (wm = 0; wm < MAX_WIIMOTES; ++wm)
+ wiiuse_set_ir_vres(wiimotes[wm], width, height); + + /* set OpenGL stuff */ + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_NORMALIZE); + glEnable(GL_BLEND); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthFunc(GL_LEQUAL); + glClearColor(0, 0, 0, 0); + + /* set the size of the window */ + resize_window(width, height); + + display();
+
+ #ifdef WIN32
+ last_render = GetTickCount(); + #endif + + while (1) { + SDL_Event event; +
+ if (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_VIDEORESIZE: + { + /* resize the window */ + resize_window(event.resize.w, event.resize.h); + break; + } + case SDL_QUIT: + { + /* shutdown */ + SDL_Quit(); + wiiuse_cleanup(wiimotes, MAX_WIIMOTES); + return 0; + } + default: + { + } + } + } + + if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) { + /* + * This happens if something happened on any wiimote. + * So go through each one and check if anything happened. + */ + int i = 0; + for (; i < MAX_WIIMOTES; ++i) { + switch (wiimotes[i]->event) { + case WIIUSE_EVENT: + /* a generic event occured */ + handle_event(wiimotes[i]); + break; + + default: + break; + } + } + } + + display();
+ } +} diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/Makefile b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/Makefile new file mode 100644 index 0000000000..41b5cd1e65 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/Makefile @@ -0,0 +1,84 @@ +# +# wiiuse Makefile +# + +# +# Change this to your GCC version. +# +CC = gcc + +#################################################### +# +# You should not need to edit below this line. +# +#################################################### + +# +# Universal cflags +# +CFLAGS = -Wall -pipe -fPIC -funroll-loops + +ifeq ($(debug),1) + OBJ_PREFIX = debug + CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG +else + OBJ_PREFIX = release + CFLAGS += -O2 +endif + +OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2) + +# +# Linking flags +# +LDFLAGS = -L../src/$(OBJ_DIR) -lm -lwiiuse + +# +# Target binaries (always created as BIN) +# +BIN = ./$(OBJ_DIR)/wiiuse-example + +# +# Inclusion paths. +# +INCLUDES = -I../src/ + +# +# Generate a list of object files +# +OBJS = $(OBJ_DIR)/example.o + +############################### +# +# Build targets. +# +############################### + +all: $(BIN) + +clean: + @-rm $(OBJS) 2> /dev/null + +distclean: + @-rm -r debug-* release-* 2> /dev/null + +install: + @if [ -e $(BIN) ]; then \ + cp -v $(BIN) /usr/bin ; \ + fi + + +$(BIN): mkdir $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN) + +$(OBJ_DIR)/%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +mkdir: + @if [ ! -d $(OBJ_DIR) ]; then \ + mkdir $(OBJ_DIR); \ + fi + +run: all + LD_LIBRARY_PATH=`pwd`/../src/$(OBJ_DIR):$(LD_LIBRARY_PATH) $(BIN) + diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/example.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/example.c new file mode 100644 index 0000000000..8536cf683c --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/example.c @@ -0,0 +1,437 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * + * @brief Example using the wiiuse API. + * + * This file is an example of how to use the wiiuse library. + */ + +#include <stdio.h> +#include <stdlib.h> + +#ifndef WIN32 + #include <unistd.h> +#endif + +#include "wiiuse.h" + + +#define MAX_WIIMOTES 4 + + +/** + * @brief Callback that handles an event. + * + * @param wm Pointer to a wiimote_t structure. + * + * This function is called automatically by the wiiuse library when an + * event occurs on the specified wiimote. + */ +void handle_event(struct wiimote_t* wm) { + printf("\n\n--- EVENT [id %i] ---\n", wm->unid); + + /* if a button is pressed, report it */ + if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) printf("A pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_B)) printf("B pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP)) printf("UP pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) printf("DOWN pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT)) printf("LEFT pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT)) printf("RIGHT pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) printf("MINUS pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) printf("PLUS pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE)) printf("ONE pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO)) printf("TWO pressed\n"); + if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME)) printf("HOME pressed\n"); + + /* + * Pressing minus will tell the wiimote we are no longer interested in movement. + * This is useful because it saves battery power. + */ + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) + wiiuse_motion_sensing(wm, 0); + + /* + * Pressing plus will tell the wiimote we are interested in movement. + */ + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) + wiiuse_motion_sensing(wm, 1); + + /* + * Pressing B will toggle the rumble + * + * if B is pressed but is not held, toggle the rumble + */ + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B)) + wiiuse_toggle_rumble(wm); + + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP)) + wiiuse_set_ir(wm, 1); + if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) + wiiuse_set_ir(wm, 0); + + /* if the accelerometer is turned on then print angles */ + if (WIIUSE_USING_ACC(wm)) { + printf("wiimote roll = %f [%f]\n", wm->orient.roll, wm->orient.a_roll); + printf("wiimote pitch = %f [%f]\n", wm->orient.pitch, wm->orient.a_pitch); + printf("wiimote yaw = %f\n", wm->orient.yaw); + } + + /* + * If IR tracking is enabled then print the coordinates + * on the virtual screen that the wiimote is pointing to. + * + * Also make sure that we see at least 1 dot. + */ + if (WIIUSE_USING_IR(wm)) { + int i = 0; + + /* go through each of the 4 possible IR sources */ + for (; i < 4; ++i) { + /* check if the source is visible */ + if (wm->ir.dot[i].visible) + printf("IR source %i: (%u, %u)\n", i, wm->ir.dot[i].x, wm->ir.dot[i].y); + } + + printf("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y); + printf("IR z distance: %f\n", wm->ir.z); + } + + /* show events specific to supported expansions */ + if (wm->exp.type == EXP_NUNCHUK) { + /* nunchuk */ + struct nunchuk_t* nc = (nunchuk_t*)&wm->exp.nunchuk; + + if (IS_PRESSED(nc, NUNCHUK_BUTTON_C)) printf("Nunchuk: C pressed\n"); + if (IS_PRESSED(nc, NUNCHUK_BUTTON_Z)) printf("Nunchuk: Z pressed\n"); + + printf("nunchuk roll = %f\n", nc->orient.roll); + printf("nunchuk pitch = %f\n", nc->orient.pitch); + printf("nunchuk yaw = %f\n", nc->orient.yaw); + + printf("nunchuk joystick angle: %f\n", nc->js.ang); + printf("nunchuk joystick magnitude: %f\n", nc->js.mag); + } else if (wm->exp.type == EXP_CLASSIC) { + /* classic controller */ + struct classic_ctrl_t* cc = (classic_ctrl_t*)&wm->exp.classic; + + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZL)) printf("Classic: ZL pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_B)) printf("Classic: B pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_Y)) printf("Classic: Y pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_A)) printf("Classic: A pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_X)) printf("Classic: X pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZR)) printf("Classic: ZR pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_LEFT)) printf("Classic: LEFT pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_UP)) printf("Classic: UP pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_RIGHT)) printf("Classic: RIGHT pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_DOWN)) printf("Classic: DOWN pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_L)) printf("Classic: FULL L pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_MINUS)) printf("Classic: MINUS pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_HOME)) printf("Classic: HOME pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_PLUS)) printf("Classic: PLUS pressed\n"); + if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_R)) printf("Classic: FULL R pressed\n"); + + printf("classic L button pressed: %f\n", cc->l_shoulder); + printf("classic R button pressed: %f\n", cc->r_shoulder); + printf("classic left joystick angle: %f\n", cc->ljs.ang); + printf("classic left joystick magnitude: %f\n", cc->ljs.mag); + printf("classic right joystick angle: %f\n", cc->rjs.ang); + printf("classic right joystick magnitude: %f\n", cc->rjs.mag); + } else if (wm->exp.type == EXP_GUITAR_HERO_3) { + /* guitar hero 3 guitar */ + struct guitar_hero_3_t* gh3 = (guitar_hero_3_t*)&wm->exp.gh3; + + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_UP)) printf("Guitar: Strum Up pressed\n"); + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_DOWN)) printf("Guitar: Strum Down pressed\n"); + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_YELLOW)) printf("Guitar: Yellow pressed\n"); + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_GREEN)) printf("Guitar: Green pressed\n"); + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_BLUE)) printf("Guitar: Blue pressed\n"); + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_RED)) printf("Guitar: Red pressed\n"); + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_ORANGE)) printf("Guitar: Orange pressed\n"); + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_PLUS)) printf("Guitar: Plus pressed\n"); + if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_MINUS)) printf("Guitar: Minus pressed\n"); + + printf("Guitar whammy bar: %f\n", gh3->whammy_bar); + printf("Guitar joystick angle: %f\n", gh3->js.ang); + printf("Guitar joystick magnitude: %f\n", gh3->js.mag); + } +} + + +/** + * @brief Callback that handles a read event. + * + * @param wm Pointer to a wiimote_t structure. + * @param data Pointer to the filled data block. + * @param len Length in bytes of the data block. + * + * This function is called automatically by the wiiuse library when + * the wiimote has returned the full data requested by a previous + * call to wiiuse_read_data(). + * + * You can read data on the wiimote, such as Mii data, if + * you know the offset address and the length. + * + * The \a data pointer was specified on the call to wiiuse_read_data(). + * At the time of this function being called, it is not safe to deallocate + * this buffer. + */ +void handle_read(struct wiimote_t* wm, byte* data, unsigned short len) { + int i = 0; + + printf("\n\n--- DATA READ [wiimote id %i] ---\n", wm->unid); + printf("finished read of size %i\n", len); + for (; i < len; ++i) { + if (!(i%16)) + printf("\n"); + printf("%x ", data[i]); + } + printf("\n\n"); +} + + +/** + * @brief Callback that handles a controller status event. + * + * @param wm Pointer to a wiimote_t structure. + * @param attachment Is there an attachment? (1 for yes, 0 for no) + * @param speaker Is the speaker enabled? (1 for yes, 0 for no) + * @param ir Is the IR support enabled? (1 for yes, 0 for no) + * @param led What LEDs are lit. + * @param battery_level Battery level, between 0.0 (0%) and 1.0 (100%). + * + * This occurs when either the controller status changed + * or the controller status was requested explicitly by + * wiiuse_status(). + * + * One reason the status can change is if the nunchuk was + * inserted or removed from the expansion port. + */ +void handle_ctrl_status(struct wiimote_t* wm) { + printf("\n\n--- CONTROLLER STATUS [wiimote id %i] ---\n", wm->unid); + + printf("attachment: %i\n", wm->exp.type); + printf("speaker: %i\n", WIIUSE_USING_SPEAKER(wm)); + printf("ir: %i\n", WIIUSE_USING_IR(wm)); + printf("leds: %i %i %i %i\n", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4)); + printf("battery: %f %%\n", wm->battery_level); +} + + +/** + * @brief Callback that handles a disconnection event. + * + * @param wm Pointer to a wiimote_t structure. + * + * This can happen if the POWER button is pressed, or + * if the connection is interrupted. + */ +void handle_disconnect(wiimote* wm) { + printf("\n\n--- DISCONNECTED [wiimote id %i] ---\n", wm->unid); +} + + +void test(struct wiimote_t* wm, byte* data, unsigned short len) { + printf("test: %i [%x %x %x %x]\n", len, data[0], data[1], data[2], data[3]); +} + + + +/** + * @brief main() + * + * Connect to up to two wiimotes and print any events + * that occur on either device. + */ +int main(int argc, char** argv) { + wiimote** wiimotes; + int found, connected; + + /* + * Initialize an array of wiimote objects. + * + * The parameter is the number of wiimotes I want to create. + */ + wiimotes = wiiuse_init(MAX_WIIMOTES); + + /* + * Find wiimote devices + * + * Now we need to find some wiimotes. + * Give the function the wiimote array we created, and tell it there + * are MAX_WIIMOTES wiimotes we are interested in. + * + * Set the timeout to be 5 seconds. + * + * This will return the number of actual wiimotes that are in discovery mode. + */ + found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5); + if (!found) { + printf ("No wiimotes found."); + return 0; + } + + /* + * Connect to the wiimotes + * + * Now that we found some wiimotes, connect to them. + * Give the function the wiimote array and the number + * of wiimote devices we found. + * + * This will return the number of established connections to the found wiimotes. + */ + connected = wiiuse_connect(wiimotes, MAX_WIIMOTES); + if (connected) + printf("Connected to %i wiimotes (of %i found).\n", connected, found); + else { + printf("Failed to connect to any wiimote.\n"); + return 0; + } + + /* + * Now set the LEDs and rumble for a second so it's easy + * to tell which wiimotes are connected (just like the wii does). + */ + wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1); + wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2); + wiiuse_set_leds(wiimotes[2], WIIMOTE_LED_3); + wiiuse_set_leds(wiimotes[3], WIIMOTE_LED_4); + wiiuse_rumble(wiimotes[0], 1); + wiiuse_rumble(wiimotes[1], 1); + + #ifndef WIN32 + usleep(200000); + #else + Sleep(200); + #endif + + wiiuse_rumble(wiimotes[0], 0); + wiiuse_rumble(wiimotes[1], 0); + + /* + * Maybe I'm interested in the battery power of the 0th + * wiimote. This should be WIIMOTE_ID_1 but to be sure + * you can get the wiimote assoicated with WIIMOTE_ID_1 + * using the wiiuse_get_by_id() function. + * + * A status request will return other things too, like + * if any expansions are plugged into the wiimote or + * what LEDs are lit. + */ + //wiiuse_status(wiimotes[0]); + + /* + * This is the main loop + * + * wiiuse_poll() needs to be called with the wiimote array + * and the number of wiimote structures in that array + * (it doesn't matter if some of those wiimotes are not used + * or are not connected). + * + * This function will set the event flag for each wiimote + * when the wiimote has things to report. + */ + while (1) { + if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) { + /* + * This happens if something happened on any wiimote. + * So go through each one and check if anything happened. + */ + int i = 0; + for (; i < MAX_WIIMOTES; ++i) { + switch (wiimotes[i]->event) { + case WIIUSE_EVENT: + /* a generic event occured */ + handle_event(wiimotes[i]); + break; + + case WIIUSE_STATUS: + /* a status event occured */ + handle_ctrl_status(wiimotes[i]); + break; + + case WIIUSE_DISCONNECT: + case WIIUSE_UNEXPECTED_DISCONNECT: + /* the wiimote disconnected */ + handle_disconnect(wiimotes[i]); + break; + + case WIIUSE_READ_DATA: + /* + * Data we requested to read was returned. + * Take a look at wiimotes[i]->read_req + * for the data. + */ + break; + + case WIIUSE_NUNCHUK_INSERTED: + /* + * a nunchuk was inserted + * This is a good place to set any nunchuk specific + * threshold values. By default they are the same + * as the wiimote. + */ + //wiiuse_set_nunchuk_orient_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 90.0f); + //wiiuse_set_nunchuk_accel_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 100); + printf("Nunchuk inserted.\n"); + break; + + case WIIUSE_CLASSIC_CTRL_INSERTED: + printf("Classic controller inserted.\n"); + break; + + case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED: + /* some expansion was inserted */ + handle_ctrl_status(wiimotes[i]); + printf("Guitar Hero 3 controller inserted.\n"); + break; + + case WIIUSE_NUNCHUK_REMOVED: + case WIIUSE_CLASSIC_CTRL_REMOVED: + case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED: + /* some expansion was removed */ + handle_ctrl_status(wiimotes[i]); + printf("An expansion was removed.\n"); + break; + + default: + break; + } + } + } + } + + /* + * Disconnect the wiimotes + */ + wiiuse_cleanup(wiimotes, MAX_WIIMOTES); + + return 0; +} diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsp b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsp new file mode 100644 index 0000000000..9e9b34faa8 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsp @@ -0,0 +1,106 @@ +# Microsoft Developer Studio Project File - Name="wiiuseexample" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=wiiuseexample - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "wiiuseexample.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "wiiuseexample.mak" CFG="wiiuseexample - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "wiiuseexample - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "wiiuseexample - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "wiiuseexample - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib wiiuse.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "wiiuseexample - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "wiiuseexample - Win32 Release"
+# Name "wiiuseexample - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\example.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\wiiuse.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsw b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsw new file mode 100644 index 0000000000..e31f8f5615 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "wiiuseexample"=".\wiiuseexample.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.opt b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.opt Binary files differnew file mode 100644 index 0000000000..fe837f89e2 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.opt diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/Makefile b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/Makefile new file mode 100644 index 0000000000..bab5b140f4 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/Makefile @@ -0,0 +1,91 @@ +# +# wiiuse Makefile +# + +# +# Change this to your GCC version. +# +CC = gcc + +#################################################### +# +# You should not need to edit below this line. +# +#################################################### + +# +# Universal cflags +# +CFLAGS = -Wall -pipe -fPIC -funroll-loops + +ifeq ($(debug),1) + OBJ_PREFIX = debug + CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG + +else + OBJ_PREFIX = release + CFLAGS += -O2 +endif + +OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2) + +# +# Linking flags +# +LDFLAGS = -shared -lm -lbluetooth + +# +# Target binaries (always created as BIN) +# +BIN = ./$(OBJ_DIR)/libwiiuse.so + +# +# Inclusion paths. +# +INCLUDES = -I. + +# +# Generate a list of object files +# +OBJS = \ + $(OBJ_DIR)/classic.o \ + $(OBJ_DIR)/dynamics.o \ + $(OBJ_DIR)/events.o \ + $(OBJ_DIR)/io.o \ + $(OBJ_DIR)/io_nix.o \ + $(OBJ_DIR)/ir.o \ + $(OBJ_DIR)/nunchuk.o \ + $(OBJ_DIR)/guitar_hero_3.o \ + $(OBJ_DIR)/wiiuse.o + +############################### +# +# Build targets. +# +############################### + +all: $(BIN) + +clean: + @-rm $(OBJS) 2> /dev/null + +distclean: + @-rm -r debug-* release-* 2> /dev/null + +install: + @if [ -e $(BIN) ]; then \ + cp -v $(BIN) /usr/lib ; \ + fi + @cp -v wiiuse.h /usr/include + +$(BIN): mkdir $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN) + +$(OBJ_DIR)/%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +mkdir: + @if [ ! -d $(OBJ_DIR) ]; then \ + mkdir $(OBJ_DIR); \ + fi + diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.c new file mode 100644 index 0000000000..1d2c3ab275 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.c @@ -0,0 +1,190 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Classic controller expansion device. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#ifdef WIN32 + #include <Winsock2.h> +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "dynamics.h" +#include "events.h" +#include "classic.h" + +static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now); + +/** + * @brief Handle the handshake data from the classic controller. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param data The data read in from the device. + * @param len The length of the data block, in bytes. + * + * @return Returns 1 if handshake was successful, 0 if not. + */ +int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len) { + int i;
+ int offset = 0; + + cc->btns = 0; + cc->btns_held = 0; + cc->btns_released = 0; + cc->r_shoulder = 0; + cc->l_shoulder = 0; + + /* decrypt data */ + for (i = 0; i < len; ++i) + data[i] = (data[i] ^ 0x17) + 0x17; +
+ if (data[offset] == 0xFF) {
+ /*
+ * Sometimes the data returned here is not correct.
+ * This might happen because the wiimote is lagging
+ * behind our initialization sequence.
+ * To fix this just request the handshake again.
+ *
+ * Other times it's just the first 16 bytes are 0xFF,
+ * but since the next 16 bytes are the same, just use
+ * those.
+ */
+ if (data[offset + 16] == 0xFF) {
+ /* get the calibration data */
+ byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+ WIIUSE_DEBUG("Classic controller handshake appears invalid, trying again.");
+ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+ return 0;
+ } else
+ offset += 16;
+ }
+
+ + /* joystick stuff */ + cc->ljs.max.x = data[0 + offset] / 4; + cc->ljs.min.x = data[1 + offset] / 4; + cc->ljs.center.x = data[2 + offset] / 4; + cc->ljs.max.y = data[3 + offset] / 4; + cc->ljs.min.y = data[4 + offset] / 4; + cc->ljs.center.y = data[5 + offset] / 4; + + cc->rjs.max.x = data[6 + offset] / 8; + cc->rjs.min.x = data[7 + offset] / 8; + cc->rjs.center.x = data[8 + offset] / 8; + cc->rjs.max.y = data[9 + offset] / 8; + cc->rjs.min.y = data[10 + offset] / 8; + cc->rjs.center.y = data[11 + offset] / 8; + + /* handshake done */ + wm->exp.type = EXP_CLASSIC; + + #ifdef WIN32 + wm->timeout = WIIMOTE_DEFAULT_TIMEOUT; + #endif + + return 1; +} + + +/** + * @brief The classic controller disconnected. + * + * @param cc A pointer to a classic_ctrl_t structure. + */ +void classic_ctrl_disconnected(struct classic_ctrl_t* cc) { + memset(cc, 0, sizeof(struct classic_ctrl_t)); +} + + + +/** + * @brief Handle classic controller event. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param msg The message specified in the event packet. + */ +void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg) { + int i, lx, ly, rx, ry; + byte l, r; + + /* decrypt data */ + for (i = 0; i < 6; ++i) + msg[i] = (msg[i] ^ 0x17) + 0x17; + + classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4))); + + /* left/right buttons */ + l = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5)); + r = (msg[3] & 0x1F); + + /* + * TODO - LR range hardcoded from 0x00 to 0x1F. + * This is probably in the calibration somewhere. + */ + cc->r_shoulder = ((float)r / 0x1F); + cc->l_shoulder = ((float)l / 0x1F); + + /* calculate joystick orientation */ + lx = (msg[0] & 0x3F); + ly = (msg[1] & 0x3F); + rx = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7); + ry = (msg[2] & 0x1F); + + calc_joystick_state(&cc->ljs, lx, ly); + calc_joystick_state(&cc->rjs, rx, ry); +} + + +/** + * @brief Find what buttons are pressed. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param msg The message byte specified in the event packet. + */ +static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) { + /* message is inverted (0 is active, 1 is inactive) */ + now = ~now & CLASSIC_CTRL_BUTTON_ALL; + + /* pressed now & were pressed, then held */ + cc->btns_held = (now & cc->btns); + + /* were pressed or were held & not pressed now, then released */ + cc->btns_released = ((cc->btns | cc->btns_held) & ~now); + + /* buttons pressed now */ + cc->btns = now; +} diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.h new file mode 100644 index 0000000000..356f6a458b --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.h @@ -0,0 +1,53 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Classic controller expansion device. + */ + +#ifndef CLASSIC_H_INCLUDED +#define CLASSIC_H_INCLUDED + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len); + +void classic_ctrl_disconnected(struct classic_ctrl_t* cc); + +void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg); + +#ifdef __cplusplus +} +#endif + +#endif // CLASSIC_H_INCLUDED diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/definitions.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/definitions.h new file mode 100644 index 0000000000..5a8da85def --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/definitions.h @@ -0,0 +1,79 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief General definitions. + */ + +#ifndef DEFINITIONS_H_INCLUDED +#define DEFINITIONS_H_INCLUDED + +/* this is wiiuse - used to distinguish from third party programs using wiiuse.h */ +#include "os.h" + +#define WIIMOTE_PI 3.14159265f + +//#define WITH_WIIUSE_DEBUG + +/* Error output macros */ +#define WIIUSE_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__) + +/* Warning output macros */ +#define WIIUSE_WARNING(fmt, ...) fprintf(stderr, "[WARNING] " fmt "\n", ##__VA_ARGS__) + +/* Information output macros */ +#define WIIUSE_INFO(fmt, ...) fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__) + +#ifdef WITH_WIIUSE_DEBUG
+ #ifdef WIN32
+ #define WIIUSE_DEBUG(fmt, ...) do { \
+ char* file = __FILE__; \
+ int i = strlen(file) - 1; \
+ for (; i && (file[i] != '\\'); --i); \
+ fprintf(stderr, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__); \
+ } while (0)
+ #else + #define WIIUSE_DEBUG(fmt, ...) fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__)
+ #endif +#else + #define WIIUSE_DEBUG(fmt, ...) +#endif + +/* Convert between radians and degrees */ +#define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI) +#define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f)) + +/* Convert to big endian */ +#define BIG_ENDIAN_LONG(i) (htonl(i)) +#define BIG_ENDIAN_SHORT(i) (htons(i)) + +#define absf(x) ((x >= 0) ? (x) : (x * -1.0f)) +#define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x))) + +#endif // DEFINITIONS_H_INCLUDED diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.c new file mode 100644 index 0000000000..53612a6b90 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.c @@ -0,0 +1,228 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles the dynamics of the wiimote. + * + * The file includes functions that handle the dynamics + * of the wiimote. Such dynamics include orientation and + * motion sensing. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#ifdef WIN32 + #include <float.h> +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "ir.h" +#include "dynamics.h" + +/** + * @brief Calculate the roll, pitch, yaw. + * + * @param ac An accelerometer (accel_t) structure. + * @param accel [in] Pointer to a vec3b_t structure that holds the raw acceleration data. + * @param orient [out] Pointer to a orient_t structure that will hold the orientation data. + * @param rorient [out] Pointer to a orient_t structure that will hold the non-smoothed orientation data. + * @param smooth If smoothing should be performed on the angles calculated. 1 to enable, 0 to disable. + * + * Given the raw acceleration data from the accelerometer struct, calculate + * the orientation of the device and set it in the \a orient parameter. + */ +void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth) { + float xg, yg, zg; + float x, y, z; + + /* + * roll - use atan(z / x) [ ranges from -180 to 180 ] + * pitch - use atan(z / y) [ ranges from -180 to 180 ] + * yaw - impossible to tell without IR + */ + + /* yaw - set to 0, IR will take care of it if it's enabled */ + orient->yaw = 0.0f; + + /* find out how much it has to move to be 1g */ + xg = (float)ac->cal_g.x; + yg = (float)ac->cal_g.y; + zg = (float)ac->cal_g.z; + + /* find out how much it actually moved and normalize to +/- 1g */ + x = ((float)accel->x - (float)ac->cal_zero.x) / xg; + y = ((float)accel->y - (float)ac->cal_zero.y) / yg; + z = ((float)accel->z - (float)ac->cal_zero.z) / zg; + + /* make sure x,y,z are between -1 and 1 for the tan functions */ + if (x < -1.0f) x = -1.0f; + else if (x > 1.0f) x = 1.0f; + if (y < -1.0f) y = -1.0f; + else if (y > 1.0f) y = 1.0f; + if (z < -1.0f) z = -1.0f; + else if (z > 1.0f) z = 1.0f; + + /* if it is over 1g then it is probably accelerating and not reliable */ + if (abs(accel->x - ac->cal_zero.x) <= ac->cal_g.x) { + /* roll */ + x = RAD_TO_DEGREE(atan2f(x, z)); + + orient->roll = x; + orient->a_roll = x; + } + + if (abs(accel->y - ac->cal_zero.y) <= ac->cal_g.y) { + /* pitch */ + y = RAD_TO_DEGREE(atan2f(y, z)); + + orient->pitch = y; + orient->a_pitch = y; + } +
+ /* smooth the angles if enabled */
+ if (smooth) {
+ apply_smoothing(ac, orient, SMOOTH_ROLL);
+ apply_smoothing(ac, orient, SMOOTH_PITCH);
+ }
+} + + +/** + * @brief Calculate the gravity forces on each axis. + * + * @param ac An accelerometer (accel_t) structure. + * @param accel [in] Pointer to a vec3b_t structure that holds the raw acceleration data. + * @param gforce [out] Pointer to a gforce_t structure that will hold the gravity force data. + */ +void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce) { + float xg, yg, zg; + + /* find out how much it has to move to be 1g */ + xg = (float)ac->cal_g.x; + yg = (float)ac->cal_g.y; + zg = (float)ac->cal_g.z; + + /* find out how much it actually moved and normalize to +/- 1g */ + gforce->x = ((float)accel->x - (float)ac->cal_zero.x) / xg; + gforce->y = ((float)accel->y - (float)ac->cal_zero.y) / yg; + gforce->z = ((float)accel->z - (float)ac->cal_zero.z) / zg; +} + + +/** + * @brief Calculate the angle and magnitude of a joystick. + * + * @param js [out] Pointer to a joystick_t structure. + * @param x The raw x-axis value. + * @param y The raw y-axis value. + */ +void calc_joystick_state(struct joystick_t* js, float x, float y) { + float rx, ry, ang; + + /* + * Since the joystick center may not be exactly: + * (min + max) / 2 + * Then the range from the min to the center and the center to the max + * may be different. + * Because of this, depending on if the current x or y value is greater + * or less than the assoicated axis center value, it needs to be interpolated + * between the center and the minimum or maxmimum rather than between + * the minimum and maximum. + * + * So we have something like this: + * (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max) + * Where the * is the current x value. + * The range is therefore -1 to 1, 0 being the exact center rather than + * the middle of min and max. + */ + if (x == js->center.x) + rx = 0; + else if (x >= js->center.x) + rx = ((float)(x - js->center.x) / (float)(js->max.x - js->center.x)); + else + rx = ((float)(x - js->min.x) / (float)(js->center.x - js->min.x)) - 1.0f; + + if (y == js->center.y) + ry = 0; + else if (y >= js->center.y) + ry = ((float)(y - js->center.y) / (float)(js->max.y - js->center.y)); + else + ry = ((float)(y - js->min.y) / (float)(js->center.y - js->min.y)) - 1.0f; + + /* calculate the joystick angle and magnitude */ + ang = RAD_TO_DEGREE(atanf(ry / rx)); + ang -= 90.0f; + if (rx < 0.0f) + ang -= 180.0f; + js->ang = absf(ang); + js->mag = (float) sqrt((rx * rx) + (ry * ry)); +} + + +void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type) { + switch (type) { + case SMOOTH_ROLL: + {
+ /* it's possible last iteration was nan or inf, so set it to 0 if that happened */ + if (isnan(ac->st_roll) || isinf(ac->st_roll)) + ac->st_roll = 0.0f; + + /* + * If the sign changes (which will happen if going from -180 to 180) + * or from (-1 to 1) then don't smooth, just use the new angle. + */ + if (((ac->st_roll < 0) && (orient->roll > 0)) || ((ac->st_roll > 0) && (orient->roll < 0))) { + ac->st_roll = orient->roll; + } else { + orient->roll = ac->st_roll + (ac->st_alpha * (orient->a_roll - ac->st_roll)); + ac->st_roll = orient->roll; + } + + return; + } + + case SMOOTH_PITCH: + { + if (isnan(ac->st_pitch) || isinf(ac->st_pitch)) + ac->st_pitch = 0.0f; + + if (((ac->st_pitch < 0) && (orient->pitch > 0)) || ((ac->st_pitch > 0) && (orient->pitch < 0))) { + ac->st_pitch = orient->pitch; + } else { + orient->pitch = ac->st_pitch + (ac->st_alpha * (orient->a_pitch - ac->st_pitch)); + ac->st_pitch = orient->pitch; + } + + return; + } + } +} diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.h new file mode 100644 index 0000000000..2a8f96500b --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.h @@ -0,0 +1,56 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles the dynamics of the wiimote. + * + * The file includes functions that handle the dynamics + * of the wiimote. Such dynamics include orientation and + * motion sensing. + */ + +#ifndef DYNAMICS_H_INCLUDED +#define DYNAMICS_H_INCLUDED + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth); +void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce); +void calc_joystick_state(struct joystick_t* js, float x, float y); +void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type); + +#ifdef __cplusplus +} +#endif + +#endif // DYNAMICS_H_INCLUDED diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.c new file mode 100644 index 0000000000..6668eda5c8 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.c @@ -0,0 +1,878 @@ +/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles wiimote events.
+ *
+ * The file includes functions that handle the events
+ * that are sent from the wiimote to us.
+ */
+
+#include <stdio.h>
+
+#ifndef WIN32
+ #include <sys/time.h>
+ #include <unistd.h>
+ #include <errno.h> +#else
+ #include <winsock2.h> +#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "definitions.h"
+#include "io.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "ir.h"
+#include "nunchuk.h"
+#include "classic.h"
+#include "guitar_hero_3.h"
+#include "events.h"
+
+static void idle_cycle(struct wiimote_t* wm);
+static void clear_dirty_reads(struct wiimote_t* wm); +static void propagate_event(struct wiimote_t* wm, byte event, byte* msg);
+static void event_data_read(struct wiimote_t* wm, byte* msg);
+static void event_status(struct wiimote_t* wm, byte* msg);
+static void handle_expansion(struct wiimote_t* wm, byte* msg);
+
+static void save_state(struct wiimote_t* wm);
+static int state_changed(struct wiimote_t* wm);
+
+/**
+ * @brief Poll the wiimotes for any events.
+ *
+ * @param wm An array of pointers to wiimote_t structures.
+ * @param wiimotes The number of wiimote_t structures in the \a wm array.
+ *
+ * @return Returns number of wiimotes that an event has occured on.
+ *
+ * It is necessary to poll the wiimote devices for events
+ * that occur. If an event occurs on a particular wiimote,
+ * the event variable will be set.
+ */
+int wiiuse_poll(struct wiimote_t** wm, int wiimotes) {
+ int evnt = 0;
+
+ #ifndef WIN32
+ /*
+ * *nix
+ */
+ struct timeval tv;
+ fd_set fds;
+ int r;
+ int i;
+ int highest_fd = -1;
+
+ if (!wm) return 0;
+
+ /* block select() for 1/2000th of a second */
+ tv.tv_sec = 0;
+ tv.tv_usec = 500;
+
+ FD_ZERO(&fds);
+
+ for (i = 0; i < wiimotes; ++i) {
+ /* only poll it if it is connected */
+ if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) {
+ FD_SET(wm[i]->in_sock, &fds);
+
+ /* find the highest fd of the connected wiimotes */
+ if (wm[i]->in_sock > highest_fd)
+ highest_fd = wm[i]->in_sock;
+ }
+
+ wm[i]->event = WIIUSE_NONE;
+ }
+
+ if (highest_fd == -1)
+ /* nothing to poll */
+ return 0;
+
+ if (select(highest_fd + 1, &fds, NULL, NULL, &tv) == -1) {
+ WIIUSE_ERROR("Unable to select() the wiimote interrupt socket(s).");
+ perror("Error Details");
+ return 0;
+ }
+
+ /* check each socket for an event */
+ for (i = 0; i < wiimotes; ++i) {
+ /* if this wiimote is not connected, skip it */
+ if (!WIIMOTE_IS_CONNECTED(wm[i]))
+ continue;
+
+ if (FD_ISSET(wm[i]->in_sock, &fds)) {
+ /* clear out the event buffer */
+ memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf)); + + /* clear out any old read requests */ + clear_dirty_reads(wm[i]);
+
+ /* read the pending message into the buffer */
+ r = read(wm[i]->in_sock, wm[i]->event_buf, sizeof(wm[i]->event_buf));
+ if (r == -1) {
+ /* error reading data */
+ WIIUSE_ERROR("Receiving wiimote data (id %i).", wm[i]->unid); + perror("Error Details"); + + if (errno == ENOTCONN) { + /* this can happen if the bluetooth dongle is disconnected */ + WIIUSE_ERROR("Bluetooth appears to be disconnected. Wiimote unid %i will be disconnected.", wm[i]->unid); + wiiuse_disconnect(wm[i]); + wm[i]->event = WIIUSE_UNEXPECTED_DISCONNECT; + } +
+ continue;
+ }
+ if (!r) {
+ /* remote disconnect */
+ wiiuse_disconnected(wm[i]);
+ evnt = 1;
+ continue;
+ }
+
+ /* propagate the event */
+ propagate_event(wm[i], wm[i]->event_buf[1], wm[i]->event_buf+2);
+ evnt += (wm[i]->event != WIIUSE_NONE);
+ } else {
+ idle_cycle(wm[i]);
+ }
+ }
+ #else
+ /*
+ * Windows
+ */
+ int i;
+
+ if (!wm) return 0;
+
+ for (i = 0; i < wiimotes; ++i) {
+ wm[i]->event = WIIUSE_NONE;
+
+ if (wiiuse_io_read(wm[i])) {
+ /* propagate the event */
+ propagate_event(wm[i], wm[i]->event_buf[0], wm[i]->event_buf+1);
+ evnt += (wm[i]->event != WIIUSE_NONE);
+
+ /* clear out the event buffer */
+ memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
+ } else {
+ idle_cycle(wm[i]);
+ }
+ }
+ #endif
+
+ return evnt;
+}
+
+
+/**
+ * @brief Called on a cycle where no significant change occurs.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+static void idle_cycle(struct wiimote_t* wm) {
+ /*
+ * Smooth the angles.
+ *
+ * This is done to make sure that on every cycle the orientation
+ * angles are smoothed. Normally when an event occurs the angles
+ * are updated and smoothed, but if no packet comes in then the
+ * angles remain the same. This means the angle wiiuse reports
+ * is still an old value. Smoothing needs to be applied in this
+ * case in order for the angle it reports to converge to the true
+ * angle of the device.
+ */
+ if (WIIUSE_USING_ACC(wm) && WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)) {
+ apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_ROLL);
+ apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_PITCH);
+ }
+ + /* clear out any old read requests */ + clear_dirty_reads(wm); +} + + +/** + * @brief Clear out all old 'dirty' read requests. + * + * @param wm Pointer to a wiimote_t structure. + */ +static void clear_dirty_reads(struct wiimote_t* wm) { + struct read_req_t* req = wm->read_req; + + while (req && req->dirty) { + WIIUSE_DEBUG("Cleared old read request for address: %x", req->addr); + + wm->read_req = req->next; + free(req); + req = wm->read_req; + } +}
+
+
+/**
+ * @brief Analyze the event that occured on a wiimote.
+ *
+ * @param wm An array of pointers to wiimote_t structures.
+ * @param event The event that occured.
+ * @param msg The message specified in the event packet.
+ *
+ * Pass the event to the registered event callback.
+ */
+static void propagate_event(struct wiimote_t* wm, byte event, byte* msg) {
+ save_state(wm);
+
+ switch (event) {
+ case WM_RPT_BTN:
+ {
+ /* button */
+ wiiuse_pressed_buttons(wm, msg);
+ break;
+ }
+ case WM_RPT_BTN_ACC:
+ {
+ /* button - motion */
+ wiiuse_pressed_buttons(wm, msg);
+
+ wm->accel.x = msg[2];
+ wm->accel.y = msg[3];
+ wm->accel.z = msg[4];
+
+ /* calculate the remote orientation */
+ calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+
+ /* calculate the gforces on each axis */
+ calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+ break;
+ }
+ case WM_RPT_READ:
+ {
+ /* data read */
+ event_data_read(wm, msg);
+
+ /* yeah buttons may be pressed, but this wasn't an "event" */
+ return;
+ }
+ case WM_RPT_CTRL_STATUS:
+ {
+ /* controller status */
+ event_status(wm, msg);
+
+ /* don't execute the event callback */
+ return;
+ }
+ case WM_RPT_BTN_EXP:
+ {
+ /* button - expansion */
+ wiiuse_pressed_buttons(wm, msg);
+ handle_expansion(wm, msg+2);
+
+ break;
+ }
+ case WM_RPT_BTN_ACC_EXP:
+ {
+ /* button - motion - expansion */
+ wiiuse_pressed_buttons(wm, msg);
+
+ wm->accel.x = msg[2];
+ wm->accel.y = msg[3];
+ wm->accel.z = msg[4];
+
+ calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+ calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+ handle_expansion(wm, msg+5);
+
+ break;
+ }
+ case WM_RPT_BTN_ACC_IR:
+ {
+ /* button - motion - ir */
+ wiiuse_pressed_buttons(wm, msg);
+
+ wm->accel.x = msg[2];
+ wm->accel.y = msg[3];
+ wm->accel.z = msg[4];
+
+ calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+ calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+ /* ir */
+ calculate_extended_ir(wm, msg+5);
+
+ break;
+ }
+ case WM_RPT_BTN_IR_EXP:
+ {
+ /* button - ir - expansion */
+ wiiuse_pressed_buttons(wm, msg);
+ handle_expansion(wm, msg+12);
+
+ /* ir */
+ calculate_basic_ir(wm, msg+2);
+
+ break;
+ }
+ case WM_RPT_BTN_ACC_IR_EXP:
+ {
+ /* button - motion - ir - expansion */
+ wiiuse_pressed_buttons(wm, msg);
+
+ wm->accel.x = msg[2];
+ wm->accel.y = msg[3];
+ wm->accel.z = msg[4];
+
+ calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+ calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+ handle_expansion(wm, msg+15);
+
+ /* ir */
+ calculate_basic_ir(wm, msg+5);
+
+ break;
+ }
+ case WM_RPT_WRITE:
+ {
+ /* write feedback - safe to skip */
+ break;
+ }
+ default:
+ {
+ WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event);
+ return;
+ }
+ }
+
+ /* was there an event? */
+ if (state_changed(wm))
+ wm->event = WIIUSE_EVENT;
+}
+
+
+/**
+ * @brief Find what buttons are pressed.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param msg The message specified in the event packet.
+ */
+void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg) {
+ short now;
+
+ /* convert to big endian */
+ now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
+
+ /* pressed now & were pressed, then held */
+ wm->btns_held = (now & wm->btns);
+
+ /* were pressed or were held & not pressed now, then released */
+ wm->btns_released = ((wm->btns | wm->btns_held) & ~now);
+
+ /* buttons pressed now */
+ wm->btns = now;
+}
+
+
+/**
+ * @brief Received a data packet from a read request.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param msg The message specified in the event packet.
+ *
+ * Data from the wiimote comes in packets. If the requested
+ * data segment size is bigger than one packet can hold then
+ * several packets will be received. These packets are first
+ * reassembled into one, then the registered callback function
+ * that handles data reads is invoked.
+ */
+static void event_data_read(struct wiimote_t* wm, byte* msg) {
+ /* we must always assume the packet received is from the most recent request */
+ byte err;
+ byte len;
+ unsigned short offset;
+ struct read_req_t* req = wm->read_req;
+
+ wiiuse_pressed_buttons(wm, msg);
+ + /* find the next non-dirty request */ + while (req && req->dirty) + req = req->next; +
+ /* if we don't have a request out then we didn't ask for this packet */
+ if (!req) {
+ WIIUSE_WARNING("Received data packet when no request was made.");
+ return;
+ }
+
+ err = msg[2] & 0x0F;
+
+ if (err == 0x08)
+ WIIUSE_WARNING("Unable to read data - address does not exist.");
+ else if (err == 0x07)
+ WIIUSE_WARNING("Unable to read data - address is for write-only registers.");
+ else if (err)
+ WIIUSE_WARNING("Unable to read data - unknown error code %x.", err);
+
+ if (err) {
+ /* this request errored out, so skip it and go to the next one */
+
+ /* delete this request */
+ wm->read_req = req->next;
+ free(req);
+
+ /* if another request exists send it to the wiimote */
+ if (wm->read_req)
+ wiiuse_send_next_pending_read_request(wm);
+
+ return;
+ }
+
+ len = ((msg[2] & 0xF0) >> 4) + 1;
+ offset = BIG_ENDIAN_SHORT(*(unsigned short*)(msg + 3));
+ req->addr = (req->addr & 0xFFFF);
+
+ req->wait -= len;
+ if (req->wait >= req->size)
+ /* this should never happen */
+ req->wait = 0;
+
+ WIIUSE_DEBUG("Received read packet:");
+ WIIUSE_DEBUG(" Packet read offset: %i bytes", offset);
+ WIIUSE_DEBUG(" Request read offset: %i bytes", req->addr);
+ WIIUSE_DEBUG(" Read offset into buf: %i bytes", offset - req->addr);
+ WIIUSE_DEBUG(" Read data size: %i bytes", len);
+ WIIUSE_DEBUG(" Still need: %i bytes", req->wait);
+
+ /* reconstruct this part of the data */
+ memcpy((req->buf + offset - req->addr), (msg + 5), len);
+
+ #ifdef WITH_WIIUSE_DEBUG
+ {
+ int i = 0;
+ printf("Read: ");
+ for (; i < req->size - req->wait; ++i)
+ printf("%x ", req->buf[i]);
+ printf("\n");
+ }
+ #endif
+
+ /* if all data has been received, execute the read event callback or generate event */
+ if (!req->wait) { + if (req->cb) { + /* this was a callback, so invoke it now */
+ req->cb(wm, req->buf, req->size);
+
+ /* delete this request */
+ wm->read_req = req->next;
+ free(req); + } else { + /* + * This should generate an event. + * We need to leave the event in the array so the client + * can access it still. We'll flag is as being 'dirty' + * and give the client one cycle to use it. Next event + * we will remove it from the list. + */ + wm->event = WIIUSE_READ_DATA; + req->dirty = 1; + }
+
+ /* if another request exists send it to the wiimote */
+ if (wm->read_req)
+ wiiuse_send_next_pending_read_request(wm);
+ }
+}
+
+
+/**
+ * @brief Read the controller status.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param msg The message specified in the event packet.
+ *
+ * Read the controller status and execute the registered status callback.
+ */
+static void event_status(struct wiimote_t* wm, byte* msg) {
+ int led[4] = {0};
+ int attachment = 0;
+ int ir = 0;
+ int exp_changed = 0;
+
+ /*
+ * An event occured.
+ * This event can be overwritten by a more specific
+ * event type during a handshake or expansion removal.
+ */
+ wm->event = WIIUSE_STATUS;
+
+ wiiuse_pressed_buttons(wm, msg);
+
+ /* find what LEDs are lit */
+ if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_1) led[0] = 1;
+ if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_2) led[1] = 1;
+ if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_3) led[2] = 1;
+ if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_4) led[3] = 1;
+
+ /* is an attachment connected to the expansion port? */
+ if ((msg[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT)
+ attachment = 1;
+
+ /* is the speaker enabled? */
+ if ((msg[2] & WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) == WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED)
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_SPEAKER);
+
+ /* is IR sensing enabled? */
+ if ((msg[2] & WM_CTRL_STATUS_BYTE1_IR_ENABLED) == WM_CTRL_STATUS_BYTE1_IR_ENABLED)
+ ir = 1;
+
+ /* find the battery level and normalize between 0 and 1 */
+ wm->battery_level = (msg[5] / (float)WM_MAX_BATTERY_CODE);
+
+ /* expansion port */
+ if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
+ /* send the initialization code for the attachment */
+ handshake_expansion(wm, NULL, 0);
+ exp_changed = 1;
+ } else if (!attachment && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
+ /* attachment removed */
+ disable_expansion(wm);
+ exp_changed = 1;
+ }
+
+ #ifdef WIN32
+ if (!attachment) {
+ WIIUSE_DEBUG("Setting timeout to normal %i ms.", wm->normal_timeout);
+ wm->timeout = wm->normal_timeout;
+ }
+ #endif
+
+ /*
+ * From now on the remote will only send status packets.
+ * We need to send a WIIMOTE_CMD_REPORT_TYPE packet to
+ * reenable other incoming reports.
+ */
+ if (exp_changed && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
+ /*
+ * Since the expansion status changed IR needs to
+ * be reset for the new IR report mode.
+ */
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
+ wiiuse_set_ir(wm, 1);
+ } else
+ wiiuse_set_report_type(wm);
+}
+
+
+/**
+ * @brief Handle data from the expansion.
+ *
+ * @param wm A pointer to a wiimote_t structure.
+ * @param msg The message specified in the event packet for the expansion.
+ */
+static void handle_expansion(struct wiimote_t* wm, byte* msg) {
+ switch (wm->exp.type) {
+ case EXP_NUNCHUK:
+ nunchuk_event(&wm->exp.nunchuk, msg);
+ break;
+ case EXP_CLASSIC:
+ classic_ctrl_event(&wm->exp.classic, msg);
+ break;
+ case EXP_GUITAR_HERO_3:
+ guitar_hero_3_event(&wm->exp.gh3, msg);
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
+ * @brief Handle the handshake data from the expansion device.
+ *
+ * @param wm A pointer to a wiimote_t structure.
+ * @param data The data read in from the device.
+ * @param len The length of the data block, in bytes.
+ *
+ * Tries to determine what kind of expansion was attached
+ * and invoke the correct handshake function.
+ *
+ * If the data is NULL then this function will try to start
+ * a handshake with the expansion.
+ */
+void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len) {
+ int id;
+
+ if (!data) {
+ byte* handshake_buf;
+ byte buf = 0x00;
+
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
+ disable_expansion(wm);
+
+ /* increase the timeout until the handshake completes */
+ #ifdef WIN32
+ WIIUSE_DEBUG("Setting timeout to expansion %i ms.", wm->exp_timeout);
+ wm->timeout = wm->exp_timeout;
+ #endif
+
+ wiiuse_write_data(wm, WM_EXP_MEM_ENABLE, &buf, 1);
+
+ /* get the calibration data */
+ handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+ /* tell the wiimote to send expansion data */
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP);
+
+ return;
+ }
+
+ id = BIG_ENDIAN_LONG(*(int*)(data + 220));
+
+ /* call the corresponding handshake function for this expansion */
+ switch (id) {
+ case EXP_ID_CODE_NUNCHUK:
+ {
+ if (nunchuk_handshake(wm, &wm->exp.nunchuk, data, len))
+ wm->event = WIIUSE_NUNCHUK_INSERTED;
+ break;
+ }
+ case EXP_ID_CODE_CLASSIC_CONTROLLER:
+ { + if (classic_ctrl_handshake(wm, &wm->exp.classic, data, len))
+ wm->event = WIIUSE_CLASSIC_CTRL_INSERTED; + break;
+ }
+ case EXP_ID_CODE_GUITAR:
+ {
+ if (guitar_hero_3_handshake(wm, &wm->exp.gh3, data, len))
+ wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED;
+ break;
+ }
+ default:
+ {
+ WIIUSE_WARNING("Unknown expansion type. Code: 0x%x", id);
+ break;
+ }
+ }
+
+ free(data);
+}
+
+
+
+/**
+ * @brief Disable the expansion device if it was enabled.
+ *
+ * @param wm A pointer to a wiimote_t structure.
+ * @param data The data read in from the device.
+ * @param len The length of the data block, in bytes.
+ *
+ * If the data is NULL then this function will try to start
+ * a handshake with the expansion.
+ */
+void disable_expansion(struct wiimote_t* wm) {
+ if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
+ return;
+
+ /* tell the assoicated module the expansion was removed */
+ switch (wm->exp.type) {
+ case EXP_NUNCHUK:
+ nunchuk_disconnected(&wm->exp.nunchuk);
+ wm->event = WIIUSE_NUNCHUK_REMOVED;
+ break;
+ case EXP_CLASSIC:
+ classic_ctrl_disconnected(&wm->exp.classic);
+ wm->event = WIIUSE_CLASSIC_CTRL_REMOVED;
+ break;
+ case EXP_GUITAR_HERO_3:
+ guitar_hero_3_disconnected(&wm->exp.gh3);
+ wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED;
+ break;
+ default:
+ break;
+ }
+
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
+ wm->exp.type = EXP_NONE;
+}
+
+
+/**
+ * @brief Save important state data.
+ * @param wm A pointer to a wiimote_t structure.
+ */
+static void save_state(struct wiimote_t* wm) {
+ /* wiimote */
+ wm->lstate.btns = wm->btns;
+ wm->lstate.accel = wm->accel;
+
+ /* ir */
+ if (WIIUSE_USING_IR(wm)) {
+ wm->lstate.ir_ax = wm->ir.ax;
+ wm->lstate.ir_ay = wm->ir.ay;
+ wm->lstate.ir_distance = wm->ir.distance;
+ }
+
+ /* expansion */
+ switch (wm->exp.type) {
+ case EXP_NUNCHUK:
+ wm->lstate.exp_ljs_ang = wm->exp.nunchuk.js.ang;
+ wm->lstate.exp_ljs_mag = wm->exp.nunchuk.js.mag;
+ wm->lstate.exp_btns = wm->exp.nunchuk.btns;
+ wm->lstate.exp_accel = wm->exp.nunchuk.accel;
+ break;
+
+ case EXP_CLASSIC:
+ wm->lstate.exp_ljs_ang = wm->exp.classic.ljs.ang;
+ wm->lstate.exp_ljs_mag = wm->exp.classic.ljs.mag;
+ wm->lstate.exp_rjs_ang = wm->exp.classic.rjs.ang;
+ wm->lstate.exp_rjs_mag = wm->exp.classic.rjs.mag;
+ wm->lstate.exp_r_shoulder = wm->exp.classic.r_shoulder;
+ wm->lstate.exp_l_shoulder = wm->exp.classic.l_shoulder;
+ wm->lstate.exp_btns = wm->exp.classic.btns;
+ break;
+
+ case EXP_GUITAR_HERO_3:
+ wm->lstate.exp_ljs_ang = wm->exp.gh3.js.ang;
+ wm->lstate.exp_ljs_mag = wm->exp.gh3.js.mag;
+ wm->lstate.exp_r_shoulder = wm->exp.gh3.whammy_bar;
+ wm->lstate.exp_btns = wm->exp.gh3.btns;
+ break;
+
+ case EXP_NONE:
+ break;
+ }
+}
+
+
+/**
+ * @brief Determine if the current state differs significantly from the previous.
+ * @param wm A pointer to a wiimote_t structure.
+ * @return 1 if a significant change occured, 0 if not.
+ */
+static int state_changed(struct wiimote_t* wm) {
+ #define STATE_CHANGED(a, b) if (a != b) return 1
+
+ #define CROSS_THRESH(last, now, thresh) \
+ do { \
+ if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \
+ if ((diff_f(last.roll, now.roll) >= thresh) || \
+ (diff_f(last.pitch, now.pitch) >= thresh) || \
+ (diff_f(last.yaw, now.yaw) >= thresh)) \
+ { \
+ last = now; \
+ return 1; \
+ } \
+ } else { \
+ if (last.roll != now.roll) return 1; \
+ if (last.pitch != now.pitch) return 1; \
+ if (last.yaw != now.yaw) return 1; \
+ } \
+ } while (0)
+
+ #define CROSS_THRESH_XYZ(last, now, thresh) \
+ do { \
+ if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \
+ if ((diff_f(last.x, now.x) >= thresh) || \
+ (diff_f(last.y, now.y) >= thresh) || \
+ (diff_f(last.z, now.z) >= thresh)) \
+ { \
+ last = now; \
+ return 1; \
+ } \
+ } else { \
+ if (last.x != now.x) return 1; \
+ if (last.y != now.y) return 1; \
+ if (last.z != now.z) return 1; \
+ } \
+ } while (0)
+
+ /* ir */
+ if (WIIUSE_USING_IR(wm)) {
+ STATE_CHANGED(wm->lstate.ir_ax, wm->ir.ax);
+ STATE_CHANGED(wm->lstate.ir_ay, wm->ir.ay);
+ STATE_CHANGED(wm->lstate.ir_distance, wm->ir.distance);
+ }
+
+ /* accelerometer */
+ if (WIIUSE_USING_ACC(wm)) {
+ /* raw accelerometer */
+ CROSS_THRESH_XYZ(wm->lstate.accel, wm->accel, wm->accel_threshold);
+
+ /* orientation */
+ CROSS_THRESH(wm->lstate.orient, wm->orient, wm->orient_threshold);
+ }
+
+ /* expansion */
+ switch (wm->exp.type) {
+ case EXP_NUNCHUK:
+ {
+ STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.nunchuk.js.ang);
+ STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.nunchuk.js.mag);
+ STATE_CHANGED(wm->lstate.exp_btns, wm->exp.nunchuk.btns);
+
+ CROSS_THRESH(wm->lstate.exp_orient, wm->exp.nunchuk.orient, wm->exp.nunchuk.orient_threshold);
+ CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->exp.nunchuk.accel, wm->exp.nunchuk.accel_threshold);
+ break;
+ }
+ case EXP_CLASSIC:
+ {
+ STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.classic.ljs.ang);
+ STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.classic.ljs.mag);
+ STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->exp.classic.rjs.ang);
+ STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->exp.classic.rjs.mag);
+ STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.classic.r_shoulder);
+ STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->exp.classic.l_shoulder);
+ STATE_CHANGED(wm->lstate.exp_btns, wm->exp.classic.btns);
+ break;
+ }
+ case EXP_GUITAR_HERO_3:
+ {
+ STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.gh3.js.ang);
+ STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.gh3.js.mag);
+ STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.gh3.whammy_bar);
+ STATE_CHANGED(wm->lstate.exp_btns, wm->exp.gh3.btns);
+ break;
+ }
+ case EXP_NONE:
+ {
+ break;
+ }
+ }
+
+ STATE_CHANGED(wm->lstate.btns, wm->btns);
+
+ return 0;
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.h new file mode 100644 index 0000000000..5e9b955c55 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.h @@ -0,0 +1,54 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles wiimote events. + * + * The file includes functions that handle the events + * that are sent from the wiimote to us. + */ + +#ifndef EVENTS_H_INCLUDED +#define EVENTS_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg); + +void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len); +void disable_expansion(struct wiimote_t* wm);
+ +#ifdef __cplusplus +} +#endif + + +#endif // EVENTS_H_INCLUDED diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.c new file mode 100644 index 0000000000..5837dc016f --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.c @@ -0,0 +1,172 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Guitar Hero 3 expansion device. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#ifdef WIN32 + #include <Winsock2.h> +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "dynamics.h" +#include "events.h" +#include "guitar_hero_3.h" + +static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now); + +/** + * @brief Handle the handshake data from the guitar. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param data The data read in from the device. + * @param len The length of the data block, in bytes. + * + * @return Returns 1 if handshake was successful, 0 if not. + */ +int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len) { + int i;
+ int offset = 0; + + /* + * The good fellows that made the Guitar Hero 3 controller + * failed to factory calibrate the devices. There is no + * calibration data on the device. + */ + + gh3->btns = 0; + gh3->btns_held = 0; + gh3->btns_released = 0; + gh3->whammy_bar = 0.0f; + + /* decrypt data */ + for (i = 0; i < len; ++i) + data[i] = (data[i] ^ 0x17) + 0x17; +
+ if (data[offset] == 0xFF) {
+ /*
+ * Sometimes the data returned here is not correct.
+ * This might happen because the wiimote is lagging
+ * behind our initialization sequence.
+ * To fix this just request the handshake again.
+ *
+ * Other times it's just the first 16 bytes are 0xFF,
+ * but since the next 16 bytes are the same, just use
+ * those.
+ */
+ if (data[offset + 16] == 0xFF) {
+ /* get the calibration data */
+ byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+ WIIUSE_DEBUG("Guitar Hero 3 handshake appears invalid, trying again.");
+ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+ return 0;
+ } else
+ offset += 16;
+ }
+ + /* joystick stuff */ + gh3->js.max.x = GUITAR_HERO_3_JS_MAX_X; + gh3->js.min.x = GUITAR_HERO_3_JS_MIN_X; + gh3->js.center.x = GUITAR_HERO_3_JS_CENTER_X; + gh3->js.max.y = GUITAR_HERO_3_JS_MAX_Y; + gh3->js.min.y = GUITAR_HERO_3_JS_MIN_Y; + gh3->js.center.y = GUITAR_HERO_3_JS_CENTER_Y; + + /* handshake done */ + wm->exp.type = EXP_GUITAR_HERO_3; + + #ifdef WIN32 + wm->timeout = WIIMOTE_DEFAULT_TIMEOUT; + #endif + + return 1; +} + + +/** + * @brief The guitar disconnected. + * + * @param cc A pointer to a classic_ctrl_t structure. + */ +void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3) { + memset(gh3, 0, sizeof(struct guitar_hero_3_t)); +} + + + +/** + * @brief Handle guitar event. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param msg The message specified in the event packet. + */ +void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg) { + int i; + + /* decrypt data */ + for (i = 0; i < 6; ++i) + msg[i] = (msg[i] ^ 0x17) + 0x17; + + guitar_hero_3_pressed_buttons(gh3, BIG_ENDIAN_SHORT(*(short*)(msg + 4))); + + /* whammy bar */ + gh3->whammy_bar = (msg[3] - GUITAR_HERO_3_WHAMMY_BAR_MIN) / (float)(GUITAR_HERO_3_WHAMMY_BAR_MAX - GUITAR_HERO_3_WHAMMY_BAR_MIN); + + /* joy stick */ + calc_joystick_state(&gh3->js, msg[0], msg[1]); +} + + +/** + * @brief Find what buttons are pressed. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param msg The message byte specified in the event packet. + */ +static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now) { + /* message is inverted (0 is active, 1 is inactive) */ + now = ~now & GUITAR_HERO_3_BUTTON_ALL; + + /* pressed now & were pressed, then held */ + gh3->btns_held = (now & gh3->btns); + + /* were pressed or were held & not pressed now, then released */ + gh3->btns_released = ((gh3->btns | gh3->btns_held) & ~now); + + /* buttons pressed now */ + gh3->btns = now; +} diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.h new file mode 100644 index 0000000000..024d603177 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.h @@ -0,0 +1,62 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Guitar Hero 3 expansion device. + */ + +#ifndef GUITAR_HERO_3_H_INCLUDED +#define GUITAR_HERO_3_H_INCLUDED + +#include "wiiuse_internal.h" + +#define GUITAR_HERO_3_JS_MIN_X 0xC5 +#define GUITAR_HERO_3_JS_MAX_X 0xFC +#define GUITAR_HERO_3_JS_CENTER_X 0xE0 +#define GUITAR_HERO_3_JS_MIN_Y 0xC5 +#define GUITAR_HERO_3_JS_MAX_Y 0xFA +#define GUITAR_HERO_3_JS_CENTER_Y 0xE0 +#define GUITAR_HERO_3_WHAMMY_BAR_MIN 0xEF +#define GUITAR_HERO_3_WHAMMY_BAR_MAX 0xFA + +#ifdef __cplusplus +extern "C" { +#endif + +int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len); + +void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3); + +void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg); + +#ifdef __cplusplus +} +#endif + +#endif // GUITAR_HERO_3_H_INCLUDED diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.c new file mode 100644 index 0000000000..ae420b9ef3 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.c @@ -0,0 +1,119 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O (non-OS specific). + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "io.h" + + + /** + * @brief Get initialization data from the wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * @param data unused + * @param len unused + * + * When first called for a wiimote_t structure, a request + * is sent to the wiimote for initialization information. + * This includes factory set accelerometer data. + * The handshake will be concluded when the wiimote responds + * with this data. + */ +void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len) { + if (!wm) return; + + switch (wm->handshake_state) { + case 0: + { + /* send request to wiimote for accelerometer calibration */ + byte* buf;
+
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); + wiiuse_set_leds(wm, WIIMOTE_LED_NONE); + + buf = (byte*)malloc(sizeof(byte) * 8); + wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7); + wm->handshake_state++; + + wiiuse_set_leds(wm, WIIMOTE_LED_NONE);
+
+ break; + } + case 1: + { + struct read_req_t* req = wm->read_req; + struct accel_t* accel = &wm->accel_calib; + + /* received read data */ + accel->cal_zero.x = req->buf[0]; + accel->cal_zero.y = req->buf[1]; + accel->cal_zero.z = req->buf[2]; + + accel->cal_g.x = req->buf[4] - accel->cal_zero.x; + accel->cal_g.y = req->buf[5] - accel->cal_zero.y; + accel->cal_g.z = req->buf[6] - accel->cal_zero.z; + + /* done with the buffer */ + free(req->buf); + + /* handshake is done */ + WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x", + accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z, + accel->cal_g.x, accel->cal_g.y, accel->cal_g.z); + +
+ /* request the status of the wiimote to see if there is an expansion */
+ wiiuse_status(wm);
+
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE); + wm->handshake_state++;
+
+ /* now enable IR if it was set before the handshake completed */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
+ WIIUSE_DEBUG("Handshake finished, enabling IR."); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); + wiiuse_set_ir(wm, 1); + }
+ + break; + }
+ default: + { + break; + } + } +} diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.h new file mode 100644 index 0000000000..7a683e4ee5 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.h @@ -0,0 +1,56 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O. + */ + +#ifndef CONNECT_H_INCLUDED +#define CONNECT_H_INCLUDED + +#ifndef WIN32 + #include <bluetooth/bluetooth.h> +#endif + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len); + +int wiiuse_io_read(struct wiimote_t* wm); +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len); + +#ifdef __cplusplus +} +#endif + +#endif // CONNECT_H_INCLUDED diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_nix.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_nix.c new file mode 100644 index 0000000000..ec4e0e1780 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_nix.c @@ -0,0 +1,270 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O for *nix. + */ + +#ifndef WIN32 + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/hci.h> +#include <bluetooth/hci_lib.h> +#include <bluetooth/l2cap.h> + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "io.h" + +static int wiiuse_connect_single(struct wiimote_t* wm, char* address); + +/** + * @brief Find a wiimote or wiimotes. + * + * @param wm An array of wiimote_t structures. + * @param max_wiimotes The number of wiimote structures in \a wm. + * @param timeout The number of seconds before the search times out. + * + * @return The number of wiimotes found. + * + * @see wiimote_connect() + * + * This function will only look for wiimote devices. \n + * When a device is found the address in the structures will be set. \n + * You can then call wiimote_connect() to connect to the found \n + * devices. + */ +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { + int device_id; + int device_sock; + int found_devices; + int found_wiimotes; + + /* reset all wiimote bluetooth device addresses */ + for (found_wiimotes = 0; found_wiimotes < max_wiimotes; ++found_wiimotes) + wm[found_wiimotes]->bdaddr = *BDADDR_ANY; + found_wiimotes = 0; + + /* get the id of the first bluetooth device. */ + device_id = hci_get_route(NULL); + if (device_id < 0) { + perror("hci_get_route"); + return 0; + } + + /* create a socket to the device */ + device_sock = hci_open_dev(device_id); + if (device_sock < 0) { + perror("hci_open_dev"); + return 0; + } + + inquiry_info scan_info_arr[128]; + inquiry_info* scan_info = scan_info_arr; + memset(&scan_info_arr, 0, sizeof(scan_info_arr)); + + /* scan for bluetooth devices for 'timeout' seconds */ + found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); + if (found_devices < 0) { + perror("hci_inquiry"); + return 0; + } + + WIIUSE_INFO("Found %i bluetooth device(s).", found_devices); + + int i = 0; + + /* display discovered devices */ + for (; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) { + if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) && + (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) && + (scan_info[i].dev_class[2] == WM_DEV_CLASS_2)) + { + /* found a device */ + ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str); + + WIIUSE_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid); + + wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr; + WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND); + ++found_wiimotes; + } + } + + close(device_sock); + return found_wiimotes; +} + + +/** + * @brief Connect to a wiimote or wiimotes once an address is known. + * + * @param wm An array of wiimote_t structures. + * @param wiimotes The number of wiimote structures in \a wm. + * + * @return The number of wiimotes that successfully connected. + * + * @see wiiuse_find() + * @see wiiuse_connect_single() + * @see wiiuse_disconnect() + * + * Connect to a number of wiimotes when the address is already set + * in the wiimote_t structures. These addresses are normally set + * by the wiiuse_find() function, but can also be set manually. + */ +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { + int connected = 0; + int i = 0; + + for (; i < wiimotes; ++i) { + if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) + /* if the device address is not set, skip it */ + continue; + + if (wiiuse_connect_single(wm[i], NULL)) + ++connected; + } + + return connected; +} + + +/** + * @brief Connect to a wiimote with a known address. + * + * @param wm Pointer to a wiimote_t structure. + * @param address The address of the device to connect to. + * If NULL, use the address in the struct set by wiiuse_find(). + * + * @return 1 on success, 0 on failure + */ +static int wiiuse_connect_single(struct wiimote_t* wm, char* address) { + struct sockaddr_l2 addr; + + if (!wm || WIIMOTE_IS_CONNECTED(wm)) + return 0; + + addr.l2_family = AF_BLUETOOTH; + + if (address) + /* use provided address */ + str2ba(address, &addr.l2_bdaddr); + else + /* use address of device discovered */ + addr.l2_bdaddr = wm->bdaddr; + + /* + * OUTPUT CHANNEL + */ + wm->out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (wm->out_sock == -1) + return 0; + + addr.l2_psm = htobs(WM_OUTPUT_CHANNEL); + + /* connect to wiimote */ + if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("connect() output sock"); + return 0; + } + + /* + * INPUT CHANNEL + */ + wm->in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (wm->in_sock == -1) { + close(wm->out_sock); + wm->out_sock = -1; + return 0; + } + + addr.l2_psm = htobs(WM_INPUT_CHANNEL); + + /* connect to wiimote */ + if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("connect() interrupt sock"); + close(wm->out_sock); + wm->out_sock = -1; + return 0; + } + + WIIUSE_INFO("Connected to wiimote [id %i].", wm->unid); + + /* do the handshake */ + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + wiiuse_handshake(wm, NULL, 0); + + wiiuse_set_report_type(wm); + + return 1; +} + + +/** + * @brief Disconnect a wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * + * @see wiiuse_connect() + * + * Note that this will not free the wiimote structure. + */ +void wiiuse_disconnect(struct wiimote_t* wm) { + if (!wm || WIIMOTE_IS_CONNECTED(wm)) + return; + + close(wm->out_sock); + close(wm->in_sock); + + wm->out_sock = -1; + wm->in_sock = -1; + wm->event = WIIUSE_NONE; + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); +} + + +int wiiuse_io_read(struct wiimote_t* wm) { + /* not used */ + return 0; +} + + +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) { + return write(wm->out_sock, buf, len); +} + + + +#endif /* ifndef WIN32 */ diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_win.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_win.c new file mode 100644 index 0000000000..17fac360d3 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_win.c @@ -0,0 +1,247 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O for Windows. + */ + +#ifdef WIN32 +
+#include <stdio.h> +#include <stdlib.h> + +#include <windows.h> +#include <hidsdi.h> +#include <setupapi.h> +
+#include "definitions.h" +#include "wiiuse_internal.h" +#include "io.h" + + +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { + GUID device_id; + HANDLE dev; + HDEVINFO device_info; + int i, index; + DWORD len; + SP_DEVICE_INTERFACE_DATA device_data; + PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; + HIDD_ATTRIBUTES attr; + int found = 0; + + (void) timeout; // unused + + device_data.cbSize = sizeof(device_data); + index = 0; + + /* get the device id */ + HidD_GetHidGuid(&device_id); + + /* get all hid devices connected */ + device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); + + for (;; ++index) { + + if (detail_data) { + free(detail_data); + detail_data = NULL; + } + + /* query the next hid device info */ + if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data)) + break; + + /* get the size of the data block required */ + i = SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL); + detail_data = malloc(len); + detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + + /* query the data for this device */ + if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) + continue; + + /* open the device */ + dev = CreateFile(detail_data->DevicePath, + (GENERIC_READ | GENERIC_WRITE), + (FILE_SHARE_READ | FILE_SHARE_WRITE), + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (dev == INVALID_HANDLE_VALUE) + continue; + + /* get device attributes */ + attr.Size = sizeof(attr); + i = HidD_GetAttributes(dev, &attr); + + if ((attr.VendorID == WM_VENDOR_ID) && (attr.ProductID == WM_PRODUCT_ID)) { + /* this is a wiimote */ + wm[found]->dev_handle = dev; + + wm[found]->hid_overlap.hEvent = CreateEvent(NULL, 1, 1, ""); + wm[found]->hid_overlap.Offset = 0; + wm[found]->hid_overlap.OffsetHigh = 0; + + WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_DEV_FOUND); + WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED); + + /* try to set the output report to see if the device is actually connected */ + if (!wiiuse_set_report_type(wm[found])) { + WIIMOTE_DISABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED); + continue; + } + + /* do the handshake */ + wiiuse_handshake(wm[found], NULL, 0); + + WIIUSE_INFO("Connected to wiimote [id %i].", wm[found]->unid); + + ++found; + if (found >= max_wiimotes) + break; + } else { + /* not a wiimote */ + CloseHandle(dev); + } + } + + if (detail_data) + free(detail_data); + + SetupDiDestroyDeviceInfoList(device_info); + + return found; +} + + +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { + int connected = 0; + int i = 0; + + for (; i < wiimotes; ++i) { + if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) + ++connected; + } + + return connected; +} + + +void wiiuse_disconnect(struct wiimote_t* wm) { + if (!wm || WIIMOTE_IS_CONNECTED(wm)) + return; + + CloseHandle(wm->dev_handle); + wm->dev_handle = 0; + + ResetEvent(&wm->hid_overlap); + + wm->event = WIIUSE_NONE; + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); +} + + +int wiiuse_io_read(struct wiimote_t* wm) { + DWORD b, r; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + + if (!ReadFile(wm->dev_handle, wm->event_buf, sizeof(wm->event_buf), &b, &wm->hid_overlap)) { + /* partial read */ + b = GetLastError();
+
+ if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) { + /* remote disconnect */ + wiiuse_disconnected(wm); + return 0; + } + + r = WaitForSingleObject(wm->hid_overlap.hEvent, wm->timeout); + if (r == WAIT_TIMEOUT) { + /* timeout - cancel and continue */
+
+ if (*wm->event_buf)
+ WIIUSE_WARNING("Packet ignored. This may indicate a problem (timeout is %i ms).", wm->timeout);
+
+ CancelIo(wm->dev_handle); + ResetEvent(wm->hid_overlap.hEvent); + return 0; + } else if (r == WAIT_FAILED) { + WIIUSE_WARNING("A wait error occured on reading from wiimote %i.", wm->unid); + return 0; + } + + if (!GetOverlappedResult(wm->dev_handle, &wm->hid_overlap, &b, 0)) + return 0; + } + + ResetEvent(wm->hid_overlap.hEvent);
+ return 1; +} + + +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) { + DWORD bytes; + int i;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0;
+
+ switch (wm->stack) { + case WIIUSE_STACK_UNKNOWN: + { + /* try to auto-detect the stack type */ + if (i = WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap)) { + /* bluesoleil will always return 1 here, even if it's not connected */ + wm->stack = WIIUSE_STACK_BLUESOLEIL;
+ return i; + } + + if (i = HidD_SetOutputReport(wm->dev_handle, buf, len)) { + wm->stack = WIIUSE_STACK_MS; + return i; + } + + WIIUSE_ERROR("Unable to determine bluetooth stack type."); + return 0; + } + + case WIIUSE_STACK_MS: + return HidD_SetOutputReport(wm->dev_handle, buf, len); + + case WIIUSE_STACK_BLUESOLEIL: + return WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap); + } + + return 0; +} + +#endif /* ifdef WIN32 */ diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.c new file mode 100644 index 0000000000..7a9bb68289 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.c @@ -0,0 +1,748 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles IR data. + */ + +#include <stdio.h> +#include <math.h> + +#ifndef WIN32 + #include <unistd.h> +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "ir.h" + +static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2); +static void interpret_ir_data(struct wiimote_t* wm); +static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang); +static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y); +static void reorder_ir_dots(struct ir_dot_t* dot); +static float ir_distance(struct ir_dot_t* dot); +static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y); +static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy); + + +/** + * @brief Set if the wiimote should track IR targets. + * + * @param wm Pointer to a wiimote_t structure. + * @param status 1 to enable, 0 to disable. + */ +void wiiuse_set_ir(struct wiimote_t* wm, int status) { + byte buf; + char* block1 = NULL; + char* block2 = NULL; + int ir_level; + + if (!wm) + return; + + /* + * Wait for the handshake to finish first. + * When it handshake finishes and sees that + * IR is enabled, it will call this function + * again to actually enable IR. + */ + if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE)) { + WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes."); + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR); + return; + } + + /* + * Check to make sure a sensitivity setting is selected. + */ + ir_level = get_ir_sens(wm, &block1, &block2); + if (!ir_level) { + WIIUSE_ERROR("No IR sensitivity setting selected."); + return; + } + + if (status) { + /* if already enabled then stop */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) + return; + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR); + } else { + /* if already disabled then stop */ + if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) + return; + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); + } + + /* set camera 1 and 2 */ + buf = (status ? 0x04 : 0x00); + wiiuse_send(wm, WM_CMD_IR, &buf, 1); + wiiuse_send(wm, WM_CMD_IR_2, &buf, 1); + + if (!status) { + WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid); + wiiuse_set_report_type(wm); + return; + } + + /* enable IR, set sensitivity */ + buf = 0x08; + wiiuse_write_data(wm, WM_REG_IR, &buf, 1); + + /* wait for the wiimote to catch up */ + #ifndef WIN32 + usleep(50000); + #else + Sleep(50); + #endif + + /* write sensitivity blocks */ + wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9); + wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2); + + /* set the IR mode */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) + buf = WM_IR_TYPE_BASIC; + else + buf = WM_IR_TYPE_EXTENDED; + wiiuse_write_data(wm, WM_REG_IR_MODENUM, &buf, 1); + + #ifndef WIN32 + usleep(50000); + #else + Sleep(50); + #endif + + /* set the wiimote report type */ + wiiuse_set_report_type(wm); + + WIIUSE_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level); +} + + +/** + * @brief Get the IR sensitivity settings. + * + * @param wm Pointer to a wiimote_t structure. + * @param block1 [out] Pointer to where block1 will be set. + * @param block2 [out] Pointer to where block2 will be set. + * + * @return Returns the sensitivity level. + */ +static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) { + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) { + *block1 = WM_IR_BLOCK1_LEVEL1; + *block2 = WM_IR_BLOCK2_LEVEL1; + return 1; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) { + *block1 = WM_IR_BLOCK1_LEVEL2; + *block2 = WM_IR_BLOCK2_LEVEL2; + return 2; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) { + *block1 = WM_IR_BLOCK1_LEVEL3; + *block2 = WM_IR_BLOCK2_LEVEL3; + return 3; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) { + *block1 = WM_IR_BLOCK1_LEVEL4; + *block2 = WM_IR_BLOCK2_LEVEL4; + return 4; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) { + *block1 = WM_IR_BLOCK1_LEVEL5; + *block2 = WM_IR_BLOCK2_LEVEL5; + return 5; + } + + *block1 = NULL; + *block2 = NULL; + return 0; +} + + +/** + * @brief Set the virtual screen resolution for IR tracking. + * + * @param wm Pointer to a wiimote_t structure. + * @param status 1 to enable, 0 to disable. + */ +void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) { + if (!wm) return; + + wm->ir.vres[0] = (x-1); + wm->ir.vres[1] = (y-1); +} + + +/** + * @brief Set the XY position for the IR cursor. + * + * @param wm Pointer to a wiimote_t structure. + */ +void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) { + if (!wm) return; + + wm->ir.pos = pos; + + switch (pos) { + + case WIIUSE_IR_ABOVE: + wm->ir.offset[0] = 0; + + if (wm->ir.aspect == WIIUSE_ASPECT_16_9) + wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70; + else if (wm->ir.aspect == WIIUSE_ASPECT_4_3) + wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100; + + return; + + case WIIUSE_IR_BELOW: + wm->ir.offset[0] = 0; + + if (wm->ir.aspect == WIIUSE_ASPECT_16_9) + wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 100; + else if (wm->ir.aspect == WIIUSE_ASPECT_4_3) + wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 70; + + return; + + default: + return; + }; +} + + +/** + * @brief Set the aspect ratio of the TV/monitor. + * + * @param wm Pointer to a wiimote_t structure. + * @param aspect Either WIIUSE_ASPECT_16_9 or WIIUSE_ASPECT_4_3 + */ +void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) { + if (!wm) return; + + wm->ir.aspect = aspect; + + if (aspect == WIIUSE_ASPECT_4_3) { + wm->ir.vres[0] = WM_ASPECT_4_3_X; + wm->ir.vres[1] = WM_ASPECT_4_3_Y; + } else { + wm->ir.vres[0] = WM_ASPECT_16_9_X; + wm->ir.vres[1] = WM_ASPECT_16_9_Y; + } + + /* reset the position offsets */ + wiiuse_set_ir_position(wm, wm->ir.pos); +} + + +/** + * @brief Set the IR sensitivity. + * + * @param wm Pointer to a wiimote_t structure. + * @param level 1-5, same as Wii system sensitivity setting. + * + * If the level is < 1, then level will be set to 1. + * If the level is > 5, then level will be set to 5. + */ +void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) { + char* block1 = NULL; + char* block2 = NULL; + + if (!wm) return; + + if (level > 5) level = 5; + if (level < 1) level = 1; + + WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 | + WIIMOTE_STATE_IR_SENS_LVL2 | + WIIMOTE_STATE_IR_SENS_LVL3 | + WIIMOTE_STATE_IR_SENS_LVL4 | + WIIMOTE_STATE_IR_SENS_LVL5)); + + switch (level) { + case 1: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1); + break; + case 2: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2); + break; + case 3: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3); + break; + case 4: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4); + break; + case 5: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5); + break; + default: + return; + } + + /* set the new sensitivity */ + get_ir_sens(wm, &block1, &block2); + + wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9); + wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2); + + WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid); +} + + +/** + * @brief Calculate the data from the IR spots. Basic IR mode. + * + * @param wm Pointer to a wiimote_t structure. + * @param data Data returned by the wiimote for the IR spots. + */ +void calculate_basic_ir(struct wiimote_t* wm, byte* data) { + struct ir_dot_t* dot = wm->ir.dot; + int i; + + dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4)); + dot[0].ry = data[1] | ((data[2] & 0xC0) << 2); + + dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8)); + dot[1].ry = data[4] | ((data[2] & 0x0C) << 6); + + dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4)); + dot[2].ry = data[6] | ((data[7] & 0xC0) << 2); + + dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8)); + dot[3].ry = data[9] | ((data[7] & 0x0C) << 6); + + /* set each IR spot to visible if spot is in range */ + for (i = 0; i < 4; ++i) { + if (dot[i].ry == 1023) + dot[i].visible = 0; + else { + dot[i].visible = 1; + dot[i].size = 0; /* since we don't know the size, set it as 0 */ + } + } + + interpret_ir_data(wm); +} + + +/** + * @brief Calculate the data from the IR spots. Extended IR mode. + * + * @param wm Pointer to a wiimote_t structure. + * @param data Data returned by the wiimote for the IR spots. + */ +void calculate_extended_ir(struct wiimote_t* wm, byte* data) { + struct ir_dot_t* dot = wm->ir.dot; + int i; + + for (i = 0; i < 4; ++i) { + dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4)); + dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2); + + dot[i].size = data[(3*i)+2] & 0x0F; + + /* if in range set to visible */ + if (dot[i].ry == 1023) + dot[i].visible = 0; + else + dot[i].visible = 1; + } + + interpret_ir_data(wm); +} + + +/** + * @brief Interpret IR data into more user friendly variables. + * + * @param wm Pointer to a wiimote_t structure. + */ +static void interpret_ir_data(struct wiimote_t* wm) { + struct ir_dot_t* dot = wm->ir.dot; + int i; + float roll = 0.0f; + int last_num_dots = wm->ir.num_dots; + + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC)) + roll = wm->orient.roll; + + /* count visible dots */ + wm->ir.num_dots = 0; + for (i = 0; i < 4; ++i) { + if (dot[i].visible) + wm->ir.num_dots++; + } + + switch (wm->ir.num_dots) { + case 0: + { + wm->ir.state = 0; + + /* reset the dot ordering */ + for (i = 0; i < 4; ++i) + dot[i].order = 0; + + wm->ir.x = 0; + wm->ir.y = 0; + wm->ir.z = 0.0f; + + return; + } + case 1: + { + fix_rotated_ir_dots(wm->ir.dot, roll); + + if (wm->ir.state < 2) { + /* + * Only 1 known dot, so use just that. + */ + for (i = 0; i < 4; ++i) { + if (dot[i].visible) { + wm->ir.x = dot[i].x; + wm->ir.y = dot[i].y; + + wm->ir.ax = wm->ir.x; + wm->ir.ay = wm->ir.y; + + /* can't calculate yaw because we don't have the distance */ + //wm->orient.yaw = calc_yaw(&wm->ir); + + ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); + break; + } + } + } else { + /* + * Only see 1 dot but know theres 2. + * Try to estimate where the other one + * should be and use that. + */ + for (i = 0; i < 4; ++i) { + if (dot[i].visible) { + int ox = 0; + int x, y; + + if (dot[i].order == 1) + /* visible is the left dot - estimate where the right is */ + ox = dot[i].x + wm->ir.distance; + else if (dot[i].order == 2) + /* visible is the right dot - estimate where the left is */ + ox = dot[i].x - wm->ir.distance; + + x = ((signed int)dot[i].x + ox) / 2; + y = dot[i].y; + + wm->ir.ax = x; + wm->ir.ay = y; + wm->orient.yaw = calc_yaw(&wm->ir); + + if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) { + ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); + wm->ir.x = x; + wm->ir.y = y; + } + + break; + } + } + } + + break; + } + case 2: + case 3: + case 4: + { + /* + * Two (or more) dots known and seen. + * Average them together to estimate the true location. + */ + int x, y; + wm->ir.state = 2; + + fix_rotated_ir_dots(wm->ir.dot, roll); + + /* if there is at least 1 new dot, reorder them all */ + if (wm->ir.num_dots > last_num_dots) { + reorder_ir_dots(dot); + wm->ir.x = 0; + wm->ir.y = 0; + } + + wm->ir.distance = ir_distance(dot); + wm->ir.z = 1023 - wm->ir.distance; + + get_ir_dot_avg(wm->ir.dot, &x, &y); + + wm->ir.ax = x; + wm->ir.ay = y; + wm->orient.yaw = calc_yaw(&wm->ir); + + if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) { + ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); + wm->ir.x = x; + wm->ir.y = y; + } + + break; + } + default: + { + break; + } + } + + #ifdef WITH_WIIUSE_DEBUG + { + int ir_level; + WIIUSE_GET_IR_SENSITIVITY(wm, &ir_level); + WIIUSE_DEBUG("IR sensitivity: %i", ir_level); + WIIUSE_DEBUG("IR visible dots: %i", wm->ir.num_dots); + for (i = 0; i < 4; ++i) + if (dot[i].visible) + WIIUSE_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y); + WIIUSE_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y); + } + #endif +} + + + +/** + * @brief Fix the rotation of the IR dots. + * + * @param dot An array of 4 ir_dot_t objects. + * @param ang The roll angle to correct by (-180, 180) + * + * If there is roll then the dots are rotated + * around the origin and give a false cursor + * position. Correct for the roll. + * + * If the accelerometer is off then obviously + * this will not do anything and the cursor + * position may be inaccurate. + */ +static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang) { + float s, c; + int x, y; + int i; + + if (!ang) { + for (i = 0; i < 4; ++i) { + dot[i].x = dot[i].rx; + dot[i].y = dot[i].ry; + } + return; + } + + s = sin(DEGREE_TO_RAD(ang)); + c = cos(DEGREE_TO_RAD(ang)); + + /* + * [ cos(theta) -sin(theta) ][ ir->rx ] + * [ sin(theta) cos(theta) ][ ir->ry ] + */ + + for (i = 0; i < 4; ++i) { + if (!dot[i].visible) + continue; + + x = dot[i].rx - (1024/2); + y = dot[i].ry - (768/2); + + dot[i].x = (c * x) + (-s * y); + dot[i].y = (s * x) + (c * y); + + dot[i].x += (1024/2); + dot[i].y += (768/2); + } +} + + +/** + * @brief Average IR dots. + * + * @param dot An array of 4 ir_dot_t objects. + * @param x [out] Average X + * @param y [out] Average Y + */ +static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y) { + int vis = 0, i = 0; + + *x = 0; + *y = 0; + + for (; i < 4; ++i) { + if (dot[i].visible) { + *x += dot[i].x; + *y += dot[i].y; + ++vis; + } + } + + *x /= vis; + *y /= vis; +} + + +/** + * @brief Reorder the IR dots. + * + * @param dot An array of 4 ir_dot_t objects. + */ +static void reorder_ir_dots(struct ir_dot_t* dot) { + int i, j, order; + + /* reset the dot ordering */ + for (i = 0; i < 4; ++i) + dot[i].order = 0; + + for (order = 1; order < 5; ++order) { + i = 0; + + for (; !dot[i].visible || dot[i].order; ++i) + if (i > 4) + return; + + for (j = 0; j < 4; ++j) { + if (dot[j].visible && !dot[j].order && (dot[j].x < dot[i].x)) + i = j; + } + + dot[i].order = order; + } +} + + +/** + * @brief Calculate the distance between the first 2 visible IR dots. + * + * @param dot An array of 4 ir_dot_t objects. + */ +static float ir_distance(struct ir_dot_t* dot) { + int i1, i2; + int xd, yd; + + for (i1 = 0; i1 < 4; ++i1) + if (dot[i1].visible) + break; + if (i1 == 4) + return 0.0f; + + for (i2 = i1+1; i2 < 4; ++i2) + if (dot[i2].visible) + break; + if (i2 == 4) + return 0.0f; + + xd = dot[i2].x - dot[i1].x; + yd = dot[i2].y - dot[i1].y; + + return sqrt(xd*xd + yd*yd); +} + + +/** + * @brief Correct for the IR bounding box. + * + * @param x [out] The current X, it will be updated if valid. + * @param y [out] The current Y, it will be updated if valid. + * @param aspect Aspect ratio of the screen. + * @param offset_x The X offset of the bounding box. + * @param offset_y The Y offset of the bounding box. + * + * @return Returns 1 if the point is valid and was updated. + * + * Nintendo was smart with this bit. They sacrifice a little + * precision for a big increase in usability. + */ +static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y) { + int x0, y0; + int xs, ys; + + if (aspect == WIIUSE_ASPECT_16_9) { + xs = WM_ASPECT_16_9_X; + ys = WM_ASPECT_16_9_Y; + } else { + xs = WM_ASPECT_4_3_X; + ys = WM_ASPECT_4_3_Y; + } + + x0 = ((1024 - xs) / 2) + offset_x; + y0 = ((768 - ys) / 2) + offset_y; + + if ((*x >= x0) + && (*x <= (x0 + xs)) + && (*y >= y0) + && (*y <= (y0 + ys))) + { + *x -= offset_x; + *y -= offset_y; + + return 1; + } + + return 0; +} + + +/** + * @brief Interpolate the point to the user defined virtual screen resolution. + */ +static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy) { + int xs, ys; + + if (aspect == WIIUSE_ASPECT_16_9) { + xs = WM_ASPECT_16_9_X; + ys = WM_ASPECT_16_9_Y; + } else { + xs = WM_ASPECT_4_3_X; + ys = WM_ASPECT_4_3_Y; + } + + *x -= ((1024-xs)/2); + *y -= ((768-ys)/2); + + *x = (*x / (float)xs) * vx; + *y = (*y / (float)ys) * vy; +} + + +/** + * @brief Calculate yaw given the IR data. + * + * @param ir IR data structure. + */ +float calc_yaw(struct ir_t* ir) { + float x; + + x = ir->ax - 512; + x = x * (ir->z / 1024.0f); + + return RAD_TO_DEGREE( atanf(x / ir->z) ); +} diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.h new file mode 100644 index 0000000000..9082492987 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.h @@ -0,0 +1,56 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles IR data. + */ + +#ifndef IR_H_INCLUDED +#define IR_H_INCLUDED + +#include "wiiuse_internal.h" + +#define WII_VRES_X 560 +#define WII_VRES_Y 340 + +#ifdef __cplusplus +extern "C" { +#endif + +void calculate_basic_ir(struct wiimote_t* wm, byte* data); +void calculate_extended_ir(struct wiimote_t* wm, byte* data); +float calc_yaw(struct ir_t* ir); + +#ifdef __cplusplus +} +#endif + +#endif // IR_H_INCLUDED + + diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsp b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsp new file mode 100644 index 0000000000..dd66ae7078 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsp @@ -0,0 +1,191 @@ +# Microsoft Developer Studio Project File - Name="wiiuse" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=wiiuse - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "wiiuse.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "wiiuse.mak" CFG="wiiuse - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "wiiuse - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "wiiuse - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "wiiuse - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib hid.lib setupapi.lib /nologo /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "wiiuse - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /D "WITH_WIIUSE_DEBUG" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib hid.lib setupapi.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "wiiuse - Win32 Release"
+# Name "wiiuse - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\classic.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dynamics.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\events.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\guitar_hero_3.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\io.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\io_nix.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\io_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ir.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nunchuk.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\wiiuse.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\classic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\definitions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\dynamics.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\events.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\guitar_hero_3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\io.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\nunchuk.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\os.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\wiiuse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\wiiuse_internal.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=..\..\CHANGELOG
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsw b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsw new file mode 100644 index 0000000000..5d662bf0ea --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "wiiuse"=".\wiiuse.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.opt b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.opt Binary files differnew file mode 100644 index 0000000000..b6ebe4c479 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.opt diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.c new file mode 100644 index 0000000000..48dbe6a089 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.c @@ -0,0 +1,210 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Nunchuk expansion device. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "dynamics.h" +#include "events.h" +#include "nunchuk.h" + +static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now); + +/** + * @brief Handle the handshake data from the nunchuk. + * + * @param nc A pointer to a nunchuk_t structure. + * @param data The data read in from the device. + * @param len The length of the data block, in bytes. + * + * @return Returns 1 if handshake was successful, 0 if not. + */ +int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len) { + int i;
+ int offset = 0;
+
+ nc->btns = 0; + nc->btns_held = 0; + nc->btns_released = 0; + + /* set the smoothing to the same as the wiimote */ + nc->flags = &wm->flags; + nc->accel_calib.st_alpha = wm->accel_calib.st_alpha; + + /* decrypt data */ + for (i = 0; i < len; ++i) + data[i] = (data[i] ^ 0x17) + 0x17;
+
+ if (data[offset] == 0xFF) {
+ /*
+ * Sometimes the data returned here is not correct.
+ * This might happen because the wiimote is lagging
+ * behind our initialization sequence.
+ * To fix this just request the handshake again.
+ *
+ * Other times it's just the first 16 bytes are 0xFF,
+ * but since the next 16 bytes are the same, just use
+ * those.
+ */
+ if (data[offset + 16] == 0xFF) {
+ /* get the calibration data */
+ byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+ WIIUSE_DEBUG("Nunchuk handshake appears invalid, trying again.");
+ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+ return 0;
+ } else
+ offset += 16;
+ } + + nc->accel_calib.cal_zero.x = data[offset + 0]; + nc->accel_calib.cal_zero.y = data[offset + 1]; + nc->accel_calib.cal_zero.z = data[offset + 2]; + nc->accel_calib.cal_g.x = data[offset + 4]; + nc->accel_calib.cal_g.y = data[offset + 5]; + nc->accel_calib.cal_g.z = data[offset + 6]; + nc->js.max.x = data[offset + 8]; + nc->js.min.x = data[offset + 9]; + nc->js.center.x = data[offset + 10]; + nc->js.max.y = data[offset + 11]; + nc->js.min.y = data[offset + 12]; + nc->js.center.y = data[offset + 13]; +
+ /* default the thresholds to the same as the wiimote */ + nc->orient_threshold = wm->orient_threshold; + nc->accel_threshold = wm->accel_threshold; + + /* handshake done */
+ wm->exp.type = EXP_NUNCHUK;
+
+ #ifdef WIN32
+ wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
+ #endif + + return 1; +} + + +/** + * @brief The nunchuk disconnected. + * + * @param nc A pointer to a nunchuk_t structure. + */ +void nunchuk_disconnected(struct nunchuk_t* nc) { + memset(nc, 0, sizeof(struct nunchuk_t)); +} + + + +/** + * @brief Handle nunchuk event. + * + * @param nc A pointer to a nunchuk_t structure. + * @param msg The message specified in the event packet. + */ +void nunchuk_event(struct nunchuk_t* nc, byte* msg) { + int i; + + /* decrypt data */ + for (i = 0; i < 6; ++i) + msg[i] = (msg[i] ^ 0x17) + 0x17; + + /* get button states */ + nunchuk_pressed_buttons(nc, msg[5]); + + /* calculate joystick state */ + calc_joystick_state(&nc->js, msg[0], msg[1]); + + /* calculate orientation */ + nc->accel.x = msg[2]; + nc->accel.y = msg[3]; + nc->accel.z = msg[4]; + + calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING)); + calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce); +} + + +/** + * @brief Find what buttons are pressed. + * + * @param nc Pointer to a nunchuk_t structure. + * @param msg The message byte specified in the event packet. + */ +static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now) { + /* message is inverted (0 is active, 1 is inactive) */ + now = ~now & NUNCHUK_BUTTON_ALL; + + /* pressed now & were pressed, then held */ + nc->btns_held = (now & nc->btns); + + /* were pressed or were held & not pressed now, then released */ + nc->btns_released = ((nc->btns | nc->btns_held) & ~now); + + /* buttons pressed now */ + nc->btns = now; +} + + +/** + * @brief Set the orientation event threshold for the nunchuk. + * + * @param wm Pointer to a wiimote_t structure with a nunchuk attached. + * @param threshold The decimal place that should be considered a significant change. + * + * See wiiuse_set_orient_threshold() for details. + */ +void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold) { + if (!wm) return; + + wm->exp.nunchuk.orient_threshold = threshold; +} + + +/** + * @brief Set the accelerometer event threshold for the nunchuk. + * + * @param wm Pointer to a wiimote_t structure with a nunchuk attached. + * @param threshold The decimal place that should be considered a significant change. + * + * See wiiuse_set_orient_threshold() for details. + */ +void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold) { + if (!wm) return; + + wm->exp.nunchuk.accel_threshold = threshold; +} diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.h new file mode 100644 index 0000000000..f036073d64 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.h @@ -0,0 +1,53 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Nunchuk expansion device. + */ + +#ifndef NUNCHUK_H_INCLUDED +#define NUNCHUK_H_INCLUDED + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len); + +void nunchuk_disconnected(struct nunchuk_t* nc); + +void nunchuk_event(struct nunchuk_t* nc, byte* msg); + +#ifdef __cplusplus +} +#endif + +#endif // NUNCHUK_H_INCLUDED diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/os.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/os.h new file mode 100644 index 0000000000..53b80f557c --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/os.h @@ -0,0 +1,56 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + + +/** + * @file + * @brief Operating system related definitions. + * + * This file is an attempt to separate operating system + * dependent functions and choose what should be used + * at compile time. + */ + +#ifndef OS_H_INCLUDED +#define OS_H_INCLUDED + +#ifdef WIN32
+ /* windows */ + #define isnan(x) _isnan(x) + #define isinf(x) !_finite(x) + + /* disable warnings I don't care about */
+ #pragma warning(disable:4244) /* possible loss of data conversion */
+ #pragma warning(disable:4273) /* inconsistent dll linkage */
+ #pragma warning(disable:4217) +#else + /* nix */ +#endif + + +#endif // OS_H_INCLUDED diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.c new file mode 100644 index 0000000000..8d4b763864 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.c @@ -0,0 +1,764 @@ +/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief General wiimote operations.
+ *
+ * The file includes functions that handle general
+ * tasks. Most of these are functions that are part
+ * of the API.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+ #include <unistd.h>
+#else
+ #include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "events.h"
+#include "io.h"
+
+static int g_banner = 0;
+
+/**
+ * @breif Returns the version of the library.
+ */
+const char* wiiuse_version() {
+ return WIIUSE_VERSION;
+}
+
+
+/**
+ * @brief Clean up wiimote_t array created by wiiuse_init()
+ */
+void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes) {
+ int i = 0;
+
+ if (!wm)
+ return;
+
+ WIIUSE_INFO("wiiuse clean up...");
+
+ for (; i < wiimotes; ++i) {
+ wiiuse_disconnect(wm[i]);
+ free(wm[i]);
+ }
+
+ free(wm);
+
+ return;
+}
+
+
+/**
+ * @brief Initialize an array of wiimote structures.
+ *
+ * @param wiimotes Number of wiimote_t structures to create.
+ *
+ * @return An array of initialized wiimote_t structures.
+ *
+ * @see wiiuse_connect()
+ *
+ * The array returned by this function can be passed to various
+ * functions, including wiiuse_connect().
+ */
+struct wiimote_t** wiiuse_init(int wiimotes) {
+ int i = 0;
+ struct wiimote_t** wm = NULL;
+
+ /*
+ * Please do not remove this banner.
+ * GPL asks that you please leave output credits intact.
+ * Thank you.
+ *
+ * This banner is only displayed once so that if you need
+ * to call this function again it won't be intrusive.
+ */
+ if (!g_banner) {
+ printf( "wiiuse v" WIIUSE_VERSION " loaded.\n"
+ " By: Michael Laforest <thepara[at]gmail{dot}com>\n"
+ " http://wiiuse.net http://wiiuse.sf.net\n");
+ g_banner = 1;
+ }
+
+ if (!wiimotes)
+ return NULL;
+
+ wm = malloc(sizeof(struct wiimote_t*) * wiimotes);
+
+ for (i = 0; i < wiimotes; ++i) {
+ wm[i] = malloc(sizeof(struct wiimote_t));
+ memset(wm[i], 0, sizeof(struct wiimote_t));
+
+ wm[i]->unid = i+1;
+
+ #ifndef WIN32
+ wm[i]->bdaddr = *BDADDR_ANY;
+ wm[i]->out_sock = -1;
+ wm[i]->in_sock = -1;
+ #else
+ wm[i]->dev_handle = 0;
+ wm[i]->stack = WIIUSE_STACK_UNKNOWN;
+ wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
+ wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
+ wm[i]->timeout = wm[i]->normal_timeout;
+ #endif
+
+ wm[i]->state = WIIMOTE_INIT_STATES;
+ wm[i]->flags = WIIUSE_INIT_FLAGS;
+
+ wm[i]->event = WIIUSE_NONE;
+
+ wm[i]->exp.type = EXP_NONE;
+
+ wiiuse_set_aspect_ratio(wm[i], WIIUSE_ASPECT_4_3);
+ wiiuse_set_ir_position(wm[i], WIIUSE_IR_ABOVE);
+
+ wm[i]->orient_threshold = 0.5f;
+ wm[i]->accel_threshold = 5;
+
+ wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA;
+ }
+
+ return wm;
+}
+
+
+/**
+ * @brief The wiimote disconnected.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+void wiiuse_disconnected(struct wiimote_t* wm) {
+ if (!wm) return;
+
+ WIIUSE_INFO("Wiimote disconnected [id %i].", wm->unid);
+
+ /* disable the connected flag */
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+
+ /* reset a bunch of stuff */
+ #ifndef WIN32
+ wm->out_sock = -1;
+ wm->in_sock = -1;
+ #else
+ wm->dev_handle = 0;
+ #endif
+
+ wm->leds = 0;
+ wm->state = WIIMOTE_INIT_STATES;
+ wm->read_req = NULL;
+ wm->handshake_state = 0;
+ wm->btns = 0;
+ wm->btns_held = 0;
+ wm->btns_released = 0;
+ memset(wm->event_buf, 0, sizeof(wm->event_buf));
+
+ wm->event = WIIUSE_DISCONNECT;
+}
+
+
+/**
+ * @brief Enable or disable the rumble.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param status 1 to enable, 0 to disable.
+ */
+void wiiuse_rumble(struct wiimote_t* wm, int status) {
+ byte buf;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return;
+
+ /* make sure to keep the current lit leds */
+ buf = wm->leds;
+
+ if (status) {
+ WIIUSE_DEBUG("Starting rumble...");
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
+ buf |= 0x01;
+ } else {
+ WIIUSE_DEBUG("Stopping rumble...");
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
+ }
+
+ /* preserve IR state */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
+ buf |= 0x04;
+
+ wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1);
+}
+
+
+/**
+ * @brief Toggle the state of the rumble.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+void wiiuse_toggle_rumble(struct wiimote_t* wm) {
+ if (!wm) return;
+
+ wiiuse_rumble(wm, !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE));
+}
+
+
+/**
+ * @brief Set the enabled LEDs.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param leds What LEDs to enable.
+ *
+ * \a leds is a bitwise or of WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, or WIIMOTE_LED_4.
+ */
+void wiiuse_set_leds(struct wiimote_t* wm, int leds) {
+ byte buf;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return;
+
+ /* remove the lower 4 bits because they control rumble */
+ wm->leds = (leds & 0xF0);
+
+ /* make sure if the rumble is on that we keep it on */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+ wm->leds |= 0x01;
+
+ buf = wm->leds;
+
+ wiiuse_send(wm, WM_CMD_LED, &buf, 1);
+}
+
+
+/**
+ * @brief Set if the wiimote should report motion sensing.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param status 1 to enable, 0 to disable.
+ *
+ * Since reporting motion sensing sends a lot of data,
+ * the wiimote saves power by not transmitting it
+ * by default.
+ */
+void wiiuse_motion_sensing(struct wiimote_t* wm, int status) {
+ if (status)
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
+ else
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
+
+ wiiuse_set_report_type(wm);
+}
+
+
+/**
+ * @brief Set the report type based on the current wiimote state.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * @return The report type sent.
+ *
+ * The wiimote reports formatted packets depending on the
+ * report type that was last requested. This function will
+ * update the type of report that should be sent based on
+ * the current state of the device.
+ */
+int wiiuse_set_report_type(struct wiimote_t* wm) {
+ byte buf[2];
+ int motion, exp, ir;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+
+ buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */
+ buf[1] = 0x00;
+
+ /* if rumble is enabled, make sure we keep it */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+ buf[0] |= 0x01;
+
+ motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC);
+ exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
+ ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
+
+ if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP;
+ else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP;
+ else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR;
+ else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP;
+ else if (ir) buf[1] = WM_RPT_BTN_ACC_IR;
+ else if (exp) buf[1] = WM_RPT_BTN_EXP;
+ else if (motion) buf[1] = WM_RPT_BTN_ACC;
+ else buf[1] = WM_RPT_BTN;
+
+ WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);
+
+ exp = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2);
+ if (exp <= 0)
+ return exp;
+
+ return buf[1];
+}
+
+
+/**
+ * @brief Read data from the wiimote (callback version).
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param read_cb Function pointer to call when the data arrives from the wiimote.
+ * @param buffer An allocated buffer to store the data as it arrives from the wiimote.
+ * Must be persistent in memory and large enough to hold the data.
+ * @param addr The address of wiimote memory to read from.
+ * @param len The length of the block to be read.
+ *
+ * The library can only handle one data read request at a time
+ * because it must keep track of the buffer and other
+ * events that are specific to that request. So if a request
+ * has already been made, subsequent requests will be added
+ * to a pending list and be sent out when the previous
+ * finishes.
+ */
+int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int addr, unsigned short len) {
+ struct read_req_t* req;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+ if (!buffer || !len || !read_cb)
+ return 0;
+
+ /* make this request structure */
+ req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
+ req->cb = read_cb;
+ req->buf = buffer;
+ req->addr = addr;
+ req->size = len;
+ req->wait = len; + req->dirty = 0;
+ req->next = NULL;
+
+ /* add this to the request list */
+ if (!wm->read_req) {
+ /* root node */
+ wm->read_req = req;
+
+ WIIUSE_DEBUG("Data read request can be sent out immediately.");
+
+ /* send the request out immediately */
+ wiiuse_send_next_pending_read_request(wm);
+ } else {
+ struct read_req_t* nptr = wm->read_req;
+ for (; nptr->next; nptr = nptr->next);
+ nptr->next = req;
+
+ WIIUSE_DEBUG("Added pending data read request.");
+ }
+
+ return 1;
+}
+
+
+/** + * @brief Read data from the wiimote (event version). + * + * @param wm Pointer to a wiimote_t structure. + * @param buffer An allocated buffer to store the data as it arrives from the wiimote. + * Must be persistent in memory and large enough to hold the data. + * @param addr The address of wiimote memory to read from. + * @param len The length of the block to be read. + * + * The library can only handle one data read request at a time + * because it must keep track of the buffer and other + * events that are specific to that request. So if a request + * has already been made, subsequent requests will be added + * to a pending list and be sent out when the previous + * finishes. + */ +int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, unsigned short len) { + struct read_req_t* req; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + if (!buffer || !len) + return 0; + + /* make this request structure */ + req = (struct read_req_t*)malloc(sizeof(struct read_req_t)); + req->cb = NULL; + req->buf = buffer; + req->addr = addr; + req->size = len; + req->wait = len; + req->dirty = 0; + req->next = NULL; + + /* add this to the request list */ + if (!wm->read_req) { + /* root node */ + wm->read_req = req; + + WIIUSE_DEBUG("Data read request can be sent out immediately."); + + /* send the request out immediately */ + wiiuse_send_next_pending_read_request(wm); + } else { + struct read_req_t* nptr = wm->read_req; + for (; nptr->next; nptr = nptr->next); + nptr->next = req; + + WIIUSE_DEBUG("Added pending data read request."); + } + + return 1; +} + + +/**
+ * @brief Send the next pending data read request to the wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * @see wiiuse_read_data()
+ *
+ * This function is not part of the wiiuse API.
+ */
+void wiiuse_send_next_pending_read_request(struct wiimote_t* wm) {
+ byte buf[6];
+ struct read_req_t* req;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return;
+ if (!wm->read_req) return;
+
+ /* skip over dirty ones since they have already been read */ + req = wm->read_req; + while (req && req->dirty) + req = req->next; + if (!req) + return;
+
+ /* the offset is in big endian */
+ *(int*)(buf) = BIG_ENDIAN_LONG(req->addr);
+
+ /* the length is in big endian */
+ *(short*)(buf + 4) = BIG_ENDIAN_SHORT(req->size);
+
+ WIIUSE_DEBUG("Request read at address: 0x%x length: %i", req->addr, req->size);
+ wiiuse_send(wm, WM_CMD_READ_DATA, buf, 6);
+}
+
+
+/**
+ * @brief Request the wiimote controller status.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * Controller status includes: battery level, LED status, expansions
+ */
+void wiiuse_status(struct wiimote_t* wm) {
+ byte buf = 0;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return;
+
+ WIIUSE_DEBUG("Requested wiimote status.");
+
+ wiiuse_send(wm, WM_CMD_CTRL_STATUS, &buf, 1);
+}
+
+
+/**
+ * @brief Find a wiimote_t structure by its unique identifier.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param wiimotes The number of wiimote_t structures in \a wm.
+ * @param unid The unique identifier to search for.
+ *
+ * @return Pointer to a wiimote_t structure, or NULL if not found.
+ */
+struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid) {
+ int i = 0;
+
+ for (; i < wiimotes; ++i) {
+ if (wm[i]->unid == unid)
+ return wm[i];
+ }
+
+ return NULL;
+}
+
+
+/**
+ * @brief Write data to the wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param addr The address to write to.
+ * @param data The data to be written to the memory location.
+ * @param len The length of the block to be written.
+ */
+int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len) {
+ byte buf[21] = {0}; /* the payload is always 23 */
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+ if (!data || !len)
+ return 0;
+
+ WIIUSE_DEBUG("Writing %i bytes to memory location 0x%x...", len, addr);
+
+ #ifdef WITH_WIIUSE_DEBUG
+ {
+ int i = 0;
+ printf("Write data is: ");
+ for (; i < len; ++i)
+ printf("%x ", data[i]);
+ printf("\n");
+ }
+ #endif
+
+ /* the offset is in big endian */
+ *(int*)(buf) = BIG_ENDIAN_LONG(addr);
+
+ /* length */
+ *(byte*)(buf + 4) = len;
+
+ /* data */
+ memcpy(buf + 5, data, len);
+
+ wiiuse_send(wm, WM_CMD_WRITE_DATA, buf, 21);
+ return 1;
+}
+
+
+/**
+ * @brief Send a packet to the wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param report_type The report type to send (WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc). Found in wiiuse.h
+ * @param msg The payload.
+ * @param len Length of the payload in bytes.
+ *
+ * This function should replace any write()s directly to the wiimote device.
+ */
+int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) {
+ byte buf[32]; /* no payload is better than this */
+ int rumble = 0;
+
+ #ifndef WIN32
+ buf[0] = WM_SET_REPORT | WM_BT_OUTPUT;
+ buf[1] = report_type;
+ #else
+ buf[0] = report_type;
+ #endif
+
+ switch (report_type) {
+ case WM_CMD_LED:
+ case WM_CMD_RUMBLE:
+ case WM_CMD_CTRL_STATUS:
+ {
+ /* Rumble flag for: 0x11, 0x13, 0x14, 0x15, 0x19 or 0x1a */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+ rumble = 1;
+ break;
+ }
+ default:
+ break;
+ }
+
+ #ifndef WIN32
+ memcpy(buf+2, msg, len);
+ if (rumble)
+ buf[2] |= 0x01;
+ #else
+ memcpy(buf+1, msg, len);
+ if (rumble)
+ buf[1] |= 0x01;
+ #endif
+
+ #ifdef WITH_WIIUSE_DEBUG
+ {
+ int x = 2;
+ printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]);
+ #ifndef WIN32
+ for (; x < len+2; ++x)
+ #else
+ for (; x < len+1; ++x)
+ #endif
+ printf("%.2x ", buf[x]);
+ printf("\n");
+ }
+ #endif
+
+ #ifndef WIN32
+ return wiiuse_io_write(wm, buf, len+2);
+ #else
+ return wiiuse_io_write(wm, buf, len+1);
+ #endif
+}
+
+
+/**
+ * @brief Set flags for the specified wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param enable Flags to enable.
+ * @param disable Flags to disable.
+ *
+ * @return The flags set after 'enable' and 'disable' have been applied.
+ *
+ * The values 'enable' and 'disable' may be any flags OR'ed together.
+ * Flags are defined in wiiuse.h.
+ */
+int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) {
+ if (!wm) return 0;
+
+ /* remove mutually exclusive flags */
+ enable &= ~disable;
+ disable &= ~enable;
+
+ wm->flags |= enable;
+ wm->flags &= ~disable;
+
+ return wm->flags;
+}
+
+
+/**
+ * @brief Set the wiimote smoothing alpha value.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param alpha The alpha value to set. Between 0 and 1.
+ *
+ * @return Returns the old alpha value.
+ *
+ * The alpha value is between 0 and 1 and is used in an exponential
+ * smoothing algorithm.
+ *
+ * Smoothing is only performed if the WIIMOTE_USE_SMOOTHING is set.
+ */
+float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha) {
+ float old;
+
+ if (!wm) return 0.0f;
+
+ old = wm->accel_calib.st_alpha;
+
+ wm->accel_calib.st_alpha = alpha;
+
+ /* if there is a nunchuk set that too */
+ if (wm->exp.type == EXP_NUNCHUK)
+ wm->exp.nunchuk.accel_calib.st_alpha = alpha;
+
+ return old;
+}
+
+
+/**
+ * @brief Set the bluetooth stack type to use.
+ *
+ * @param wm Array of wiimote_t structures.
+ * @param wiimotes Number of objects in the wm array.
+ * @param type The type of bluetooth stack to use.
+ */
+void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type) {
+ #ifdef WIN32
+ int i;
+
+ if (!wm) return;
+
+ for (i = 0; i < wiimotes; ++i)
+ wm[i]->stack = type;
+ #endif
+}
+
+
+/**
+ * @brief Set the orientation event threshold.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param threshold The decimal place that should be considered a significant change.
+ *
+ * If threshold is 0.01, and any angle changes by 0.01 then a significant change
+ * has occured and the event callback will be invoked. If threshold is 1 then
+ * the angle has to change by a full degree to generate an event.
+ */
+void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold) {
+ if (!wm) return;
+
+ wm->orient_threshold = threshold;
+}
+
+
+/**
+ * @brief Set the accelerometer event threshold.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param threshold The decimal place that should be considered a significant change.
+ */
+void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold) {
+ if (!wm) return;
+
+ wm->accel_threshold = threshold;
+}
+
+
+/**
+ * @brief Try to resync with the wiimote by starting a new handshake.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+void wiiuse_resync(struct wiimote_t* wm) {
+ if (!wm) return;
+
+ wm->handshake_state = 0;
+ wiiuse_handshake(wm, NULL, 0);
+}
+
+
+/**
+ * @brief Set the normal and expansion handshake timeouts.
+ *
+ * @param wm Array of wiimote_t structures.
+ * @param wiimotes Number of objects in the wm array.
+ * @param normal_timeout The timeout in milliseconds for a normal read.
+ * @param exp_timeout The timeout in millisecondsd to wait for an expansion handshake.
+ */
+void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout) {
+ #ifdef WIN32
+ int i;
+
+ if (!wm) return;
+
+ for (i = 0; i < wiimotes; ++i) {
+ wm[i]->normal_timeout = normal_timeout;
+ wm[i]->exp_timeout = exp_timeout;
+ }
+ #endif
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.h new file mode 100644 index 0000000000..9dff81c8e4 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.h @@ -0,0 +1,653 @@ +/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ *
+ * @brief API header file.
+ *
+ * If this file is included from inside the wiiuse source
+ * and not from a third party program, then wiimote_internal.h
+ * is also included which extends this file.
+ */
+
+#ifndef WIIUSE_H_INCLUDED
+#define WIIUSE_H_INCLUDED
+
+#ifdef _WIN32
+ /* windows */
+ #include <windows.h>
+#else
+ /* nix */
+ #include <bluetooth/bluetooth.h>
+#endif
+
+#ifdef WIIUSE_INTERNAL_H_INCLUDED
+ #define WCONST
+#else
+ #define WCONST const
+#endif
+
+/* led bit masks */
+#define WIIMOTE_LED_NONE 0x00
+#define WIIMOTE_LED_1 0x10
+#define WIIMOTE_LED_2 0x20
+#define WIIMOTE_LED_3 0x40
+#define WIIMOTE_LED_4 0x80
+
+/* button codes */
+#define WIIMOTE_BUTTON_TWO 0x0001
+#define WIIMOTE_BUTTON_ONE 0x0002
+#define WIIMOTE_BUTTON_B 0x0004
+#define WIIMOTE_BUTTON_A 0x0008
+#define WIIMOTE_BUTTON_MINUS 0x0010
+#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020
+#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040
+#define WIIMOTE_BUTTON_HOME 0x0080
+#define WIIMOTE_BUTTON_LEFT 0x0100
+#define WIIMOTE_BUTTON_RIGHT 0x0200
+#define WIIMOTE_BUTTON_DOWN 0x0400
+#define WIIMOTE_BUTTON_UP 0x0800
+#define WIIMOTE_BUTTON_PLUS 0x1000
+#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000
+#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000
+#define WIIMOTE_BUTTON_UNKNOWN 0x8000
+#define WIIMOTE_BUTTON_ALL 0x1F9F
+
+/* nunchul button codes */
+#define NUNCHUK_BUTTON_Z 0x01
+#define NUNCHUK_BUTTON_C 0x02
+#define NUNCHUK_BUTTON_ALL 0x03
+
+/* classic controller button codes */
+#define CLASSIC_CTRL_BUTTON_UP 0x0001
+#define CLASSIC_CTRL_BUTTON_LEFT 0x0002
+#define CLASSIC_CTRL_BUTTON_ZR 0x0004
+#define CLASSIC_CTRL_BUTTON_X 0x0008
+#define CLASSIC_CTRL_BUTTON_A 0x0010
+#define CLASSIC_CTRL_BUTTON_Y 0x0020
+#define CLASSIC_CTRL_BUTTON_B 0x0040
+#define CLASSIC_CTRL_BUTTON_ZL 0x0080
+#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200
+#define CLASSIC_CTRL_BUTTON_PLUS 0x0400
+#define CLASSIC_CTRL_BUTTON_HOME 0x0800
+#define CLASSIC_CTRL_BUTTON_MINUS 0x1000
+#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000
+#define CLASSIC_CTRL_BUTTON_DOWN 0x4000
+#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000
+#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF
+
+/* guitar hero 3 button codes */
+#define GUITAR_HERO_3_BUTTON_STRUM_UP 0x0001
+#define GUITAR_HERO_3_BUTTON_YELLOW 0x0008
+#define GUITAR_HERO_3_BUTTON_GREEN 0x0010
+#define GUITAR_HERO_3_BUTTON_BLUE 0x0020
+#define GUITAR_HERO_3_BUTTON_RED 0x0040
+#define GUITAR_HERO_3_BUTTON_ORANGE 0x0080
+#define GUITAR_HERO_3_BUTTON_PLUS 0x0400
+#define GUITAR_HERO_3_BUTTON_MINUS 0x1000
+#define GUITAR_HERO_3_BUTTON_STRUM_DOWN 0x4000
+#define GUITAR_HERO_3_BUTTON_ALL 0xFEFF
+
+
+/* wiimote option flags */
+#define WIIUSE_SMOOTHING 0x01
+#define WIIUSE_CONTINUOUS 0x02
+#define WIIUSE_ORIENT_THRESH 0x04
+#define WIIUSE_INIT_FLAGS (WIIUSE_SMOOTHING | WIIUSE_ORIENT_THRESH)
+
+#define WIIUSE_ORIENT_PRECISION 100.0f
+
+/* expansion codes */
+#define EXP_NONE 0
+#define EXP_NUNCHUK 1
+#define EXP_CLASSIC 2
+#define EXP_GUITAR_HERO_3 3
+
+/* IR correction types */
+typedef enum ir_position_t {
+ WIIUSE_IR_ABOVE,
+ WIIUSE_IR_BELOW
+} ir_position_t;
+
+/**
+ * @brief Check if a button is pressed.
+ * @param dev Pointer to a wiimote_t or expansion structure.
+ * @param button The button you are interested in.
+ * @return 1 if the button is pressed, 0 if not.
+ */
+#define IS_PRESSED(dev, button) ((dev->btns & button) == button)
+
+/**
+ * @brief Check if a button is being held.
+ * @param dev Pointer to a wiimote_t or expansion structure.
+ * @param button The button you are interested in.
+ * @return 1 if the button is held, 0 if not.
+ */
+#define IS_HELD(dev, button) ((dev->btns_held & button) == button)
+
+/**
+ * @brief Check if a button is released on this event. \n\n
+ * This does not mean the button is not pressed, it means \n
+ * this button was just now released.
+ * @param dev Pointer to a wiimote_t or expansion structure.
+ * @param button The button you are interested in.
+ * @return 1 if the button is released, 0 if not.
+ *
+ */
+#define IS_RELEASED(dev, button) ((dev->btns_released & button) == button)
+
+/**
+ * @brief Check if a button has just been pressed this event.
+ * @param dev Pointer to a wiimote_t or expansion structure.
+ * @param button The button you are interested in.
+ * @return 1 if the button is pressed, 0 if not.
+ */
+#define IS_JUST_PRESSED(dev, button) (IS_PRESSED(dev, button) && !IS_HELD(dev, button)) + +/** + * @brief Return the IR sensitivity level. + * @param wm Pointer to a wiimote_t structure. + * @param lvl [out] Pointer to an int that will hold the level setting. + * If no level is set 'lvl' will be set to 0. + */ +#define WIIUSE_GET_IR_SENSITIVITY(dev, lvl) \ + do { \ + if ((wm->state & 0x0200) == 0x0200) *lvl = 1; \ + else if ((wm->state & 0x0400) == 0x0400) *lvl = 2; \ + else if ((wm->state & 0x0800) == 0x0800) *lvl = 3; \ + else if ((wm->state & 0x1000) == 0x1000) *lvl = 4; \ + else if ((wm->state & 0x2000) == 0x2000) *lvl = 5; \ + else *lvl = 0; \ + } while (0) +
+#define WIIUSE_USING_ACC(wm) ((wm->state & 0x020) == 0x020)
+#define WIIUSE_USING_EXP(wm) ((wm->state & 0x040) == 0x040)
+#define WIIUSE_USING_IR(wm) ((wm->state & 0x080) == 0x080)
+#define WIIUSE_USING_SPEAKER(wm) ((wm->state & 0x100) == 0x100)
+
+#define WIIUSE_IS_LED_SET(wm, num) ((wm->leds & WIIMOTE_LED_##num) == WIIMOTE_LED_##num)
+
+/*
+ * Largest known payload is 21 bytes.
+ * Add 2 for the prefix and round up to a power of 2.
+ */
+#define MAX_PAYLOAD 32
+
+/*
+ * This is left over from an old hack, but it may actually
+ * be a useful feature to keep so it wasn't removed.
+ */
+#ifdef WIN32
+ #define WIIMOTE_DEFAULT_TIMEOUT 10
+ #define WIIMOTE_EXP_TIMEOUT 10
+#endif
+
+typedef unsigned char byte;
+typedef char sbyte;
+
+struct wiimote_t;
+struct vec3b_t;
+struct orient_t;
+struct gforce_t;
+
+
+/**
+ * @brief Callback that handles a read event.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param data Pointer to the filled data block.
+ * @param len Length in bytes of the data block.
+ *
+ * @see wiiuse_init()
+ *
+ * A registered function of this type is called automatically by the wiiuse
+ * library when the wiimote has returned the full data requested by a previous
+ * call to wiiuse_read_data().
+ */
+typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, unsigned short len);
+
+
+/**
+ * @struct read_req_t
+ * @brief Data read request structure.
+ */
+struct read_req_t {
+ wiiuse_read_cb cb; /**< read data callback */
+ byte* buf; /**< buffer where read data is written */
+ unsigned int addr; /**< the offset that the read started at */
+ unsigned short size; /**< the length of the data read */
+ unsigned short wait; /**< num bytes still needed to finish read */ + byte dirty; /**< set to 1 if not using callback and needs to be cleaned up */
+
+ struct read_req_t* next; /**< next read request in the queue */
+};
+
+
+/**
+ * @struct vec2b_t
+ * @brief Unsigned x,y byte vector.
+ */
+typedef struct vec2b_t {
+ byte x, y;
+} vec2b_t;
+
+
+/**
+ * @struct vec3b_t
+ * @brief Unsigned x,y,z byte vector.
+ */
+typedef struct vec3b_t {
+ byte x, y, z;
+} vec3b_t;
+
+
+/**
+ * @struct vec3f_t
+ * @brief Signed x,y,z float struct.
+ */
+typedef struct vec3f_t {
+ float x, y, z;
+} vec3f_t;
+
+
+/**
+ * @struct orient_t
+ * @brief Orientation struct.
+ *
+ * Yaw, pitch, and roll range from -180 to 180 degrees.
+ */
+typedef struct orient_t {
+ float roll; /**< roll, this may be smoothed if enabled */
+ float pitch; /**< pitch, this may be smoothed if enabled */
+ float yaw;
+
+ float a_roll; /**< absolute roll, unsmoothed */
+ float a_pitch; /**< absolute pitch, unsmoothed */
+} orient_t;
+
+
+/**
+ * @struct gforce_t
+ * @brief Gravity force struct.
+ */
+typedef struct gforce_t {
+ float x, y, z;
+} gforce_t;
+
+
+/**
+ * @struct accel_t
+ * @brief Accelerometer struct. For any device with an accelerometer.
+ */
+typedef struct accel_t {
+ struct vec3b_t cal_zero; /**< zero calibration */
+ struct vec3b_t cal_g; /**< 1g difference around 0cal */
+
+ float st_roll; /**< last smoothed roll value */
+ float st_pitch; /**< last smoothed roll pitch */
+ float st_alpha; /**< alpha value for smoothing [0-1] */
+} accel_t;
+
+
+/**
+ * @struct ir_dot_t
+ * @brief A single IR source.
+ */
+typedef struct ir_dot_t {
+ byte visible; /**< if the IR source is visible */
+
+ unsigned int x; /**< interpolated X coordinate */
+ unsigned int y; /**< interpolated Y coordinate */
+
+ short rx; /**< raw X coordinate (0-1023) */
+ short ry; /**< raw Y coordinate (0-767) */
+
+ byte order; /**< increasing order by x-axis value */
+
+ byte size; /**< size of the IR dot (0-15) */
+} ir_dot_t;
+
+
+/**
+ * @enum aspect_t
+ * @brief Screen aspect ratio.
+ */
+typedef enum aspect_t {
+ WIIUSE_ASPECT_4_3,
+ WIIUSE_ASPECT_16_9
+} aspect_t;
+
+
+/**
+ * @struct ir_t
+ * @brief IR struct. Hold all data related to the IR tracking.
+ */
+typedef struct ir_t {
+ struct ir_dot_t dot[4]; /**< IR dots */
+ byte num_dots; /**< number of dots at this time */
+
+ enum aspect_t aspect; /**< aspect ratio of the screen */
+
+ enum ir_position_t pos; /**< IR sensor bar position */
+
+ unsigned int vres[2]; /**< IR virtual screen resolution */
+ int offset[2]; /**< IR XY correction offset */
+ int state; /**< keeps track of the IR state */
+
+ int ax; /**< absolute X coordinate */
+ int ay; /**< absolute Y coordinate */
+
+ int x; /**< calculated X coordinate */
+ int y; /**< calculated Y coordinate */
+
+ float distance; /**< pixel distance between first 2 dots*/
+ float z; /**< calculated distance */
+} ir_t;
+
+
+/**
+ * @struct joystick_t
+ * @brief Joystick calibration structure.
+ *
+ * The angle \a ang is relative to the positive y-axis into quadrant I
+ * and ranges from 0 to 360 degrees. So if the joystick is held straight
+ * upwards then angle is 0 degrees. If it is held to the right it is 90,
+ * down is 180, and left is 270.
+ *
+ * The magnitude \a mag is the distance from the center to where the
+ * joystick is being held. The magnitude ranges from 0 to 1.
+ * If the joystick is only slightly tilted from the center the magnitude
+ * will be low, but if it is closer to the outter edge the value will
+ * be higher.
+ */
+typedef struct joystick_t {
+ struct vec2b_t max; /**< maximum joystick values */
+ struct vec2b_t min; /**< minimum joystick values */
+ struct vec2b_t center; /**< center joystick values */
+
+ float ang; /**< angle the joystick is being held */
+ float mag; /**< magnitude of the joystick (range 0-1) */
+} joystick_t;
+
+
+/**
+ * @struct nunchuk_t
+ * @brief Nunchuk expansion device.
+ */
+typedef struct nunchuk_t {
+ struct accel_t accel_calib; /**< nunchuk accelerometer calibration */
+ struct joystick_t js; /**< joystick calibration */
+
+ int* flags; /**< options flag (points to wiimote_t.flags) */
+
+ byte btns; /**< what buttons have just been pressed */
+ byte btns_held; /**< what buttons are being held down */
+ byte btns_released; /**< what buttons were just released this */
+ + float orient_threshold; /**< threshold for orient to generate an event */ + int accel_threshold; /**< threshold for accel to generate an event */ +
+ struct vec3b_t accel; /**< current raw acceleration data */
+ struct orient_t orient; /**< current orientation on each axis */
+ struct gforce_t gforce; /**< current gravity forces on each axis */
+} nunchuk_t;
+
+
+/**
+ * @struct classic_ctrl_t
+ * @brief Classic controller expansion device.
+ */
+typedef struct classic_ctrl_t {
+ short btns; /**< what buttons have just been pressed */
+ short btns_held; /**< what buttons are being held down */
+ short btns_released; /**< what buttons were just released this */
+
+ float r_shoulder; /**< right shoulder button (range 0-1) */
+ float l_shoulder; /**< left shoulder button (range 0-1) */
+
+ struct joystick_t ljs; /**< left joystick calibration */
+ struct joystick_t rjs; /**< right joystick calibration */
+} classic_ctrl_t;
+
+
+/**
+ * @struct guitar_hero_3_t
+ * @brief Guitar Hero 3 expansion device.
+ */
+typedef struct guitar_hero_3_t {
+ short btns; /**< what buttons have just been pressed */
+ short btns_held; /**< what buttons are being held down */
+ short btns_released; /**< what buttons were just released this */
+
+ float whammy_bar; /**< whammy bar (range 0-1) */
+
+ struct joystick_t js; /**< joystick calibration */
+} guitar_hero_3_t;
+
+
+/**
+ * @struct expansion_t
+ * @brief Generic expansion device plugged into wiimote.
+ */
+typedef struct expansion_t {
+ int type; /**< type of expansion attached */
+
+ union {
+ struct nunchuk_t nunchuk;
+ struct classic_ctrl_t classic;
+ struct guitar_hero_3_t gh3;
+ };
+} expansion_t;
+
+
+/**
+ * @enum win32_bt_stack_t
+ * @brief Available bluetooth stacks for Windows.
+ */
+typedef enum win_bt_stack_t {
+ WIIUSE_STACK_UNKNOWN,
+ WIIUSE_STACK_MS,
+ WIIUSE_STACK_BLUESOLEIL
+} win_bt_stack_t;
+
+
+/**
+ * @struct wiimote_state_t
+ * @brief Significant data from the previous event.
+ */
+typedef struct wiimote_state_t {
+ /* expansion_t */
+ float exp_ljs_ang;
+ float exp_rjs_ang;
+ float exp_ljs_mag;
+ float exp_rjs_mag;
+ unsigned short exp_btns;
+ struct orient_t exp_orient;
+ struct vec3b_t exp_accel; + float exp_r_shoulder;
+ float exp_l_shoulder;
+
+ /* ir_t */
+ int ir_ax;
+ int ir_ay;
+ float ir_distance;
+
+ struct orient_t orient;
+ unsigned short btns;
+
+ struct vec3b_t accel;
+} wiimote_state_t;
+
+
+/**
+ * @enum WIIUSE_EVENT_TYPE
+ * @brief Events that wiiuse can generate from a poll.
+ */
+typedef enum WIIUSE_EVENT_TYPE {
+ WIIUSE_NONE = 0,
+ WIIUSE_EVENT,
+ WIIUSE_STATUS, + WIIUSE_CONNECT,
+ WIIUSE_DISCONNECT, + WIIUSE_UNEXPECTED_DISCONNECT, + WIIUSE_READ_DATA, + WIIUSE_NUNCHUK_INSERTED,
+ WIIUSE_NUNCHUK_REMOVED, + WIIUSE_CLASSIC_CTRL_INSERTED, + WIIUSE_CLASSIC_CTRL_REMOVED, + WIIUSE_GUITAR_HERO_3_CTRL_INSERTED, + WIIUSE_GUITAR_HERO_3_CTRL_REMOVED +} WIIUSE_EVENT_TYPE;
+
+/**
+ * @struct wiimote_t
+ * @brief Wiimote structure.
+ */
+typedef struct wiimote_t {
+ WCONST int unid; /**< user specified id */
+
+ #ifndef WIN32
+ WCONST bdaddr_t bdaddr; /**< bt address */
+ WCONST char bdaddr_str[18]; /**< readable bt address */
+ WCONST int out_sock; /**< output socket */
+ WCONST int in_sock; /**< input socket */
+ #else
+ WCONST HANDLE dev_handle; /**< HID handle */
+ WCONST OVERLAPPED hid_overlap; /**< overlap handle */
+ WCONST enum win_bt_stack_t stack; /**< type of bluetooth stack to use */
+ WCONST int timeout; /**< read timeout */
+ WCONST byte normal_timeout; /**< normal timeout */
+ WCONST byte exp_timeout; /**< timeout for expansion handshake */
+ #endif
+
+ WCONST int state; /**< various state flags */
+ WCONST byte leds; /**< currently lit leds */
+ WCONST float battery_level; /**< battery level */
+
+ WCONST int flags; /**< options flag */ + + WCONST byte handshake_state; /**< the state of the connection handshake */
+
+ WCONST struct read_req_t* read_req; /**< list of data read requests */
+ WCONST struct accel_t accel_calib; /**< wiimote accelerometer calibration */
+ WCONST struct expansion_t exp; /**< wiimote expansion device */
+
+ WCONST struct vec3b_t accel; /**< current raw acceleration data */
+ WCONST struct orient_t orient; /**< current orientation on each axis */
+ WCONST struct gforce_t gforce; /**< current gravity forces on each axis */
+
+ WCONST struct ir_t ir; /**< IR data */
+
+ WCONST unsigned short btns; /**< what buttons have just been pressed */
+ WCONST unsigned short btns_held; /**< what buttons are being held down */
+ WCONST unsigned short btns_released; /**< what buttons were just released this */
+
+ WCONST float orient_threshold; /**< threshold for orient to generate an event */
+ WCONST int accel_threshold; /**< threshold for accel to generate an event */
+
+ WCONST struct wiimote_state_t lstate; /**< last saved state */
+
+ WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occured */
+ WCONST byte event_buf[MAX_PAYLOAD]; /**< event buffer */
+} wiimote;
+
+
+/*****************************************
+ *
+ * Include API specific stuff
+ *
+ *****************************************/
+
+#ifdef _WIN32
+ #define WIIUSE_EXPORT_DECL __declspec(dllexport)
+ #define WIIUSE_IMPORT_DECL __declspec(dllimport)
+#else
+ #define WIIUSE_EXPORT_DECL
+ #define WIIUSE_IMPORT_DECL
+#endif
+
+#ifdef WIIUSE_COMPILE_LIB
+ #define WIIUSE_EXPORT WIIUSE_EXPORT_DECL
+#else
+ #define WIIUSE_EXPORT WIIUSE_IMPORT_DECL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* wiiuse.c */
+WIIUSE_EXPORT extern const char* wiiuse_version();
+
+WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds);
+WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len);
+WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len);
+WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm);
+WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid);
+WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable);
+WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha);
+WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type);
+WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold);
+WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout);
+WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold);
+
+/* connect.c */
+WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout);
+WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm);
+
+/* events.c */
+WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes);
+
+/* ir.c */
+WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y);
+WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos);
+WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect); +WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level); + +/* nunchuk.c */ +WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold); +WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold); +
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* WIIUSE_H_INCLUDED */
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse_internal.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse_internal.h new file mode 100644 index 0000000000..1b2f423862 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse_internal.h @@ -0,0 +1,226 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief General internal wiiuse stuff. + * + * Since Wiiuse is a library, wiiuse.h is a duplicate + * of the API header. + * + * The code that would normally go in that file, but + * which is not needed by third party developers, + * is put here. + * + * So wiiuse_internal.h is included by other files + * internally, wiiuse.h is included only here. + */ + +#ifndef WIIUSE_INTERNAL_H_INCLUDED +#define WIIUSE_INTERNAL_H_INCLUDED + +#ifndef WIN32 + #include <arpa/inet.h> /* htons() */ + #include <bluetooth/bluetooth.h> +#endif + +#include "definitions.h" + +/* wiiuse version */ +#define WIIUSE_VERSION "0.12" + +/******************** + * + * Wiimote internal codes + * + ********************/ + +/* Communication channels */ +#define WM_OUTPUT_CHANNEL 0x11 +#define WM_INPUT_CHANNEL 0x13 + +#define WM_SET_REPORT 0x50 + +/* commands */ +#define WM_CMD_LED 0x11 +#define WM_CMD_REPORT_TYPE 0x12 +#define WM_CMD_RUMBLE 0x13 +#define WM_CMD_IR 0x13 +#define WM_CMD_CTRL_STATUS 0x15 +#define WM_CMD_WRITE_DATA 0x16 +#define WM_CMD_READ_DATA 0x17 +#define WM_CMD_IR_2 0x1A + +/* input report ids */ +#define WM_RPT_CTRL_STATUS 0x20 +#define WM_RPT_READ 0x21 +#define WM_RPT_WRITE 0x22 +#define WM_RPT_BTN 0x30 +#define WM_RPT_BTN_ACC 0x31 +#define WM_RPT_BTN_ACC_IR 0x33 +#define WM_RPT_BTN_EXP 0x34 +#define WM_RPT_BTN_ACC_EXP 0x35 +#define WM_RPT_BTN_IR_EXP 0x36 +#define WM_RPT_BTN_ACC_IR_EXP 0x37 + +#define WM_BT_INPUT 0x01 +#define WM_BT_OUTPUT 0x02 + +/* Identify the wiimote device by its class */ +#define WM_DEV_CLASS_0 0x04 +#define WM_DEV_CLASS_1 0x25 +#define WM_DEV_CLASS_2 0x00 +#define WM_VENDOR_ID 0x057E +#define WM_PRODUCT_ID 0x0306 + +/* controller status stuff */ +#define WM_MAX_BATTERY_CODE 0xC8 + +/* offsets in wiimote memory */ +#define WM_MEM_OFFSET_CALIBRATION 0x16 +#define WM_EXP_MEM_BASE 0x04A40000 +#define WM_EXP_MEM_ENABLE 0x04A40040 +#define WM_EXP_MEM_CALIBR 0x04A40020 + +#define WM_REG_IR 0x04B00030 +#define WM_REG_IR_BLOCK1 0x04B00000 +#define WM_REG_IR_BLOCK2 0x04B0001A +#define WM_REG_IR_MODENUM 0x04B00033 + +/* ir block data */ +#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe" +#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05" +#define WM_IR_BLOCK1_LEVEL2 "\x02\x00\x00\x71\x01\x00\x96\x00\xb4" +#define WM_IR_BLOCK2_LEVEL2 "\xb3\x04" +#define WM_IR_BLOCK1_LEVEL3 "\x02\x00\x00\x71\x01\x00\xaa\x00\x64" +#define WM_IR_BLOCK2_LEVEL3 "\x63\x03" +#define WM_IR_BLOCK1_LEVEL4 "\x02\x00\x00\x71\x01\x00\xc8\x00\x36" +#define WM_IR_BLOCK2_LEVEL4 "\x35\x03" +#define WM_IR_BLOCK1_LEVEL5 "\x07\x00\x00\x71\x01\x00\x72\x00\x20" +#define WM_IR_BLOCK2_LEVEL5 "\x1f\x03" + +#define WM_IR_TYPE_BASIC 0x01 +#define WM_IR_TYPE_EXTENDED 0x03 + +/* controller status flags for the first message byte */ +/* bit 1 is unknown */ +#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02 +#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04 +#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08 +#define WM_CTRL_STATUS_BYTE1_LED_1 0x10 +#define WM_CTRL_STATUS_BYTE1_LED_2 0x20 +#define WM_CTRL_STATUS_BYTE1_LED_3 0x40 +#define WM_CTRL_STATUS_BYTE1_LED_4 0x80 + +/* aspect ratio */ +#define WM_ASPECT_16_9_X 660 +#define WM_ASPECT_16_9_Y 370 +#define WM_ASPECT_4_3_X 560 +#define WM_ASPECT_4_3_Y 420 + + +/** + * Expansion stuff + */ + +/* encrypted expansion id codes (located at 0x04A400FC) */ +#define EXP_ID_CODE_NUNCHUK 0x9A1EFEFE +#define EXP_ID_CODE_CLASSIC_CONTROLLER 0x9A1EFDFD +#define EXP_ID_CODE_GUITAR 0x9A1EFDFB + +#define EXP_HANDSHAKE_LEN 224
+
+/******************** + * + * End Wiimote internal codes + * + ********************/ + +/* wiimote state flags - (some duplicated in wiiuse.h)*/ +#define WIIMOTE_STATE_DEV_FOUND 0x0001 +#define WIIMOTE_STATE_HANDSHAKE 0x0002 /* actual connection exists but no handshake yet */ +#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x0004 /* actual connection exists but no handshake yet */ +#define WIIMOTE_STATE_CONNECTED 0x0008 +#define WIIMOTE_STATE_RUMBLE 0x0010 +#define WIIMOTE_STATE_ACC 0x0020 +#define WIIMOTE_STATE_EXP 0x0040 +#define WIIMOTE_STATE_IR 0x0080 +#define WIIMOTE_STATE_SPEAKER 0x0100 +#define WIIMOTE_STATE_IR_SENS_LVL1 0x0200 +#define WIIMOTE_STATE_IR_SENS_LVL2 0x0400 +#define WIIMOTE_STATE_IR_SENS_LVL3 0x0800 +#define WIIMOTE_STATE_IR_SENS_LVL4 0x1000 +#define WIIMOTE_STATE_IR_SENS_LVL5 0x2000 + +#define WIIMOTE_INIT_STATES (WIIMOTE_STATE_IR_SENS_LVL3) + +/* macro to manage states */ +#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s)) +#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s)) +#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s)) +#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s)) + +#define WIIMOTE_IS_FLAG_SET(wm, s) ((wm->flags & (s)) == (s)) +#define WIIMOTE_ENABLE_FLAG(wm, s) (wm->flags |= (s)) +#define WIIMOTE_DISABLE_FLAG(wm, s) (wm->flags &= ~(s)) +#define WIIMOTE_TOGGLE_FLAG(wm, s) ((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s)) + +#define NUNCHUK_IS_FLAG_SET(wm, s) ((*(wm->flags) & (s)) == (s)) + +/* misc macros */ +#define WIIMOTE_ID(wm) (wm->unid) +#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED)) + +/* + * Smooth tilt calculations are computed with the + * exponential moving average formula: + * St = St_last + (alpha * (tilt - St_last)) + * alpha is between 0 and 1 + */ +#define WIIUSE_DEFAULT_SMOOTH_ALPHA 0.07f + +#define SMOOTH_ROLL 0x01 +#define SMOOTH_PITCH 0x02
+
+#include "wiiuse.h" +
+#ifdef __cplusplus +extern "C" { +#endif + +/* not part of the api */ +int wiiuse_set_report_type(struct wiimote_t* wm); +void wiiuse_send_next_pending_read_request(struct wiimote_t* wm); +int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len); +int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int offset, unsigned short len); + +#ifdef __cplusplus +} +#endif + +#endif /* WIIUSE_INTERNAL_H_INCLUDED */ diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.cbp b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.cbp new file mode 100644 index 0000000000..a71d3a0ceb --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.cbp @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="wiiuse" /> + <Option makefile_is_custom="1" /> + <Option pch_mode="2" /> + <Option compiler="gcc" /> + <MakeCommands> + <Build command="$make $target" /> + <CompileFile command="$make $file" /> + <Clean command="$make clean" /> + <DistClean command="$make distclean" /> + </MakeCommands> + <Build> + <Target title="Release"> + <Option output="bin/Release/wiiuse" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Release/" /> + <Option type="1" /> + <Option compiler="gcc" /> + <Compiler> + <Add option="-O2" /> + </Compiler> + <Linker> + <Add option="-s" /> + </Linker> + </Target> + </Build> + <Compiler> + <Add option="-Wall" /> + </Compiler> + <Unit filename="CHANGELOG" /> + <Unit filename="README" /> + <Unit filename="example-sdl/sdl.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="example/example.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/classic.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/classic.h" /> + <Unit filename="src/definitions.h" /> + <Unit filename="src/dynamics.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/dynamics.h" /> + <Unit filename="src/events.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/events.h" /> + <Unit filename="src/guitar_hero_3.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/guitar_hero_3.h" /> + <Unit filename="src/io.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/io.h" /> + <Unit filename="src/io_nix.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/io_win.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/ir.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/ir.h" /> + <Unit filename="src/nunchuk.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/nunchuk.h" /> + <Unit filename="src/os.h" /> + <Unit filename="src/wiiuse.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/wiiuse.h" /> + <Unit filename="src/wiiuse_internal.h" /> + <Extensions> + <code_completion /> + <debugger /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.layout b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.layout new file mode 100644 index 0000000000..5b74afea49 --- /dev/null +++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.layout @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_layout_file> + <ActiveTarget name="Release" /> + <File name="CHANGELOG" open="1" top="0" tabpos="7"> + <Cursor position="0" topLine="0" /> + </File> + <File name="README" open="0" top="0" tabpos="8"> + <Cursor position="3582" topLine="0" /> + </File> + <File name="example-sdl/sdl.c" open="1" top="0" tabpos="6"> + <Cursor position="3235" topLine="105" /> + </File> + <File name="example/example.c" open="1" top="0" tabpos="5"> + <Cursor position="0" topLine="0" /> + </File> + <File name="src/classic.c" open="0" top="0" tabpos="4"> + <Cursor position="2464" topLine="53" /> + </File> + <File name="src/definitions.h" open="1" top="0" tabpos="9"> + <Cursor position="1099" topLine="12" /> + </File> + <File name="src/dynamics.c" open="0" top="0" tabpos="10"> + <Cursor position="3216" topLine="59" /> + </File> + <File name="src/events.c" open="1" top="0" tabpos="4"> + <Cursor position="2983" topLine="117" /> + </File> + <File name="src/guitar_hero_3.c" open="0" top="0" tabpos="0"> + <Cursor position="2604" topLine="45" /> + </File> + <File name="src/io.c" open="0" top="0" tabpos="6"> + <Cursor position="1817" topLine="60" /> + </File> + <File name="src/io_nix.c" open="0" top="0" tabpos="8"> + <Cursor position="6286" topLine="211" /> + </File> + <File name="src/io_win.c" open="0" top="0" tabpos="9"> + <Cursor position="4021" topLine="123" /> + </File> + <File name="src/ir.c" open="1" top="0" tabpos="8"> + <Cursor position="0" topLine="0" /> + </File> + <File name="src/ir.h" open="0" top="0" tabpos="0"> + <Cursor position="1059" topLine="0" /> + </File> + <File name="src/nunchuk.c" open="0" top="0" tabpos="10"> + <Cursor position="2454" topLine="43" /> + </File> + <File name="src/nunchuk.h" open="0" top="0" tabpos="0"> + <Cursor position="1171" topLine="0" /> + </File> + <File name="src/wiiuse.c" open="1" top="0" tabpos="1"> + <Cursor position="0" topLine="0" /> + </File> + <File name="src/wiiuse.h" open="1" top="1" tabpos="2"> + <Cursor position="0" topLine="0" /> + </File> + <File name="src/wiiuse_internal.h" open="1" top="0" tabpos="3"> + <Cursor position="3424" topLine="81" /> + </File> +</CodeBlocks_layout_file> diff --git a/tools/EventClients/Clients/XBMC Send/xbmc-send.py b/tools/EventClients/Clients/XBMC Send/xbmc-send.py new file mode 100644 index 0000000000..2746ae026a --- /dev/null +++ b/tools/EventClients/Clients/XBMC Send/xbmc-send.py @@ -0,0 +1,61 @@ +#!/usr/bin/python + +import sys +import getopt +from socket import * +try: + from xbmc.xbmcclient import * +except: + sys.path.append('../../lib/python') + from xbmcclient import * + +def usage(): + print "xbmc-send [OPTION] --action=ACTION" + print 'Example' + print '\txbmc-send --host=192.168.0.1 --port=9777 --action="XBMC.Quit"' + print "Options" + print "\t-?, --help\t\t\tWill bring up this message" + print "\t--host=HOST\t\t\tChoose what HOST to connect to (default=localhost)" + print "\t--port=PORT\t\t\tChoose what PORT to connect to (default=9777)" + print '\t--action=ACTION\t\t\tSends an action to XBMC, this option can be added multiple times to create a macro' + pass + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], "?pa:v", ["help", "host=", "port=", "action="]) + except getopt.GetoptError, err: + # print help information and exit: + print str(err) # will print something like "option -a not recognized" + usage() + sys.exit(2) + ip = "localhost" + port = 9777 + actions = [] + verbose = False + for o, a in opts: + if o in ("-?", "--help"): + usage() + sys.exit() + elif o == "--host": + ip = a + elif o == "--port": + port = int(a) + elif o in ("-a", "--action"): + actions.append(a) + else: + assert False, "unhandled option" + + addr = (ip, port) + sock = socket(AF_INET,SOCK_DGRAM) + + if len(actions) is 0: + usage() + sys.exit(0) + + for action in actions: + print 'Sending action:', action + packet = PacketACTION(actionmessage=action, actiontype=ACTION_BUTTON) + packet.send(sock, addr) + +if __name__=="__main__": + main() diff --git a/tools/EventClients/Clients/Xbox360 Controller/Xbox360Controller.cpp b/tools/EventClients/Clients/Xbox360 Controller/Xbox360Controller.cpp new file mode 100644 index 0000000000..149026776e --- /dev/null +++ b/tools/EventClients/Clients/Xbox360 Controller/Xbox360Controller.cpp @@ -0,0 +1,154 @@ +#include "StdAfx.h"
+#include "Xbox360Controller.h"
+
+
+Xbox360Controller::Xbox360Controller(int num)
+{
+ this->num = num;
+ for (int i = 0; i < 14; i++)
+ {
+ button_down[i] = false;
+ button_released[i] = false;
+ button_pressed[i] = false;
+ }
+}
+
+XINPUT_STATE Xbox360Controller::getState()
+{
+ // Zeroise the state
+ ZeroMemory(&state, sizeof(XINPUT_STATE));
+
+ // Get the state
+ XInputGetState(num, &state);
+
+ return state;
+}
+
+void Xbox360Controller::updateButton(int num, int button)
+{
+ if (state.Gamepad.wButtons & button)
+ {
+ if (!button_down[num])
+ {
+ button_pressed[num] = true;
+ }
+ button_down[num] = true;
+ } else
+ {
+ if (button_down[num])
+ {
+ button_released[num] = true;
+ }
+ button_down[num] = false;
+ }
+}
+
+bool Xbox360Controller::buttonPressed(int num)
+{
+ return button_pressed[num];
+}
+
+bool Xbox360Controller::buttonReleased(int num)
+{
+ return button_released[num];
+}
+
+void Xbox360Controller::updateState()
+{
+ for (int i = 0; i < 14; i++)
+ {
+ button_released[i] = false;
+ button_pressed[i] = false;
+ }
+ if (isConnected())
+ {
+ XINPUT_STATE s = getState();
+ updateButton(0, XINPUT_GAMEPAD_A);
+ updateButton(1, XINPUT_GAMEPAD_B);
+ updateButton(2, XINPUT_GAMEPAD_X);
+ updateButton(3, XINPUT_GAMEPAD_Y);
+ updateButton(4, XINPUT_GAMEPAD_DPAD_UP);
+ updateButton(5, XINPUT_GAMEPAD_DPAD_DOWN);
+ updateButton(6, XINPUT_GAMEPAD_DPAD_LEFT);
+ updateButton(7, XINPUT_GAMEPAD_DPAD_RIGHT);
+ updateButton(8, XINPUT_GAMEPAD_START);
+ updateButton(9, XINPUT_GAMEPAD_BACK);
+ updateButton(10, XINPUT_GAMEPAD_LEFT_THUMB);
+ updateButton(11, XINPUT_GAMEPAD_RIGHT_THUMB);
+ updateButton(12, XINPUT_GAMEPAD_LEFT_SHOULDER);
+ updateButton(13, XINPUT_GAMEPAD_RIGHT_SHOULDER);
+ }
+}
+
+bool Xbox360Controller::isConnected()
+{
+ // Zeroise the state
+ ZeroMemory(&state, sizeof(XINPUT_STATE));
+
+ // Get the state
+ DWORD Result = XInputGetState(num, &state);
+
+ if(Result == ERROR_SUCCESS)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+bool Xbox360Controller::triggerMoved(int num)
+{
+ if (num == 0)
+ return (state.Gamepad.bRightTrigger &&
+ state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD);
+ return (state.Gamepad.bLeftTrigger &&
+ state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD);
+}
+
+BYTE Xbox360Controller::getTrigger(int num)
+{
+ if (num == 0)
+ return state.Gamepad.bRightTrigger;
+ return state.Gamepad.bLeftTrigger;
+}
+
+bool Xbox360Controller::thumbMoved(int num)
+{
+ switch(num)
+ {
+ case 0:
+ return !(state.Gamepad.sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
+ state.Gamepad.sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
+ case 1:
+ return !(state.Gamepad.sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
+ state.Gamepad.sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
+ case 2:
+ return !(state.Gamepad.sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
+ state.Gamepad.sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
+ case 3:
+ return !(state.Gamepad.sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
+ state.Gamepad.sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
+ }
+
+ return false;
+}
+SHORT Xbox360Controller::getThumb(int num)
+{
+ switch (num)
+ {
+ case 0:
+ return state.Gamepad.sThumbLX;
+ case 1:
+ return state.Gamepad.sThumbLY;
+ case 2:
+ return state.Gamepad.sThumbRX;
+ case 3:
+ return state.Gamepad.sThumbRY;
+ }
+
+ return 0;
+}
+
diff --git a/tools/EventClients/Clients/Xbox360 Controller/Xbox360Controller.h b/tools/EventClients/Clients/Xbox360 Controller/Xbox360Controller.h new file mode 100644 index 0000000000..5a858d5f80 --- /dev/null +++ b/tools/EventClients/Clients/Xbox360 Controller/Xbox360Controller.h @@ -0,0 +1,28 @@ +#pragma once
+#include <windows.h>
+#include <XInput.h> // Defines XBOX controller API
+#pragma comment(lib, "XInput.lib") // Library containing necessary 360
+ // functions
+
+class Xbox360Controller
+{
+private:
+ XINPUT_STATE state;
+ int num;
+ bool button_down[14];
+ bool button_pressed[14];
+ bool button_released[14];
+
+ XINPUT_STATE getState();
+ void updateButton(int num, int button);
+public:
+ Xbox360Controller(int num);
+ void updateState();
+ bool isConnected();
+ bool buttonPressed(int num);
+ bool buttonReleased(int num);
+ bool thumbMoved(int num);
+ SHORT getThumb(int num);
+ bool triggerMoved(int num);
+ BYTE getTrigger(int num);
+};
diff --git a/tools/EventClients/Clients/Xbox360 Controller/Xbox360EventClient.cpp b/tools/EventClients/Clients/Xbox360 Controller/Xbox360EventClient.cpp new file mode 100644 index 0000000000..74b5e6a680 --- /dev/null +++ b/tools/EventClients/Clients/Xbox360 Controller/Xbox360EventClient.cpp @@ -0,0 +1,123 @@ +// Xbox360EventClient.cpp : Defines the entry point for the console application.
+//
+
+#include "stdafx.h"
+#include "Xbox360Controller.h"
+#include "../../lib/c++/xbmcclient.h"
+#pragma comment(lib, "wsock32.lib") // needed for xmbclient.h?
+
+// global variable :(
+// needed for exit event handler
+CXBMCClient *client;
+
+BOOL exitHandler( DWORD ctrlType )
+{
+ // TODO: Send BYE Packet
+ delete client;
+
+ WSACleanup();
+
+ return FALSE;
+}
+
+void checkTrigger(Xbox360Controller &cont, CXBMCClient *client, int num, const char* name)
+{
+ if (cont.triggerMoved(num))
+ {
+ client->SendButton(name, "XG", 0x20, cont.getTrigger(num) * 128);
+ }
+}
+
+void checkThumb(Xbox360Controller &cont, CXBMCClient *client, int num,
+ const char* leftname, const char* rightname)
+{
+ if (cont.thumbMoved(num))
+ {
+ if (cont.getThumb(num) < 0)
+ {
+ client->SendButton(leftname, "XG", 0x20, -cont.getThumb(num));
+ }
+ else
+ {
+ client->SendButton(rightname, "XG", 0x20, cont.getThumb(num));
+ }
+ }
+}
+
+void checkButton(Xbox360Controller &cont, CXBMCClient *client, int num, const char* name)
+{
+ if (cont.buttonPressed(num))
+ {
+ client->SendButton(name, "XG", 0x02);
+ }
+ else if (cont.buttonReleased(num))
+ {
+ client->SendButton(name, "XG", 0x04);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ char *host = "localhost";
+ char *port = "9777";
+
+ Xbox360Controller cont(0);
+
+ // Start Winsock stuff
+ WSADATA wsaData;
+ WSAStartup(MAKEWORD(2, 2), &wsaData);
+
+ if ( argc > 3 )
+ {
+ printf("USAGE: %s [HOST [PORT]]\n\nThe event client connects to the XBMC EventServer at HOST:PORT.\
+ Default value for HOST is localhost, default value for port is 9777.\n", argv[0]);
+ return -1;
+ }
+
+ if ( argc > 1 )
+ {
+ host = argv[1];
+ }
+
+ if ( argc > 2 )
+ {
+ port = argv[2];
+ }
+
+ client = new CXBMCClient(host, atoi(port));
+
+ SetConsoleCtrlHandler( (PHANDLER_ROUTINE) exitHandler, TRUE);
+
+ client->SendHELO("Xbox 360 Controller", 0);
+
+ while(true)
+ {
+ if (cont.isConnected())
+ {
+ cont.updateState();
+ checkButton(cont, client, 0, "a");
+ checkButton(cont, client, 1, "b");
+ checkButton(cont, client, 2, "x");
+ checkButton(cont, client, 3, "y");
+ checkButton(cont, client, 4, "dpadup");
+ checkButton(cont, client, 5, "dpaddown");
+ checkButton(cont, client, 6, "dpadleft");
+ checkButton(cont, client, 7, "dpadright");
+ checkButton(cont, client, 8, "start");
+ checkButton(cont, client, 9, "back");
+ checkButton(cont, client, 10, "leftthumbbutton");
+ checkButton(cont, client, 11, "rightthumbbutton");
+ checkButton(cont, client, 12, "white");
+ checkButton(cont, client, 13, "black");
+ checkTrigger(cont, client, 0, "rightanalogtrigger");
+ checkTrigger(cont, client, 1, "leftanalogtrigger");
+ checkThumb(cont, client, 0, "leftthumbstickleft", "leftthumbstickright");
+ checkThumb(cont, client, 1, "leftthumbstickdown", "leftthumbstickup");
+ checkThumb(cont, client, 2, "rightthumbstickleft", "rightthumbstickright");
+ checkThumb(cont, client, 3, "rightthumbstickdown", "rightthumbstickup");
+ }
+ Sleep(10);
+ }
+
+ return 0;
+}
diff --git a/tools/EventClients/Clients/Xbox360 Controller/Xbox360EventClient.vcproj b/tools/EventClients/Clients/Xbox360 Controller/Xbox360EventClient.vcproj new file mode 100644 index 0000000000..4e6f8c558e --- /dev/null +++ b/tools/EventClients/Clients/Xbox360 Controller/Xbox360EventClient.vcproj @@ -0,0 +1,208 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="Xbox360EventClient"
+ ProjectGUID="{19E7A234-4F29-4828-BBC7-E3564AB57EF0}"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\targetver.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Xbox360Controller.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Xbox360Controller.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Xbox360EventClient.cpp"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/EventClients/Clients/Xbox360 Controller/stdafx.cpp b/tools/EventClients/Clients/Xbox360 Controller/stdafx.cpp new file mode 100644 index 0000000000..81d9f220d5 --- /dev/null +++ b/tools/EventClients/Clients/Xbox360 Controller/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes
+// Xbox360EventClient.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/tools/EventClients/Clients/Xbox360 Controller/stdafx.h b/tools/EventClients/Clients/Xbox360 Controller/stdafx.h new file mode 100644 index 0000000000..47a0d0252b --- /dev/null +++ b/tools/EventClients/Clients/Xbox360 Controller/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/tools/EventClients/Clients/Xbox360 Controller/targetver.h b/tools/EventClients/Clients/Xbox360 Controller/targetver.h new file mode 100644 index 0000000000..a38195a4ef --- /dev/null +++ b/tools/EventClients/Clients/Xbox360 Controller/targetver.h @@ -0,0 +1,13 @@ +#pragma once
+
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
diff --git a/tools/EventClients/Makefile b/tools/EventClients/Makefile new file mode 100644 index 0000000000..5e902f7fbc --- /dev/null +++ b/tools/EventClients/Makefile @@ -0,0 +1,32 @@ +# Default prefix dir +prefix=/usr/local +installdir=$(prefix) +WII_EXTRA_OPTS= + +all: wiimote install + +wiimote: + cd Clients/WiiRemote && \ + g++ CWIID_WiiRemote.cpp -lcwiid -DICON_PATH="\"$(installdir)/share/pixmaps/xbmc/\"" $(WII_EXTRA_OPTS) -o WiiRemote + +j2me-remote: + cd Clients/J2ME\ Client + ant -f build.xml + +install: + mkdir -p $(prefix)/bin + cp -a Clients/WiiRemote/WiiRemote $(prefix)/bin/xbmc-wiiremote + cp -a Clients/J2ME\ Client/j2me_remote.py $(prefix)/bin/xbmc-j2meremote + cp -a Clients/PS3\ BD\ Remote/ps3_remote.py $(prefix)/bin/xbmc-ps3remote + #cp -a Clients/PS3\ Sixaxis\ Controller/ps3d.py $(prefix)/bin/xbmc-ps3d + mkdir -p $(prefix)/lib/python2.5/site-packages/xbmc + echo 'ICON_PATH="$(installdir)/share/pixmaps/xbmc/"' > $(prefix)/lib/python2.5/site-packages/xbmc/defs.py + cp -a lib/python/* $(prefix)/lib/python2.5/site-packages/xbmc/ + cp -a Clients/PS3\ BD\ Remote/ps3_remote.py $(prefix)/lib/python2.5/site-packages/xbmc/ + mkdir -p $(prefix)/include/xbmc + cp -a lib/c++/* $(prefix)/include/xbmc/ + mkdir -p $(prefix)/share/pixmaps/xbmc + cp -a icons/* $(prefix)/share/pixmaps/xbmc/ + +clean: + rm -f Clients/WiiRemote/WiiRemote diff --git a/tools/EventClients/README.txt b/tools/EventClients/README.txt new file mode 100644 index 0000000000..6e1a454e5b --- /dev/null +++ b/tools/EventClients/README.txt @@ -0,0 +1,101 @@ +Event Client Examples and PS3 Sixaxis and Blu-Ray Remote Support +---------------------------------------------------------------- + +This directory contains 6 sample programs that demonstrate XBMC's +event server (which is still in development). The programs are in +Python and C++. XBMC also needs to be running (obviously) so that it +can receive the events. + +- example_button1.py | example_button1.cpp +- example_button2.py | example_button2.cpp +- example_notification.py | example_notification.cpp + +The first 2 show how button / key presses can be sent to XBMC. +The third one shows how to display notifications in XBMC. + +- xbmcclient.py +- xbmcclient.h + +These are the Python module and C++ header that you can use when +writing your own programs. It is not yet complete and likely to change +but is still usable. + +Implementation details can be found in the comments in the sample +programs. + + +PS3 Controller and PS3 Blu-Ray Remote Support +--------------------------------------------- + +There is also initial support for the PS3 controller (sixaxis) and the +PS3 Blu-Ray remote. + +Pairing of the PS3 Blu-Ray Remote +--------------------------------- + +The remote needs to be paired initially with the 'ps3_remote.py' +program in this directory which you can continue using if you do not +want to run 'ps3d.py' as root. The disadvantage of using +'ps3_remote.py' is that pairing is required on every run. Once initial +pairing is done, 'ps3d.py', when run as root, will automatically +detect incoming connections from both the PS3 remote and the Sixaxis +controller. + +Pairing of the PS3 Sixaxis Controller (TODO) +-------------------------------------------- + +The pairing of the PS3 controller is not yet handled automatically. It +can however be done using the program "sixaxis.c" available from: + +http://www.pabr.org/sixlinux/sixlinux.en.html + +Once pairing for eiher or both has been done, run the ps3d.py program +as root after disabling any existing HID servers that might currently +be running. The program requires root prvilieges since it listens on +Bluetooth L2CAP PSMs 17 and 19. + +Using the PS3 Sixaxis Controller +-------------------------------- + +Currently, all that is supported with the Sixaxis controller is to be able +emulate the mouse behavior. Hold down the PS button and wave the controller +around and watch the mouse in XBMC mouse. Tilt it from left to right (along +your Z axis) to control horizontal motion. Tilt it towards and away from you +along (along your X axis) to control vertical mouse movement. + +That's all for now. + +WiiRemote Support +----------------- + +The executable depends on libcwiid and libbluetooth and is compiled using +# g++ WiiRemote.cpp -lcwiid -o WiiRemote +The WiiRemote will emulate mouse by default but can be disabled by running with --disable-mouseemulation +The sensitivity of the mouseemulation can be set using the --deadzone_x or --deadzone_y where the number is +the percentage of the space is considered "dead", higher means more sensative. +Other commands can be listed with --help + +The WiiRemote is mappable with keymap.xml where button id's are the following: +1 = Up +2 = Down +3 = Left +4 = Right +5 = A +6 = B +7 = Minus +8 = Home +9 = Plus +10 = 1 +11 = 2 +The name is by standard WiiRemote but this can be changed with the --joystick-name + +J2ME (Java Phone Application) +----------------------------- + +To use the J2ME client only CLDC 1.0 and MIDP 1.0 is needed. +The client will also need bluetooth and must be able to initialize the connection. +For compilation of the Java Application see Clients/J2ME Client/README but precompiled versions +exists in our forum. + +The Client is mappable in the same manner as PS3 in keymap.xml but with the name J2ME (<joystick name="J2ME">). +The KeyID's generated in terminal when running j2me_remote.py. diff --git a/tools/EventClients/examples/c#/XBMCDemoClient1.cs b/tools/EventClients/examples/c#/XBMCDemoClient1.cs new file mode 100644 index 0000000000..849cc36c07 --- /dev/null +++ b/tools/EventClients/examples/c#/XBMCDemoClient1.cs @@ -0,0 +1,35 @@ +using System;
+using System.Collections.Generic;
+using System.Windows.Forms; +using XBMC;
+
+namespace XBMCEventClientDemo
+{
+ static class Program
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ { + EventClient eventClient = new EventClient(); + eventClient.Connect("127.0.0.1", 9777);
+ eventClient.SendHelo("XBMC Client Demo", IconType.ICON_PNG, "icon.png");
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendNotification("XBMC Client Demo", "Notification Message", IconType.ICON_PNG, "/usr/share/xbmc/media/icon.png");
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendButton("dpadup", "XG", ButtonFlagsType.BTN_DOWN | ButtonFlagsType.BTN_NO_REPEAT, 0);
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendPing();
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendMouse(32768, 32768);
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendLog(LogTypeEnum.LOGERROR, "Example error log message from XBMC Client Demo");
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendAction("Mute");
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendBye();
+ }
+ }
+} diff --git a/tools/EventClients/examples/c++/example_button1.cpp b/tools/EventClients/examples/c++/example_button1.cpp new file mode 100644 index 0000000000..a980e3da24 --- /dev/null +++ b/tools/EventClients/examples/c++/example_button1.cpp @@ -0,0 +1,38 @@ +#include "../../lib/c++/xbmcclient.h" +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> + +int main(int argc, char **argv) +{ + /* connect to localhost, port 9777 using a UDP socket + this only needs to be done once. + by default this is where XBMC will be listening for incoming + connections. */ + CAddress my_addr; // Address => localhost on 9777 + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + printf("Error creating socket\n"); + return -1; + } + + my_addr.Bind(sockfd); + + CPacketHELO HeloPackage("Example Remote", ICON_PNG, "../../icons/bluetooth.png"); + HeloPackage.Send(sockfd, my_addr); + + sleep(5); + // press 'S' + CPacketBUTTON btn1('S', true); + btn1.Send(sockfd, my_addr); + + sleep(2); + // press the enter key (13 = enter) + CPacketBUTTON btn2(13, true); + btn2.Send(sockfd, my_addr); + + // BYE is not required since XBMC would have shut down + CPacketBYE bye; // CPacketPing if you want to ping + bye.Send(sockfd, my_addr); +} diff --git a/tools/EventClients/examples/c++/example_button2.cpp b/tools/EventClients/examples/c++/example_button2.cpp new file mode 100644 index 0000000000..852e49f9a2 --- /dev/null +++ b/tools/EventClients/examples/c++/example_button2.cpp @@ -0,0 +1,48 @@ +#include "../../lib/c++/xbmcclient.h" +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> + +int main(int argc, char **argv) +{ + /* connect to localhost, port 9777 using a UDP socket + this only needs to be done once. + by default this is where XBMC will be listening for incoming + connections. */ + CAddress my_addr; // Address => localhost on 9777 + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + printf("Error creating socket\n"); + return -1; + } + + my_addr.Bind(sockfd); + + CPacketHELO HeloPackage("Example Remote", ICON_PNG, "../../icons/bluetooth.png"); + HeloPackage.Send(sockfd, my_addr); + + sleep(5); + // Note that we have foo(BUTTON, DEVICEMAP); + CPacketBUTTON btn1("dpadup", "XG"); + btn1.Send(sockfd, my_addr); + + sleep(5); + + CPacketBUTTON btn2(0x28); + btn2.Send(sockfd, my_addr); + + sleep(5); + + CPacketBUTTON btn3("right", "KB"); + btn3.Send(sockfd, my_addr); + + sleep(5); + // Release button + CPacketBUTTON btn4; + btn4.Send(sockfd, my_addr); + + // BYE is not required since XBMC would have shut down + CPacketBYE bye; // CPacketPing if you want to ping + bye.Send(sockfd, my_addr); +} diff --git a/tools/EventClients/examples/c++/example_log.cpp b/tools/EventClients/examples/c++/example_log.cpp new file mode 100644 index 0000000000..6194ed9c51 --- /dev/null +++ b/tools/EventClients/examples/c++/example_log.cpp @@ -0,0 +1,34 @@ +#include "../../lib/c++/xbmcclient.h" +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> + +int main(int argc, char **argv) +{ + /* connect to localhost, port 9777 using a UDP socket + this only needs to be done once. + by default this is where XBMC will be listening for incoming + connections. */ + + CAddress my_addr; // Address => localhost on 9777 + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + printf("Error creating socket\n"); + return -1; + } + + my_addr.Bind(sockfd); + //Normally this is already done by the client + CPacketHELO HeloPackage("LOG Test", ICON_NONE); + HeloPackage.Send(sockfd, my_addr); + + sleep(5); + //This works as XBMC internal CLog::LOG(LOGTYPE, STRING); + CPacketLOG packet(LOGERROR, "The Log Message"); + packet.Send(sockfd, my_addr); + + // BYE is not required since XBMC would have shut down + CPacketBYE bye; // CPacketPing if you want to ping + bye.Send(sockfd, my_addr); +} diff --git a/tools/EventClients/examples/c++/example_mouse.cpp b/tools/EventClients/examples/c++/example_mouse.cpp new file mode 100644 index 0000000000..23f40d3de8 --- /dev/null +++ b/tools/EventClients/examples/c++/example_mouse.cpp @@ -0,0 +1,36 @@ +#include "../../lib/c++/xbmcclient.h" +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> + +int main(int argc, char **argv) +{ + /* connect to localhost, port 9777 using a UDP socket + this only needs to be done once. + by default this is where XBMC will be listening for incoming + connections. */ + CAddress my_addr; // Address => localhost on 9777 + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + printf("Error creating socket\n"); + return -1; + } + + my_addr.Bind(sockfd); + + CPacketHELO HeloPackage("Example Mouse", ICON_PNG, "../../icons/mouse.png"); + HeloPackage.Send(sockfd, my_addr); + + sleep(5); + + for(int i = 0; i < 65536; i++) + { + CPacketMOUSE mouse(i,i); + mouse.Send(sockfd, my_addr); + } + + // BYE is not required since XBMC would have shut down + CPacketBYE bye; // CPacketPing if you want to ping + bye.Send(sockfd, my_addr); +} diff --git a/tools/EventClients/examples/c++/example_notification.cpp b/tools/EventClients/examples/c++/example_notification.cpp new file mode 100644 index 0000000000..dc51075b85 --- /dev/null +++ b/tools/EventClients/examples/c++/example_notification.cpp @@ -0,0 +1,37 @@ +#include "../../lib/c++/xbmcclient.h" +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> + +int main(int argc, char **argv) +{ + /* connect to localhost, port 9777 using a UDP socket + this only needs to be done once. + by default this is where XBMC will be listening for incoming + connections. */ + + CAddress my_addr; // Address => localhost on 9777 + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + printf("Error creating socket\n"); + return -1; + } + + my_addr.Bind(sockfd); + + CPacketHELO HeloPackage("Email Notifier", ICON_NONE); + HeloPackage.Send(sockfd, my_addr); + + sleep(5); + + CPacketNOTIFICATION packet("New Mail!", // caption + "RE: Check this out", // message + ICON_PNG, // optional icon type + "../../icons/mail.png"); // icon file (local) + packet.Send(sockfd, my_addr); + + // BYE is not required since XBMC would have shut down + CPacketBYE bye; // CPacketPing if you want to ping + bye.Send(sockfd, my_addr); +} diff --git a/tools/EventClients/examples/java/XBMCDemoClient1.java b/tools/EventClients/examples/java/XBMCDemoClient1.java new file mode 100644 index 0000000000..0be3865cbd --- /dev/null +++ b/tools/EventClients/examples/java/XBMCDemoClient1.java @@ -0,0 +1,52 @@ +package org.xbmc.eventclient.demo; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; + +import org.xbmc.eventclient.XBMCClient; + +/** + * Simple Demo EventClient + * @author Stefan Agner + * + */ +public class XBMCDemoClient1 { + + /** + * Simple Demo EventClient + * @param args + */ + public static void main(String[] args) throws IOException, InterruptedException { + InetAddress host = Inet4Address.getByAddress(new byte[] { (byte)192, (byte)168, 0, 20 } ); + + Thread.sleep(20000); + XBMCClient oXBMCClient = new XBMCClient(host, 9777, "My Client", "/usr/share/xbmc/media/icon.png"); + + Thread.sleep(7000); + + oXBMCClient.sendNotification("My Title", "My Message"); + + + Thread.sleep(7000); + + oXBMCClient.sendButton("KB", "escape", false, true, false, (short)0 , (byte)0); + + + Thread.sleep(7000); + oXBMCClient.sendButton("KB", "escape", true, true, false, (short)0 , (byte)0); + oXBMCClient.sendNotification("My Title", "Escape sent"); + + Thread.sleep(1000); + + oXBMCClient.sendButton("KB", "escape", true, false, false, (short)0 , (byte)0); + oXBMCClient.sendNotification("My Title", "Escape released"); + + Thread.sleep(7000); + oXBMCClient.sendLog((byte)0, "My Client disconnects...."); + oXBMCClient.sendNotification("My Title", "Client will disconnect"); + oXBMCClient.stopClient(); + + } + +} diff --git a/tools/EventClients/examples/python/example_action.py b/tools/EventClients/examples/python/example_action.py new file mode 100755 index 0000000000..d5ab9cf61c --- /dev/null +++ b/tools/EventClients/examples/python/example_action.py @@ -0,0 +1,40 @@ +#!/usr/bin/python + +# This is a simple example showing how you can send a key press event +# to XBMC using the XBMCClient class + +import sys +sys.path.append("../../lib/python") + +import time +from xbmcclient import XBMCClient,ACTION_EXECBUILTIN,ACTION_BUTTON + +def main(): + + host = "localhost" + port = 9777 + + # Create an XBMCClient object and connect + xbmc = XBMCClient("Example Remote", "../../icons/bluetooth.png") + xbmc.connect() + + # send a up key press using the xbox gamepad map "XG" and button + # name "dpadup" ( see PacketBUTTON doc for more details) + try: + xbmc.send_action(sys.argv[2], ACTION_BUTTON) + except: + try: + xbmc.send_action(sys.argv[1], ACTION_EXECBUILTIN) + except Exception, e: + print str(e) + xbmc.send_action("XBMC.ActivateWindow(ShutdownMenu)") + + + # ok we're done, close the connection + # Note that closing the connection clears any repeat key that is + # active. So in this example, the actual release button event above + # need not have been sent. + xbmc.close() + +if __name__=="__main__": + main() diff --git a/tools/EventClients/examples/python/example_button1.py b/tools/EventClients/examples/python/example_button1.py new file mode 100755 index 0000000000..7b208252cb --- /dev/null +++ b/tools/EventClients/examples/python/example_button1.py @@ -0,0 +1,79 @@ +#!/usr/bin/python + +# This is a simple example showing how you can send 2 button events +# to XBMC in a queued fashion to shut it down. + +# Queued button events are not repeatable. + +# The basic idea is to create single packets and shoot them to XBMC +# The provided library implements some of the support commands and +# takes care of creating the actual packet. Using it is as simple +# as creating an object with the required constructor arguments and +# sending it through a socket. + +# Currently, only keyboard keys are supported so the key codes used +# below are the same key codes used in guilib/common/SDLKeyboard.cpp + +# In effect, anything that can be done with the keyboard can be done +# using the event client. + +# import the XBMC client library +# NOTE: The library is not complete yet but is usable at this stage. + +import sys +sys.path.append("../../lib/python") + +from xbmcclient import * +from socket import * + +def main(): + import time + import sys + + # connect to localhost, port 9777 using a UDP socket + # this only needs to be done once. + # by default this is where XBMC will be listening for incoming + # connections. + host = "localhost" + port = 9777 + addr = (host, port) + sock = socket(AF_INET,SOCK_DGRAM) + + # First packet must be HELO (no it's not a typo) and can contain an icon + # 'icon_type' can be one of ICON_NONE, ICON_PNG, ICON_JPG or ICON_GIF + packet = PacketHELO(devicename="Example Remote", + icon_type=ICON_PNG, + icon_file="../../icons/bluetooth.png") + packet.send(sock, addr) + + # IMPORTANT: After a HELO packet is sent, the client needs to "ping" XBMC + # at least once every 60 seconds or else the client will time out. + # Every valid packet sent to XBMC acts as a ping, however if no valid + # packets NEED to be sent (eg. the user hasn't pressed a key in 50 seconds) + # then you can use the PacketPING class to send a ping packet (which is + # basically just an emppty packet). See below. + + # Once a client times out, it will need to reissue the HELO packet. + # Currently, since this is a unidirectional protocol, there is no way + # for the client to know if it has timed out. + + # wait for notification window to close (in XBMC) + time.sleep(5) + + # press 'S' + packet = PacketBUTTON(code='S', queue=1) + packet.send(sock, addr) + + # wait for a few seconds + time.sleep(2) + + # press the enter key (13 = enter) + packet = PacketBUTTON(code=13, queue=1) + packet.send(sock, addr) + + # BYE is not required since XBMC would have shut down + packet = PacketBYE() # PacketPING if you want to ping + packet.send(sock, addr) + +if __name__=="__main__": + main() diff --git a/tools/EventClients/examples/python/example_button2.py b/tools/EventClients/examples/python/example_button2.py new file mode 100755 index 0000000000..b420bd84b8 --- /dev/null +++ b/tools/EventClients/examples/python/example_button2.py @@ -0,0 +1,73 @@ +#!/usr/bin/python + +# This is a simple example showing how you can send a key press event +# to XBMC in a non-queued fashion to achieve a button pressed down +# event i.e. a key press that repeats. + +# The repeat interval is currently hard coded in XBMC but that might +# change in the future. + +# NOTE: Read the comments in 'example_button1.py' for a more detailed +# explanation. + +import sys +sys.path.append("../../lib/python") + +from xbmcclient import * +from socket import * + +def main(): + import time + import sys + + host = "localhost" + port = 9777 + addr = (host, port) + + sock = socket(AF_INET,SOCK_DGRAM) + + # First packet must be HELO and can contain an icon + packet = PacketHELO("Example Remote", ICON_PNG, + "../../icons/bluetooth.png") + packet.send(sock, addr) + + # wait for notification window to close (in XBMC) + time.sleep(5) + + # send a up key press using the xbox gamepad map "XG" and button + # name "dpadup" ( see PacketBUTTON doc for more details) + packet = PacketBUTTON(map_name="XG", button_name="dpadup") + packet.send(sock, addr) + + # wait for a few seconds to see its effect + time.sleep(5) + + # send a down key press using the raw keyboard code + packet = PacketBUTTON(code=0x28) + packet.send(sock, addr) + + # wait for a few seconds to see its effect + time.sleep(5) + + # send a right key press using the keyboard map "KB" and button + # name "right" + packet = PacketBUTTON(map_name="KB", button_name="right") + packet.send(sock, addr) + + # wait for a few seconds to see its effect + time.sleep(5) + + # that's enough, release the button. During release, button code + # doesn't matter. + packet = PacketBUTTON(code=0x28, down=0) + packet.send(sock, addr) + + # ok we're done, close the connection + # Note that closing the connection clears any repeat key that is + # active. So in this example, the actual release button event above + # need not have been sent. + packet = PacketBYE() + packet.send(sock, addr) + +if __name__=="__main__": + main() diff --git a/tools/EventClients/examples/python/example_mouse.py b/tools/EventClients/examples/python/example_mouse.py new file mode 100755 index 0000000000..10d7f61ba7 --- /dev/null +++ b/tools/EventClients/examples/python/example_mouse.py @@ -0,0 +1,45 @@ +#!/usr/bin/python + +# This is a simple example showing how you can send mouse movement +# events to XBMC. + +# NOTE: Read the comments in 'example_button1.py' for a more detailed +# explanation. + +import sys +sys.path.append("../../lib/python") + +from xbmcclient import * +from socket import * + +def main(): + import time + import sys + + host = "localhost" + port = 9777 + addr = (host, port) + + sock = socket(AF_INET,SOCK_DGRAM) + + # First packet must be HELO and can contain an icon + packet = PacketHELO("Example Mouse", ICON_PNG, + "../../icons/mouse.png") + packet.send(sock, addr) + + # wait for notification window to close (in XBMC) + time.sleep(2) + + # send mouse events to take cursor from top left to bottom right of the screen + # here 0 to 65535 will map to XBMC's screen width and height. + # Specifying absolute mouse coordinates is unsupported currently. + for i in range(0, 65535, 2): + packet = PacketMOUSE(i,i) + packet.send(sock, addr) + + # ok we're done, close the connection + packet = PacketBYE() + packet.send(sock, addr) + +if __name__=="__main__": + main() diff --git a/tools/EventClients/examples/python/example_notification.py b/tools/EventClients/examples/python/example_notification.py new file mode 100755 index 0000000000..81bbadccd2 --- /dev/null +++ b/tools/EventClients/examples/python/example_notification.py @@ -0,0 +1,38 @@ +#!/usr/bin/python + +# This is a simple example showing how you can show a notification +# window with a custom icon inside XBMC. It could be used by mail +# monitoring apps, calendar apps, etc. + +import sys +sys.path.append("../../lib/python") + +from xbmcclient import * +from socket import * + +def main(): + import time + import sys + + host = "localhost" + port = 9777 + addr = (host, port) + sock = socket(AF_INET,SOCK_DGRAM) + + packet = PacketHELO("Email Notifier", ICON_NONE) + packet.send(sock, addr) + + # wait for 5 seconds + time.sleep (5) + + packet = PacketNOTIFICATION("New Mail!", # caption + "RE: Check this out", # message + ICON_PNG, # optional icon type + "../../icons/mail.png") # icon file (local) + packet.send(sock, addr) + + packet = PacketBYE() + packet.send(sock, addr) + +if __name__=="__main__": + main() diff --git a/tools/EventClients/examples/python/example_simple.py b/tools/EventClients/examples/python/example_simple.py new file mode 100755 index 0000000000..6218131e13 --- /dev/null +++ b/tools/EventClients/examples/python/example_simple.py @@ -0,0 +1,48 @@ +#!/usr/bin/python + +# This is a simple example showing how you can send a key press event +# to XBMC using the XBMCClient class + +import sys +sys.path.append("../../lib/python") + +import time +from xbmcclient import XBMCClient + +def main(): + + host = "localhost" + port = 9777 + + # Create an XBMCClient object and connect + xbmc = XBMCClient("Example Remote", "../../icons/bluetooth.png") + xbmc.connect() + + # wait for notification window to close (in XBMC) (optional) + time.sleep(5) + + # send a up key press using the xbox gamepad map "XG" and button + # name "dpadup" ( see PacketBUTTON doc for more details) + xbmc.send_button(map="XG", button="dpadup") + + # wait for a few seconds to see its effect + time.sleep(5) + + # send a right key press using the keyboard map "KB" and button + # name "right" + xbmc.send_keyboard_button("right") + + # wait for a few seconds to see its effect + time.sleep(5) + + # that's enough, release the button. + xbmc.release_button() + + # ok we're done, close the connection + # Note that closing the connection clears any repeat key that is + # active. So in this example, the actual release button event above + # need not have been sent. + xbmc.close() + +if __name__=="__main__": + main() diff --git a/tools/EventClients/icons/bluetooth.png b/tools/EventClients/icons/bluetooth.png Binary files differnew file mode 100644 index 0000000000..5ede31fd45 --- /dev/null +++ b/tools/EventClients/icons/bluetooth.png diff --git a/tools/EventClients/icons/mail.png b/tools/EventClients/icons/mail.png Binary files differnew file mode 100644 index 0000000000..7c68b2e854 --- /dev/null +++ b/tools/EventClients/icons/mail.png diff --git a/tools/EventClients/icons/mouse.png b/tools/EventClients/icons/mouse.png Binary files differnew file mode 100644 index 0000000000..c0e165760c --- /dev/null +++ b/tools/EventClients/icons/mouse.png diff --git a/tools/EventClients/icons/phone.png b/tools/EventClients/icons/phone.png Binary files differnew file mode 100644 index 0000000000..3db1682eeb --- /dev/null +++ b/tools/EventClients/icons/phone.png diff --git a/tools/EventClients/lib/c#/EventClient.cs b/tools/EventClients/lib/c#/EventClient.cs new file mode 100644 index 0000000000..f904dcaa93 --- /dev/null +++ b/tools/EventClients/lib/c#/EventClient.cs @@ -0,0 +1,529 @@ +using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+
+namespace XBMC
+{
+
+ public enum IconType
+ {
+ ICON_NONE = 0x00,
+ ICON_JPEG = 0x01,
+ ICON_PNG = 0x02,
+ ICON_GIF = 0x03
+ }
+
+ public enum ButtonFlagsType
+ {
+ BTN_USE_NAME = 0x01,
+ BTN_DOWN = 0x02,
+ BTN_UP = 0x04,
+ BTN_USE_AMOUNT = 0x08,
+ BTN_QUEUE = 0x10,
+ BTN_NO_REPEAT = 0x20,
+ BTN_VKEY = 0x40,
+ BTN_AXIS = 0x80
+ }
+
+ public enum MouseFlagsType
+ {
+ MS_ABSOLUTE = 0x01
+ }
+
+ public enum LogTypeEnum
+ {
+ LOGDEBUG = 0,
+ LOGINFO = 1,
+ LOGNOTICE = 2,
+ LOGWARNING = 3,
+ LOGERROR = 4,
+ LOGSEVERE = 5,
+ LOGFATAL = 6,
+ LOGNONE = 7
+ }
+
+ public enum ActionType
+ {
+ ACTION_EXECBUILTIN = 0x01,
+ ACTION_BUTTON = 0x02
+ }
+
+ public class EventClient
+ {
+
+ /************************************************************************/
+ /* Written by Peter Tribe aka EqUiNox (TeamBlackbolt) */
+ /* Based upon XBMC's xbmcclient.cpp class */
+ /************************************************************************/
+
+ private enum PacketType
+ {
+ PT_HELO = 0x01,
+ PT_BYE = 0x02,
+ PT_BUTTON = 0x03,
+ PT_MOUSE = 0x04,
+ PT_PING = 0x05,
+ PT_BROADCAST = 0x06, //Currently not implemented
+ PT_NOTIFICATION = 0x07,
+ PT_BLOB = 0x08,
+ PT_LOG = 0x09,
+ PT_ACTION = 0x0A,
+ PT_DEBUG = 0xFF //Currently not implemented
+ }
+
+ private const int STD_PORT = 9777;
+ private const int MAX_PACKET_SIZE = 1024;
+ private const int HEADER_SIZE = 32;
+ private const int MAX_PAYLOAD_SIZE = MAX_PACKET_SIZE - HEADER_SIZE;
+ private const byte MAJOR_VERSION = 2;
+ private const byte MINOR_VERSION = 0;
+
+ private uint uniqueToken;
+ private Socket socket;
+
+ public bool Connect(string Address)
+ {
+ return Connect(Address, STD_PORT, (uint)System.DateTime.Now.TimeOfDay.Milliseconds);
+ }
+
+ public bool Connect(string Address, int Port)
+ {
+ return Connect(Address, Port, (uint)System.DateTime.Now.TimeOfDay.Milliseconds);
+ }
+
+
+ public bool Connect(string Address, int Port, uint UID)
+ {
+ try
+ {
+ if (socket != null) Disconnect();
+ uniqueToken = UID;
+ socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.Connect(Dns.GetHostByName(Address).AddressList[0].ToString(), Port);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ public bool Connected
+ {
+ get
+ {
+ if (socket == null) return false;
+ return socket.Connected;
+ }
+ }
+
+ public void Disconnect()
+ {
+ try
+ {
+ if (socket != null)
+ {
+ socket.Shutdown(SocketShutdown.Both);
+ socket.Close();
+ socket = null;
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ private byte[] Header(PacketType PacketType, int NumberOfPackets, int CurrentPacket, int PayloadSize)
+ {
+
+ byte[] header = new byte[HEADER_SIZE];
+
+ header[0] = (byte)'X';
+ header[1] = (byte)'B';
+ header[2] = (byte)'M';
+ header[3] = (byte)'C';
+
+ header[4] = MAJOR_VERSION;
+ header[5] = MINOR_VERSION;
+
+ if (CurrentPacket == 1)
+ {
+ header[6] = (byte)(((ushort)PacketType & 0xff00) >> 8);
+ header[7] = (byte)((ushort)PacketType & 0x00ff);
+ }
+ else
+ {
+ header[6] = (byte)(((ushort)PacketType.PT_BLOB & 0xff00) >> 8);
+ header[7] = (byte)((ushort)PacketType.PT_BLOB & 0x00ff);
+ }
+
+ header[8] = (byte)((CurrentPacket & 0xff000000) >> 24);
+ header[9] = (byte)((CurrentPacket & 0x00ff0000) >> 16);
+ header[10] = (byte)((CurrentPacket & 0x0000ff00) >> 8);
+ header[11] = (byte)(CurrentPacket & 0x000000ff);
+
+ header[12] = (byte)((NumberOfPackets & 0xff000000) >> 24);
+ header[13] = (byte)((NumberOfPackets & 0x00ff0000) >> 16);
+ header[14] = (byte)((NumberOfPackets & 0x0000ff00) >> 8);
+ header[15] = (byte)(NumberOfPackets & 0x000000ff);
+
+ header[16] = (byte)((PayloadSize & 0xff00) >> 8);
+ header[17] = (byte)(PayloadSize & 0x00ff);
+
+ header[18] = (byte)((uniqueToken & 0xff000000) >> 24);
+ header[19] = (byte)((uniqueToken & 0x00ff0000) >> 16);
+ header[20] = (byte)((uniqueToken & 0x0000ff00) >> 8);
+ header[21] = (byte)(uniqueToken & 0x000000ff);
+
+ return header;
+
+ }
+
+ private bool Send(PacketType PacketType, byte[] Payload)
+ {
+ try
+ {
+
+ bool successfull = true;
+ int packetCount = (Payload.Length / MAX_PAYLOAD_SIZE) + 1;
+ int bytesToSend = 0;
+ int bytesSent = 0;
+ int bytesLeft = Payload.Length;
+
+ for (int Package = 1; Package <= packetCount; Package++)
+ {
+
+ if (bytesLeft > MAX_PAYLOAD_SIZE)
+ {
+ bytesToSend = MAX_PAYLOAD_SIZE;
+ bytesLeft -= bytesToSend;
+ }
+ else
+ {
+ bytesToSend = bytesLeft;
+ bytesLeft = 0;
+ }
+
+ byte[] header = Header(PacketType, packetCount, Package, bytesToSend);
+ byte[] packet = new byte[MAX_PACKET_SIZE];
+
+ Array.Copy(header, 0, packet, 0, header.Length);
+ Array.Copy(Payload, bytesSent, packet, header.Length, bytesToSend);
+
+ int sendSize = socket.Send(packet, header.Length + bytesToSend, SocketFlags.None);
+
+ if (sendSize != (header.Length + bytesToSend))
+ {
+ successfull = false;
+ break;
+ }
+
+ bytesSent += bytesToSend;
+
+ }
+
+ return successfull;
+
+ }
+ catch
+ {
+
+ return false;
+
+ }
+
+ }
+
+ /************************************************************************/
+ /* SendHelo - Payload format */
+ /* %s - device name (max 128 chars) */
+ /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */
+ /* %s - my port ( 0=>not listening ) */
+ /* %d - reserved1 ( 0 ) */
+ /* %d - reserved2 ( 0 ) */
+ /* XX - imagedata ( can span multiple packets ) */
+ /************************************************************************/
+ public bool SendHelo(string DevName, IconType IconType, string IconFile)
+ {
+
+ byte[] icon = new byte[0];
+ if (IconType != IconType.ICON_NONE)
+ icon = File.ReadAllBytes(IconFile);
+
+ byte[] payload = new byte[DevName.Length + 12 + icon.Length];
+
+ int offset = 0;
+
+ for (int i = 0; i < DevName.Length; i++)
+ payload[offset++] = (byte)DevName[i];
+ payload[offset++] = (byte)'\0';
+
+ payload[offset++] = (byte)IconType;
+
+ payload[offset++] = (byte)0;
+ payload[offset++] = (byte)'\0';
+
+ for (int i = 0; i < 8; i++)
+ payload[offset++] = (byte)0;
+
+ Array.Copy(icon, 0, payload, DevName.Length + 12, icon.Length);
+
+ return Send(PacketType.PT_HELO, payload);
+
+ }
+
+ public bool SendHelo(string DevName)
+ {
+ return SendHelo(DevName, IconType.ICON_NONE, "");
+ }
+
+ /************************************************************************/
+ /* SendNotification - Payload format */
+ /* %s - caption */
+ /* %s - message */
+ /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */
+ /* %d - reserved ( 0 ) */
+ /* XX - imagedata ( can span multiple packets ) */
+ /************************************************************************/
+ public bool SendNotification(string Caption, string Message, IconType IconType, string IconFile)
+ {
+
+ byte[] icon = new byte[0];
+ if (IconType != IconType.ICON_NONE)
+ icon = File.ReadAllBytes(IconFile);
+
+ byte[] payload = new byte[Caption.Length + Message.Length + 7 + icon.Length];
+
+ int offset = 0;
+
+ for (int i = 0; i < Caption.Length; i++)
+ payload[offset++] = (byte)Caption[i];
+ payload[offset++] = (byte)'\0';
+
+ for (int i = 0; i < Message.Length; i++)
+ payload[offset++] = (byte)Message[i];
+ payload[offset++] = (byte)'\0';
+
+ payload[offset++] = (byte)IconType;
+
+ for (int i = 0; i < 4; i++)
+ payload[offset++] = (byte)0;
+
+ Array.Copy(icon, 0, payload, Caption.Length + Message.Length + 7, icon.Length);
+
+ return Send(PacketType.PT_NOTIFICATION, payload);
+
+ }
+
+ public bool SendNotification(string Caption, string Message)
+ {
+ return SendNotification(Caption, Message, IconType.ICON_NONE, "");
+ }
+
+ /************************************************************************/
+ /* SendButton - Payload format */
+ /* %i - button code */
+ /* %i - flags 0x01 => use button map/name instead of code */
+ /* 0x02 => btn down */
+ /* 0x04 => btn up */
+ /* 0x08 => use amount */
+ /* 0x10 => queue event */
+ /* 0x20 => do not repeat */
+ /* 0x40 => virtual key */
+ /* 0x80 => axis key */
+ /* %i - amount ( 0 => 65k maps to -1 => 1 ) */
+ /* %s - device map (case sensitive and required if flags & 0x01) */
+ /* "KB" - Standard keyboard map */
+ /* "XG" - Xbox Gamepad */
+ /* "R1" - Xbox Remote */
+ /* "R2" - Xbox Universal Remote */
+ /* "LI:devicename" - valid LIRC device map where 'devicename' */
+ /* is the actual name of the LIRC device */
+ /* "JS<num>:joyname" - valid Joystick device map where */
+ /* 'joyname' is the name specified in */
+ /* the keymap. JS only supports button code */
+ /* and not button name currently (!0x01). */
+ /* %s - button name (required if flags & 0x01) */
+ /************************************************************************/
+ private bool SendButton(string Button, ushort ButtonCode, string DeviceMap, ButtonFlagsType Flags, short Amount)
+ {
+
+ if (Button.Length != 0)
+ {
+ if ((Flags & ButtonFlagsType.BTN_USE_NAME) == 0)
+ Flags |= ButtonFlagsType.BTN_USE_NAME;
+ ButtonCode = 0;
+ }
+ else
+ Button = "";
+
+ if (Amount > 0)
+ {
+ if ((Flags & ButtonFlagsType.BTN_USE_AMOUNT) == 0)
+ Flags |= ButtonFlagsType.BTN_USE_AMOUNT;
+ }
+
+ if ((Flags & ButtonFlagsType.BTN_DOWN) == 0 || (Flags & ButtonFlagsType.BTN_UP) == 0)
+ Flags |= ButtonFlagsType.BTN_DOWN;
+
+ byte[] payload = new byte[Button.Length + DeviceMap.Length + 8];
+
+ int offset = 0;
+
+ payload[offset++] = (byte)((ButtonCode & 0xff00) >> 8);
+ payload[offset++] = (byte)(ButtonCode & 0x00ff);
+
+ payload[offset++] = (byte)(((ushort)Flags & 0xff00) >> 8);
+ payload[offset++] = (byte)((ushort)Flags & 0x00ff);
+
+ payload[offset++] = (byte)((Amount & 0xff00) >> 8);
+ payload[offset++] = (byte)(Amount & 0x00ff);
+
+ for (int i = 0; i < DeviceMap.Length; i++)
+ payload[offset++] = (byte)DeviceMap[i];
+ payload[offset++] = (byte)'\0';
+
+ for (int i = 0; i < Button.Length; i++)
+ payload[offset++] = (byte)Button[i];
+ payload[offset++] = (byte)'\0';
+
+ return Send(PacketType.PT_BUTTON, payload);
+
+ }
+
+ public bool SendButton(string Button, string DeviceMap, ButtonFlagsType Flags, short Amount)
+ {
+ return SendButton(Button, 0, DeviceMap, Flags, Amount);
+ }
+
+ public bool SendButton(string Button, string DeviceMap, ButtonFlagsType Flags)
+ {
+ return SendButton(Button, 0, DeviceMap, Flags, 0);
+ }
+
+ public bool SendButton(ushort ButtonCode, string DeviceMap, ButtonFlagsType Flags, short Amount)
+ {
+ return SendButton("", ButtonCode, DeviceMap, Flags, Amount);
+ }
+
+ public bool SendButton(ushort ButtonCode, string DeviceMap, ButtonFlagsType Flags)
+ {
+ return SendButton("", ButtonCode, DeviceMap, Flags, 0);
+ }
+
+ public bool SendButton(ushort ButtonCode, ButtonFlagsType Flags, short Amount)
+ {
+ return SendButton("", ButtonCode, "", Flags, Amount);
+ }
+
+ public bool SendButton(ushort ButtonCode, ButtonFlagsType Flags)
+ {
+ return SendButton("", ButtonCode, "", Flags, 0);
+ }
+
+ public bool SendButton()
+ {
+ return SendButton("", 0, "", ButtonFlagsType.BTN_UP, 0);
+ }
+
+ /************************************************************************/
+ /* SendPing - No payload */
+ /************************************************************************/
+ public bool SendPing()
+ {
+ byte[] payload = new byte[0];
+ return Send(PacketType.PT_PING, payload);
+ }
+
+ /************************************************************************/
+ /* SendBye - No payload */
+ /************************************************************************/
+ public bool SendBye()
+ {
+ byte[] payload = new byte[0];
+ return Send(PacketType.PT_BYE, payload);
+ }
+
+ /************************************************************************/
+ /* SendMouse - Payload format */
+ /* %c - flags */
+ /* - 0x01 absolute position */
+ /* %i - mousex (0-65535 => maps to screen width) */
+ /* %i - mousey (0-65535 => maps to screen height) */
+ /************************************************************************/
+ public bool SendMouse(ushort X, ushort Y, MouseFlagsType Flags)
+ {
+
+ byte[] payload = new byte[9];
+
+ int offset = 0;
+
+ payload[offset++] = (byte)Flags;
+
+ payload[offset++] = (byte)((X & 0xff00) >> 8);
+ payload[offset++] = (byte)(X & 0x00ff);
+
+ payload[offset++] = (byte)((Y & 0xff00) >> 8);
+ payload[offset++] = (byte)(Y & 0x00ff);
+
+ return Send(PacketType.PT_MOUSE, payload);
+
+ }
+
+ public bool SendMouse(ushort X, ushort Y)
+ {
+ return SendMouse(X, Y, MouseFlagsType.MS_ABSOLUTE);
+ }
+
+ /************************************************************************/
+ /* SendLog - Payload format */
+ /* %c - log type */
+ /* %s - message */
+ /************************************************************************/
+ public bool SendLog(LogTypeEnum LogLevel, string Message)
+ {
+
+ byte[] payload = new byte[Message.Length + 2];
+
+ int offset = 0;
+
+ payload[offset++] = (byte)LogLevel;
+
+ for (int i = 0; i < Message.Length; i++)
+ payload[offset++] = (byte)Message[i];
+ payload[offset++] = (byte)'\0';
+
+ return Send(PacketType.PT_LOG, payload);
+
+ }
+
+ /************************************************************************/
+ /* SendAction - Payload format */
+ /* %c - action type */
+ /* %s - action message */
+ /************************************************************************/
+ public bool SendAction(ActionType Action, string Message)
+ {
+
+ byte[] payload = new byte[Message.Length + 2];
+
+ int offset = 0;
+
+ payload[offset++] = (byte)Action;
+
+ for (int i = 0; i < Message.Length; i++)
+ payload[offset++] = (byte)Message[i];
+ payload[offset++] = (byte)'\0';
+
+ return Send(PacketType.PT_ACTION, payload);
+
+ }
+
+ public bool SendAction(string Message)
+ {
+ return SendAction(ActionType.ACTION_EXECBUILTIN, Message);
+ }
+
+ }
+}
diff --git a/tools/EventClients/lib/c++/xbmcclient.h b/tools/EventClients/lib/c++/xbmcclient.h new file mode 100644 index 0000000000..f7456baef8 --- /dev/null +++ b/tools/EventClients/lib/c++/xbmcclient.h @@ -0,0 +1,816 @@ +#ifndef __XBMC_CLIENT_H__ +#define __XBMC_CLIENT_H__ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#ifdef _WIN32 +#include <winsock.h> +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> +#endif +#include <vector> +#include <iostream> +#include <fstream> +#include <time.h> + +#define STD_PORT 9777 + +#define MS_ABSOLUTE 0x01 +//#define MS_RELATIVE 0x02 + +#define BTN_USE_NAME 0x01 +#define BTN_DOWN 0x02 +#define BTN_UP 0x04 +#define BTN_USE_AMOUNT 0x08 +#define BTN_QUEUE 0x10 +#define BTN_NO_REPEAT 0x20 +#define BTN_VKEY 0x40 +#define BTN_AXIS 0x80 + +#define PT_HELO 0x01 +#define PT_BYE 0x02 +#define PT_BUTTON 0x03 +#define PT_MOUSE 0x04 +#define PT_PING 0x05 +#define PT_BROADCAST 0x06 +#define PT_NOTIFICATION 0x07 +#define PT_BLOB 0x08 +#define PT_LOG 0x09 +#define PT_ACTION 0x0A +#define PT_DEBUG 0xFF + +#define ICON_NONE 0x00 +#define ICON_JPEG 0x01 +#define ICON_PNG 0x02 +#define ICON_GIF 0x03 + +#define MAX_PACKET_SIZE 1024 +#define HEADER_SIZE 32 +#define MAX_PAYLOAD_SIZE (MAX_PACKET_SIZE - HEADER_SIZE) + +#define MAJOR_VERSION 2 +#define MINOR_VERSION 0 + +#define LOGDEBUG 0 +#define LOGINFO 1 +#define LOGNOTICE 2 +#define LOGWARNING 3 +#define LOGERROR 4 +#define LOGSEVERE 5 +#define LOGFATAL 6 +#define LOGNONE 7 + +#define ACTION_EXECBUILTIN 0x01 +#define ACTION_BUTTON 0x02 + +class CAddress +{ +private: + struct sockaddr_in m_Addr; +public: + CAddress(int Port = STD_PORT) + { + m_Addr.sin_family = AF_INET; + m_Addr.sin_port = htons(Port); + m_Addr.sin_addr.s_addr = INADDR_ANY; + memset(m_Addr.sin_zero, '\0', sizeof m_Addr.sin_zero); + } + + CAddress(const char *Address, int Port = STD_PORT) + { + m_Addr.sin_port = htons(Port); + + struct hostent *h; + if (Address == NULL || (h=gethostbyname(Address)) == NULL) + { + if (Address != NULL) + printf("Error: Get host by name\n"); + + m_Addr.sin_addr.s_addr = INADDR_ANY; + m_Addr.sin_family = AF_INET; + } + else + { + m_Addr.sin_family = h->h_addrtype; + m_Addr.sin_addr = *((struct in_addr *)h->h_addr); + } + memset(m_Addr.sin_zero, '\0', sizeof m_Addr.sin_zero); + } + + void SetPort(int port) + { + m_Addr.sin_port = htons(port); + } + + const sockaddr *GetAddress() + { + return ((struct sockaddr *)&m_Addr); + } + + bool Bind(int Sockfd) + { + return (bind(Sockfd, (struct sockaddr *)&m_Addr, sizeof m_Addr) == 0); + } +}; + +class XBMCClientUtils +{ +public: + XBMCClientUtils() {} + ~XBMCClientUtils() {} + static unsigned int GetUniqueIdentifier() + { + static time_t id = time(NULL); + return id; + } + + static void Clean() + { + #ifdef _WIN32 + WSACleanup(); + #endif + } + + static bool Initialize() + { + #ifdef _WIN32 + WSADATA wsaData; + if (WSAStartup(MAKEWORD(1, 1), &wsaData)) + return false; + #endif + return true; + } +}; + +class CPacket +{ +/* Base class that implements a single event packet. + + - Generic packet structure (maximum 1024 bytes per packet) + - Header is 32 bytes long, so 992 bytes available for payload + - large payloads can be split into multiple packets using H4 and H5 + H5 should contain total no. of packets in such a case + - H6 contains length of P1, which is limited to 992 bytes + - if H5 is 0 or 1, then H4 will be ignored (single packet msg) + - H7 must be set to zeros for now + + ----------------------------- + | -H1 Signature ("XBMC") | - 4 x CHAR 4B + | -H2 Version (eg. 2.0) | - 2 x UNSIGNED CHAR 2B + | -H3 PacketType | - 1 x UNSIGNED SHORT 2B + | -H4 Sequence number | - 1 x UNSIGNED LONG 4B + | -H5 No. of packets in msg | - 1 x UNSIGNED LONG 4B + | -H6 Payload size | - 1 x UNSIGNED SHORT 2B + | -H7 Client's unique token | - 1 x UNSIGNED LONG 4B + | -H8 Reserved | - 10 x UNSIGNED CHAR 10B + |---------------------------| + | -P1 payload | - + ----------------------------- +*/ +public: + CPacket() + { + m_PacketType = 0; + } + virtual ~CPacket() + { } + + bool Send(int Socket, CAddress &Addr, unsigned int UID = XBMCClientUtils::GetUniqueIdentifier()) + { + if (m_Payload.size() == 0) + ConstructPayload(); + bool SendSuccessfull = true; + int NbrOfPackages = (m_Payload.size() / MAX_PAYLOAD_SIZE) + 1; + int Send = 0; + int Sent = 0; + int Left = m_Payload.size(); + for (int Package = 1; Package <= NbrOfPackages; Package++) + { + if (Left > MAX_PAYLOAD_SIZE) + { + Send = MAX_PAYLOAD_SIZE; + Left -= Send; + } + else + { + Send = Left; + Left = 0; + } + + ConstructHeader(m_PacketType, NbrOfPackages, Package, Send, UID, m_Header); + char t[MAX_PACKET_SIZE]; + int i, j; + for (i = 0; i < 32; i++) + t[i] = m_Header[i]; + + for (j = 0; j < Send; j++) + t[(32 + j)] = m_Payload[j + Sent]; + + int rtn = sendto(Socket, t, (32 + Send), 0, Addr.GetAddress(), sizeof(struct sockaddr)); + + if (rtn != (32 + Send)) + SendSuccessfull = false; + + Sent += Send; + } + return SendSuccessfull; + } +protected: + char m_Header[HEADER_SIZE]; + unsigned short m_PacketType; + + std::vector<char> m_Payload; + + static void ConstructHeader(int PacketType, int NumberOfPackets, int CurrentPacket, unsigned short PayloadSize, unsigned int UniqueToken, char *Header) + { + sprintf(Header, "XBMC"); + for (int i = 4; i < HEADER_SIZE; i++) + Header[i] = 0; + Header[4] = MAJOR_VERSION; + Header[5] = MINOR_VERSION; + if (CurrentPacket == 1) + { + Header[6] = ((PacketType & 0xff00) >> 8); + Header[7] = (PacketType & 0x00ff); + } + else + { + Header[6] = ((PT_BLOB & 0xff00) >> 8); + Header[7] = (PT_BLOB & 0x00ff); + } + Header[8] = ((CurrentPacket & 0xff000000) >> 24); + Header[9] = ((CurrentPacket & 0x00ff0000) >> 16); + Header[10] = ((CurrentPacket & 0x0000ff00) >> 8); + Header[11] = (CurrentPacket & 0x000000ff); + + Header[12] = ((NumberOfPackets & 0xff000000) >> 24); + Header[13] = ((NumberOfPackets & 0x00ff0000) >> 16); + Header[14] = ((NumberOfPackets & 0x0000ff00) >> 8); + Header[15] = (NumberOfPackets & 0x000000ff); + + Header[16] = ((PayloadSize & 0xff00) >> 8); + Header[17] = (PayloadSize & 0x00ff); + + Header[18] = ((UniqueToken & 0xff000000) >> 24); + Header[19] = ((UniqueToken & 0x00ff0000) >> 16); + Header[20] = ((UniqueToken & 0x0000ff00) >> 8); + Header[21] = (UniqueToken & 0x000000ff); + } + + virtual void ConstructPayload() + { } +}; + +class CPacketHELO : public CPacket +{ + /************************************************************************/ + /* Payload format */ + /* %s - device name (max 128 chars) */ + /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */ + /* %s - my port ( 0=>not listening ) */ + /* %d - reserved1 ( 0 ) */ + /* %d - reserved2 ( 0 ) */ + /* XX - imagedata ( can span multiple packets ) */ + /************************************************************************/ +private: + std::vector<char> m_DeviceName; + unsigned short m_IconType; + char *m_IconData; + unsigned short m_IconSize; +public: + virtual void ConstructPayload() + { + m_Payload.clear(); + + for (unsigned int i = 0; i < m_DeviceName.size(); i++) + m_Payload.push_back(m_DeviceName[i]); + + m_Payload.push_back('\0'); + + m_Payload.push_back(m_IconType); + + m_Payload.push_back(0); + m_Payload.push_back('\0'); + + for (int j = 0; j < 8; j++) + m_Payload.push_back(0); + + for (int ico = 0; ico < m_IconSize; ico++) + m_Payload.push_back(m_IconData[ico]); + } + + CPacketHELO(const char *DevName, unsigned short IconType, const char *IconFile = NULL) : CPacket() + { + m_PacketType = PT_HELO; + + unsigned int len = strlen(DevName); + for (unsigned int i = 0; i < len; i++) + m_DeviceName.push_back(DevName[i]); + + m_IconType = IconType; + + if (IconType == ICON_NONE || IconFile == NULL) + { + m_IconData = NULL; + m_IconSize = 0; + return; + } + + std::ifstream::pos_type size; + + std::ifstream file (IconFile, std::ios::in|std::ios::binary|std::ios::ate); + if (file.is_open()) + { + size = file.tellg(); + m_IconData = new char [size]; + file.seekg (0, std::ios::beg); + file.read (m_IconData, size); + file.close(); + m_IconSize = size; + } + else + { + m_IconType = ICON_NONE; + m_IconSize = 0; + } + } + + virtual ~CPacketHELO() + { + m_DeviceName.clear(); + if (m_IconData) + free(m_IconData); + } +}; + +class CPacketNOTIFICATION : public CPacket +{ + /************************************************************************/ + /* Payload format: */ + /* %s - caption */ + /* %s - message */ + /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */ + /* %d - reserved ( 0 ) */ + /* XX - imagedata ( can span multiple packets ) */ + /************************************************************************/ +private: + std::vector<char> m_Title; + std::vector<char> m_Message; + unsigned short m_IconType; + char *m_IconData; + unsigned short m_IconSize; +public: + virtual void ConstructPayload() + { + m_Payload.clear(); + + for (unsigned int i = 0; i < m_Title.size(); i++) + m_Payload.push_back(m_Title[i]); + + m_Payload.push_back('\0'); + + for (unsigned int i = 0; i < m_Message.size(); i++) + m_Payload.push_back(m_Message[i]); + + m_Payload.push_back('\0'); + + m_Payload.push_back(m_IconType); + + for (int i = 0; i < 4; i++) + m_Payload.push_back(0); + + for (int ico = 0; ico < m_IconSize; ico++) + m_Payload.push_back(m_IconData[ico]); + } + + CPacketNOTIFICATION(const char *Title, const char *Message, unsigned short IconType, const char *IconFile = NULL) : CPacket() + { + m_PacketType = PT_NOTIFICATION; + m_IconData = NULL; + + unsigned int len = 0; + if (Title != NULL) + { + len = strlen(Title); + for (unsigned int i = 0; i < len; i++) + m_Title.push_back(Title[i]); + } + + if (Message != NULL) + { + len = strlen(Message); + for (unsigned int i = 0; i < len; i++) + m_Message.push_back(Message[i]); + } + m_IconType = IconType; + + if (IconType == ICON_NONE || IconFile == NULL) + return; + + std::ifstream::pos_type size; + + std::ifstream file (IconFile, std::ios::in|std::ios::binary|std::ios::ate); + if (file.is_open()) + { + size = file.tellg(); + m_IconData = new char [size]; + file.seekg (0, std::ios::beg); + file.read (m_IconData, size); + file.close(); + m_IconSize = size; + } + else + { + m_IconType = ICON_NONE; + m_IconSize = 0; + } + } + + virtual ~CPacketNOTIFICATION() + { + m_Title.clear(); + m_Message.clear(); + if (m_IconData) + free(m_IconData); + } +}; + +class CPacketBUTTON : public CPacket +{ + /************************************************************************/ + /* Payload format */ + /* %i - button code */ + /* %i - flags 0x01 => use button map/name instead of code */ + /* 0x02 => btn down */ + /* 0x04 => btn up */ + /* 0x08 => use amount */ + /* 0x10 => queue event */ + /* 0x20 => do not repeat */ + /* 0x40 => virtual key */ + /* 0x40 => axis key */ + /* %i - amount ( 0 => 65k maps to -1 => 1 ) */ + /* %s - device map (case sensitive and required if flags & 0x01) */ + /* "KB" - Standard keyboard map */ + /* "XG" - Xbox Gamepad */ + /* "R1" - Xbox Remote */ + /* "R2" - Xbox Universal Remote */ + /* "LI:devicename" - valid LIRC device map where 'devicename' */ + /* is the actual name of the LIRC device */ + /* "JS<num>:joyname" - valid Joystick device map where */ + /* 'joyname' is the name specified in */ + /* the keymap. JS only supports button code */ + /* and not button name currently (!0x01). */ + /* %s - button name (required if flags & 0x01) */ + /************************************************************************/ +private: + std::vector<char> m_DeviceMap; + std::vector<char> m_Button; + unsigned short m_ButtonCode; + unsigned short m_Amount; + unsigned short m_Flags; +public: + virtual void ConstructPayload() + { + m_Payload.clear(); + + if (m_Button.size() != 0) + { + if (!(m_Flags & BTN_USE_NAME)) // If the BTN_USE_NAME isn't flagged for some reason + m_Flags |= BTN_USE_NAME; + m_ButtonCode = 0; + } + else + m_Button.clear(); + + if (m_Amount > 0) + { + if (!(m_Flags & BTN_USE_AMOUNT)) + m_Flags |= BTN_USE_AMOUNT; + } + if (!((m_Flags & BTN_DOWN) || (m_Flags & BTN_UP))) //If none of them are tagged. + m_Flags |= BTN_DOWN; + + m_Payload.push_back(((m_ButtonCode & 0xff00) >> 8)); + m_Payload.push_back( (m_ButtonCode & 0x00ff)); + + m_Payload.push_back(((m_Flags & 0xff00) >> 8) ); + m_Payload.push_back( (m_Flags & 0x00ff)); + + m_Payload.push_back(((m_Amount & 0xff00) >> 8) ); + m_Payload.push_back( (m_Amount & 0x00ff)); + + + for (unsigned int i = 0; i < m_DeviceMap.size(); i++) + m_Payload.push_back(m_DeviceMap[i]); + + m_Payload.push_back('\0'); + + for (unsigned int i = 0; i < m_Button.size(); i++) + m_Payload.push_back(m_Button[i]); + + m_Payload.push_back('\0'); + } + + CPacketBUTTON(const char *Button, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) : CPacket() + { + m_PacketType = PT_BUTTON; + m_Flags = Flags; + m_ButtonCode = 0; + m_Amount = Amount; + + unsigned int len = strlen(DeviceMap); + for (unsigned int i = 0; i < len; i++) + m_DeviceMap.push_back(DeviceMap[i]); + + len = strlen(Button); + for (unsigned int i = 0; i < len; i++) + m_Button.push_back(Button[i]); + } + + CPacketBUTTON(unsigned short ButtonCode, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) : CPacket() + { + m_PacketType = PT_BUTTON; + m_Flags = Flags; + m_ButtonCode = ButtonCode; + m_Amount = Amount; + + unsigned int len = strlen(DeviceMap); + for (unsigned int i = 0; i < len; i++) + m_DeviceMap.push_back(DeviceMap[i]); + } + + CPacketBUTTON(unsigned short ButtonCode, unsigned short Flags, unsigned short Amount = 0) : CPacket() + { + m_PacketType = PT_BUTTON; + m_Flags = Flags; + m_ButtonCode = ButtonCode; + m_Amount = Amount; + } + + // Used to send a release event + CPacketBUTTON() : CPacket() + { + m_PacketType = PT_BUTTON; + m_Flags = BTN_UP; + m_Amount = 0; + m_ButtonCode = 0; + } + + virtual ~CPacketBUTTON() + { + m_DeviceMap.clear(); + m_Button.clear(); + } + + inline unsigned short GetFlags() { return m_Flags; } + inline unsigned short GetButtonCode() { return m_ButtonCode; } +}; + +class CPacketPING : public CPacket +{ + /************************************************************************/ + /* no payload */ + /************************************************************************/ +public: + CPacketPING() : CPacket() + { + m_PacketType = PT_PING; + } + virtual ~CPacketPING() + { } +}; + +class CPacketBYE : public CPacket +{ + /************************************************************************/ + /* no payload */ + /************************************************************************/ +public: + CPacketBYE() : CPacket() + { + m_PacketType = PT_BYE; + } + virtual ~CPacketBYE() + { } +}; + +class CPacketMOUSE : public CPacket +{ + /************************************************************************/ + /* Payload format */ + /* %c - flags */ + /* - 0x01 absolute position */ + /* %i - mousex (0-65535 => maps to screen width) */ + /* %i - mousey (0-65535 => maps to screen height) */ + /************************************************************************/ +private: + unsigned short m_X; + unsigned short m_Y; + unsigned char m_Flag; +public: + CPacketMOUSE(int X, int Y, unsigned char Flag = MS_ABSOLUTE) + { + m_PacketType = PT_MOUSE; + m_Flag = Flag; + m_X = X; + m_Y = Y; + } + + virtual void ConstructPayload() + { + m_Payload.clear(); + + m_Payload.push_back(m_Flag); + + m_Payload.push_back(((m_X & 0xff00) >> 8)); + m_Payload.push_back( (m_X & 0x00ff)); + + m_Payload.push_back(((m_Y & 0xff00) >> 8)); + m_Payload.push_back( (m_Y & 0x00ff)); + } + + virtual ~CPacketMOUSE() + { } +}; + +class CPacketLOG : public CPacket +{ + /************************************************************************/ + /* Payload format */ + /* %c - log type */ + /* %s - message */ + /************************************************************************/ +private: + std::vector<char> m_Message; + unsigned char m_LogLevel; + bool m_AutoPrintf; +public: + CPacketLOG(int LogLevel, const char *Message, bool AutoPrintf = true) + { + m_PacketType = PT_LOG; + + unsigned int len = strlen(Message); + for (unsigned int i = 0; i < len; i++) + m_Message.push_back(Message[i]); + + m_LogLevel = LogLevel; + m_AutoPrintf = AutoPrintf; + } + + virtual void ConstructPayload() + { + m_Payload.clear(); + + m_Payload.push_back( (m_LogLevel & 0x00ff) ); + + if (m_AutoPrintf) + { + char* str=&m_Message[0]; + printf("%s\n", str); + } + for (unsigned int i = 0; i < m_Message.size(); i++) + m_Payload.push_back(m_Message[i]); + + m_Payload.push_back('\0'); + } + + virtual ~CPacketLOG() + { } +}; + +class CPacketACTION : public CPacket +{ + /************************************************************************/ + /* Payload format */ + /* %c - action type */ + /* %s - action message */ + /************************************************************************/ +private: + unsigned char m_ActionType; + std::vector<char> m_Action; +public: + CPacketACTION(const char *Action, unsigned char ActionType = ACTION_EXECBUILTIN) + { + m_PacketType = PT_ACTION; + + m_ActionType = ActionType; + unsigned int len = strlen(Action); + for (unsigned int i = 0; i < len; i++) + m_Action.push_back(Action[i]); + } + + virtual void ConstructPayload() + { + m_Payload.clear(); + + m_Payload.push_back(m_ActionType); + for (unsigned int i = 0; i < m_Action.size(); i++) + m_Payload.push_back(m_Action[i]); + + m_Payload.push_back('\0'); + } + + virtual ~CPacketACTION() + { } +}; + +class CXBMCClient +{ +private: + CAddress m_Addr; + int m_Socket; + unsigned int m_UID; +public: + CXBMCClient(const char *IP = "127.0.0.1", int Port = 9777, int Socket = -1, unsigned int UID = 0) + { + m_Addr = CAddress(IP, Port); + if (Socket == -1) + m_Socket = socket(AF_INET, SOCK_DGRAM, 0); + else + m_Socket = Socket; + + if (UID) + m_UID = UID; + else + m_UID = XBMCClientUtils::GetUniqueIdentifier(); + } + + void SendNOTIFICATION(const char *Title, const char *Message, unsigned short IconType, const char *IconFile = NULL) + { + if (m_Socket < 0) + return; + + CPacketNOTIFICATION notification(Title, Message, IconType, IconFile); + notification.Send(m_Socket, m_Addr, m_UID); + } + + void SendHELO(const char *DevName, unsigned short IconType, const char *IconFile = NULL) + { + if (m_Socket < 0) + return; + + CPacketHELO helo(DevName, IconType, IconFile); + helo.Send(m_Socket, m_Addr, m_UID); + } + + void SendButton(const char *Button, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) + { + if (m_Socket < 0) + return; + + CPacketBUTTON button(Button, DeviceMap, Flags, Amount); + button.Send(m_Socket, m_Addr, m_UID); + } + + void SendButton(unsigned short ButtonCode, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) + { + if (m_Socket < 0) + return; + + CPacketBUTTON button(ButtonCode, DeviceMap, Flags, Amount); + button.Send(m_Socket, m_Addr, m_UID); + } + + void SendButton(unsigned short ButtonCode, unsigned Flags, unsigned short Amount = 0) + { + if (m_Socket < 0) + return; + + CPacketBUTTON button(ButtonCode, Flags, Amount); + button.Send(m_Socket, m_Addr, m_UID); + } + + void SendMOUSE(int X, int Y, unsigned char Flag = MS_ABSOLUTE) + { + if (m_Socket < 0) + return; + + CPacketMOUSE mouse(X, Y, Flag); + mouse.Send(m_Socket, m_Addr, m_UID); + } + + void SendLOG(int LogLevel, const char *Message, bool AutoPrintf = true) + { + if (m_Socket < 0) + return; + + CPacketLOG log(LogLevel, Message, AutoPrintf); + log.Send(m_Socket, m_Addr, m_UID); + } + + void SendACTION(const char *ActionMessage, int ActionType = ACTION_EXECBUILTIN) + { + if (m_Socket < 0) + return; + + CPacketACTION action(ActionMessage, ActionType); + action.Send(m_Socket, m_Addr, m_UID); + } +}; + +#endif diff --git a/tools/EventClients/lib/java/build.xml b/tools/EventClients/lib/java/build.xml new file mode 100755 index 0000000000..fe25bde90a --- /dev/null +++ b/tools/EventClients/lib/java/build.xml @@ -0,0 +1,72 @@ +<project default="jar" name="JXBMCEventClient"> + <description description="JXBMCEventClient"/> + <target name="init"> + <tstamp/> + <property name="srcdir" value="${basedir}/src"/> + <property name="classdir" value="${basedir}/classes"/> + <property name="apidir" value="${basedir}/doc/api"/> + <property name="libdir" value="/usr/local/share/java/classes"/> + <property name="projectname" value="JXBMCEventClient"/> + <property name="jarfile" value="${projectname}.jar"/> + <property name="distdir" value="${basedir}/../dist"/> + <fileset id="eventclient.files" dir="${classdir}" includes="**/*"/> + <path id="classpath"> + <pathelement location="${libdir}/junit.jar" /> + </path> + </target> + + + <target name="jar" depends="compile"> + <jar jarfile="${jarfile}" index="true"> + <fileset refid="eventclient.files"/> + </jar> + </target> + + <target name="dist" depends="jar, javadoc"> + <fail unless="version">use: ant dist -Dversion=x.x</fail> + <mkdir dir="${distdir}"/> + <copy todir="${distdir}/doc"> + <fileset dir="${apidir}"/> + </copy> + <property name="filename" value="${projectname}-${version}"/> + <copy file="${jarfile}" tofile="${distdir}/${projectname}-${version}.jar" /> + <tar destfile="${distdir}/${filename}.tar.gz" compression="gzip"> + <tarfileset dir="${basedir}" prefix="${filename}"> + <exclude name="classes/**"/> + <exclude name="**/CVS"/> + <exclude name="**/.*"/> + <exclude name="${jarfile}"/> + <exclude name="doc/**"/> + </tarfileset> + </tar> + </target> + + <target name="compile" depends="init" description="Compiles all classes"> + <mkdir dir="${classdir}"/> + <javac debug="yes" deprecation="true" destdir="${classdir}" srcdir="${srcdir}" classpathref="classpath"/> + </target> + + <target name="javadoc" depends="init"> + <mkdir dir="${apidir}"/> + <javadoc + packagenames="org.xbmc.eventclient.*" + sourcepath="${srcdir}" + defaultexcludes="yes" + destdir="${apidir}" + author="true" + version="true" + use="true" + private="false" + windowtitle="${projectname} API" + classpathref="classpath"> + <link href="http://java.sun.com/j2se/1.4.2/docs/api/"/> + </javadoc> + </target> + + <target name="clean" depends="init" description="cleans all classes and jars"> + <delete dir="${classdir}"/> + <delete dir="${apidir}"/> + <delete file="${jarfile}"/> + </target> + +</project> diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/Packet.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/Packet.java new file mode 100755 index 0000000000..4904d5c9b1 --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/Packet.java @@ -0,0 +1,271 @@ +package org.xbmc.eventclient; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; + +/** + * XBMC Event Client Class + * <p> + * Implementation of XBMC's UDP based input system. + * A set of classes that abstract the various packets that the event server + * currently supports. In addition, there's also a class, XBMCClient, that + * provides functions that sends the various packets. Use XBMCClient if you + * don't need complete control over packet structure. + * </p> + * <p> + * The basic workflow involves: + * <ol> + * <li>Send a HELO packet</li> + * <li>Send x number of valid packets</li> + * <li>Send a BYE packet</li> + * </ol> + * </p> + * <p> + * IMPORTANT NOTE ABOUT TIMEOUTS: + * A client is considered to be timed out if XBMC doesn't received a packet + * at least once every 60 seconds. To "ping" XBMC with an empty packet use + * PacketPING or XBMCClient.ping(). See the documentation for details. + * </p> + * <p> + * Base class that implements a single event packet. + * - Generic packet structure (maximum 1024 bytes per packet) + * - Header is 32 bytes long, so 992 bytes available for payload + * - large payloads can be split into multiple packets using H4 and H5 + * H5 should contain total no. of packets in such a case + * - H6 contains length of P1, which is limited to 992 bytes + * - if H5 is 0 or 1, then H4 will be ignored (single packet msg) + * - H7 must be set to zeros for now + * </p> + * <pre> + * ----------------------------- + * | -H1 Signature ("XBMC") | - 4 x CHAR 4B + * | -H2 Version (eg. 2.0) | - 2 x UNSIGNED CHAR 2B + * | -H3 PacketType | - 1 x UNSIGNED SHORT 2B + * | -H4 Sequence number | - 1 x UNSIGNED LONG 4B + * | -H5 No. of packets in msg | - 1 x UNSIGNED LONG 4B + * | -H6 Payloadsize of packet | - 1 x UNSIGNED SHORT 2B + * | -H7 Client's unique token | - 1 x UNSIGNED LONG 4B + * | -H8 Reserved | - 10 x UNSIGNED CHAR 10B + * |---------------------------| + * | -P1 payload | - + * ----------------------------- + * </pre> + * @author Stefan Agner + * + */ +public abstract class Packet { + + private byte[] sig; + private byte[] payload = new byte[0]; + private byte minver; + private byte majver; + + private short packettype; + + + private final static short MAX_PACKET_SIZE = 1024; + private final static short HEADER_SIZE = 32; + private final static short MAX_PAYLOAD_SIZE = MAX_PACKET_SIZE - HEADER_SIZE; + + protected final static byte PT_HELO = 0x01; + protected final static byte PT_BYE = 0x02; + protected final static byte PT_BUTTON = 0x03; + protected final static byte PT_MOUSE = 0x04; + protected final static byte PT_PING = 0x05; + protected final static byte PT_BROADCAST = 0x06; + protected final static byte PT_NOTIFICATION = 0x07; + protected final static byte PT_BLOB = 0x08; + protected final static byte PT_LOG = 0x09; + protected final static byte PT_ACTION = 0x0A; + protected final static byte PT_DEBUG = (byte)0xFF; + + public final static byte ICON_NONE = 0x00; + public final static byte ICON_JPEG = 0x01; + public final static byte ICON_PNG = 0x02; + public final static byte ICON_GIF = 0x03; + + private static int uid = (int)(Math.random()*Integer.MAX_VALUE); + + /** + * This is an Abstract class and cannot be instanced. Please use one of the Packet implementation Classes + * (PacketXXX). + * + * Implements an XBMC Event Client Packet. Type is to be specified at creation time, Payload can be added + * with the various appendPayload methods. Packet can be sent through UDP-Socket with method "send". + * @param packettype Type of Packet (PT_XXX) + */ + protected Packet(short packettype) + { + sig = new byte[] {'X', 'B', 'M', 'C' }; + minver = 0; + majver = 2; + this.packettype = packettype; + } + + /** + * Appends a String to the payload (terminated with 0x00) + * @param payload Payload as String + */ + protected void appendPayload(String payload) + { + byte[] payloadarr = payload.getBytes(); + int oldpayloadsize = this.payload.length; + byte[] oldpayload = this.payload; + this.payload = new byte[oldpayloadsize+payloadarr.length+1]; // Create new Array with more place (+1 for string terminator) + System.arraycopy(oldpayload, 0, this.payload, 0, oldpayloadsize); + System.arraycopy(payloadarr, 0, this.payload, oldpayloadsize, payloadarr.length); + } + + /** + * Appends a single Byte to the payload + * @param payload Payload + */ + protected void appendPayload(byte payload) + { + appendPayload(new byte[] { payload }); + } + + /** + * Appends a Byte-Array to the payload + * @param payloadarr Payload + */ + protected void appendPayload(byte[] payloadarr) + { + int oldpayloadsize = this.payload.length; + byte[] oldpayload = this.payload; + this.payload = new byte[oldpayloadsize+payloadarr.length]; + System.arraycopy(oldpayload, 0, this.payload, 0, oldpayloadsize); + System.arraycopy(payloadarr, 0, this.payload, oldpayloadsize, payloadarr.length); + } + + /** + * Appends an integer to the payload + * @param i Payload + */ + protected void appendPayload(int i) { + appendPayload(intToByteArray(i)); + } + + /** + * Appends a short to the payload + * @param s Payload + */ + protected void appendPayload(short s) { + appendPayload(shortToByteArray(s)); + } + + /** + * Get Number of Packets which will be sent with current Payload... + * @return Number of Packets + */ + public int getNumPackets() + { + return (int)((payload.length + (MAX_PAYLOAD_SIZE - 1)) / MAX_PAYLOAD_SIZE); + } + + /** + * Get Header for a specific Packet in this sequence... + * @param seq Current sequence number + * @param maxseq Maximal sequence number + * @param actpayloadsize Payloadsize of this packet + * @return Byte-Array with Header information (currently 32-Byte long, see HEADER_SIZE) + */ + private byte[] getHeader(int seq, int maxseq, short actpayloadsize) + { + byte[] header = new byte[HEADER_SIZE]; + System.arraycopy(sig, 0, header, 0, 4); + header[4] = majver; + header[5] = minver; + byte[] packettypearr = shortToByteArray(this.packettype); + System.arraycopy(packettypearr, 0, header, 6, 2); + byte[] seqarr = intToByteArray(seq); + System.arraycopy(seqarr, 0, header, 8, 4); + byte[] maxseqarr = intToByteArray(maxseq); + System.arraycopy(maxseqarr, 0, header, 12, 4); + byte[] payloadsize = shortToByteArray(actpayloadsize); + System.arraycopy(payloadsize, 0, header, 16, 2); + byte[] uid = intToByteArray(Packet.uid); + System.arraycopy(uid, 0, header, 18, 4); + byte[] reserved = new byte[10]; + System.arraycopy(reserved, 0, header, 22, 10); + + return header; + } + + /** + * Generates the whole UDP-Message with Header and Payload of a specific Packet in sequence + * @param seq Current sequence number + * @return Byte-Array with UDP-Message + */ + private byte[] getUDPMessage(int seq) + { + int maxseq = (int)((payload.length + (MAX_PAYLOAD_SIZE - 1)) / MAX_PAYLOAD_SIZE); + if(seq > maxseq) + return null; + + short actpayloadsize; + + if(seq == maxseq) + actpayloadsize = (short)(payload.length%MAX_PAYLOAD_SIZE); + + else + actpayloadsize = (short)MAX_PAYLOAD_SIZE; + + byte[] pack = new byte[HEADER_SIZE+actpayloadsize]; + + System.arraycopy(getHeader(seq, maxseq, actpayloadsize), 0, pack, 0, HEADER_SIZE); + System.arraycopy(payload, (seq-1)*MAX_PAYLOAD_SIZE, pack, HEADER_SIZE, actpayloadsize); + + return pack; + } + + /** + * Sends this packet to the EventServer + * @param adr Address of the EventServer + * @param port Port of the EventServer + * @throws IOException + */ + public void send(InetAddress adr, int port) throws IOException + { + int maxseq = getNumPackets(); + DatagramSocket s = new DatagramSocket(); + + // For each Packet in Sequence... + for(int seq=1;seq<=maxseq;seq++) + { + // Get Message and send them... + byte[] pack = getUDPMessage(seq); + DatagramPacket p = new DatagramPacket(pack, pack.length); + p.setAddress(adr); + p.setPort(port); + s.send(p); + } + } + + /** + * Helper Method to convert an integer to a Byte array + * @param value + * @return Byte-Array + */ + private static final byte[] intToByteArray(int value) { + return new byte[] { + (byte)(value >>> 24), + (byte)(value >>> 16), + (byte)(value >>> 8), + (byte)value}; + } + + /** + * Helper Method to convert an short to a Byte array + * @param value + * @return Byte-Array + */ + private static final byte[] shortToByteArray(short value) { + return new byte[] { + (byte)(value >>> 8), + (byte)value}; + } + + +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketACTION.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketACTION.java new file mode 100755 index 0000000000..ae633c783a --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketACTION.java @@ -0,0 +1,43 @@ +package org.xbmc.eventclient; +/** + * XBMC Event Client Class + * + * An ACTION packet tells XBMC to do the action specified, based on the type it knows were it needs to be sent. + * The idea is that this will be as in scripting/skining and keymapping, just triggered from afar. + * @author Stefan Agner + * + */ +public class PacketACTION extends Packet { + + public final static byte ACTION_EXECBUILTIN = 0x01; + public final static byte ACTION_BUTTON = 0x02; + + + /** + * An ACTION packet tells XBMC to do the action specified, based on the type it knows were it needs to be sent. + * @param actionmessage Actionmessage (as in scripting/skinning) + */ + public PacketACTION(String actionmessage) + { + super(PT_ACTION); + byte actiontype = ACTION_EXECBUILTIN; + appendPayload(actionmessage, actiontype); + } + + /** + * An ACTION packet tells XBMC to do the action specified, based on the type it knows were it needs to be sent. + * @param actionmessage Actionmessage (as in scripting/skinning) + * @param actiontype Actiontype (ACTION_EXECBUILTIN or ACTION_BUTTON) + */ + public PacketACTION(String actionmessage, byte actiontype) + { + super(PT_ACTION); + appendPayload(actionmessage, actiontype); + } + + private void appendPayload(String actionmessage, byte actiontype) + { + appendPayload(actiontype); + appendPayload(actionmessage); + } +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBUTTON.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBUTTON.java new file mode 100755 index 0000000000..cc0ff35efb --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBUTTON.java @@ -0,0 +1,139 @@ +package org.xbmc.eventclient; +/** + * XBMC Event Client Class + * + * A button packet send a key press or release event to XBMC + * @author Stefan Agner + * + */ +public class PacketBUTTON extends Packet { + + protected final static byte BT_USE_NAME = 0x01; + protected final static byte BT_DOWN = 0x02; + protected final static byte BT_UP = 0x04; + protected final static byte BT_USE_AMOUNT = 0x08; + protected final static byte BT_QUEUE = 0x10; + protected final static byte BT_NO_REPEAT = 0x20; + protected final static byte BT_VKEY = 0x40; + protected final static byte BT_AXIS = (byte)0x80; + protected final static byte BT_AXISSINGLE = (byte)0x100; + + /** + * A button packet send a key press or release event to XBMC + * @param code raw button code (default: 0) + * @param repeat this key press should repeat until released (default: 1) + * Note that queued pressed cannot repeat. + * @param down if this is 1, it implies a press event, 0 implies a release + * event. (default: 1) + * @param queue a queued key press means that the button event is + * executed just once after which the next key press is processed. + * It can be used for macros. Currently there is no support for + * time delays between queued presses. (default: 0) + * @param amount unimplemented for now; in the future it will be used for + * specifying magnitude of analog key press events + * @param axis + */ + public PacketBUTTON(short code, boolean repeat, boolean down, boolean queue, short amount, byte axis) + { + super(PT_BUTTON); + String map_name = ""; + String button_name = ""; + short flags = 0; + appendPayload(code, map_name, button_name, repeat, down, queue, amount, axis, flags); + } + + /** + * A button packet send a key press or release event to XBMC + * @param map_name a combination of map_name and button_name refers to a + * mapping in the user's Keymap.xml or Lircmap.xml. + * map_name can be one of the following: + * <ul> + * <li>"KB" => standard keyboard map ( <keyboard> section )</li> + * <li>"XG" => xbox gamepad map ( <gamepad> section )</li> + * <li>"R1" => xbox remote map ( <remote> section )</li> + * <li>"R2" => xbox universal remote map ( <universalremote> section )</li> + * <li>"LI:devicename" => LIRC remote map where 'devicename' is the + * actual device's name</li></ul> + * @param button_name a button name defined in the map specified in map_name. + * For example, if map_name is "KB" refering to the <keyboard> section in Keymap.xml + * then, valid button_names include "printscreen", "minus", "x", etc. + * @param repeat this key press should repeat until released (default: 1) + * Note that queued pressed cannot repeat. + * @param down if this is 1, it implies a press event, 0 implies a release + * event. (default: 1) + * @param queue a queued key press means that the button event is + * executed just once after which the next key press is processed. + * It can be used for macros. Currently there is no support for + * time delays between queued presses. (default: 0) + * @param amount unimplemented for now; in the future it will be used for + * specifying magnitude of analog key press events + * @param axis + */ + public PacketBUTTON(String map_name, String button_name, boolean repeat, boolean down, boolean queue, short amount, byte axis) + { + super(PT_BUTTON); + short code = 0; + short flags = BT_USE_NAME; + appendPayload(code, map_name, button_name, repeat, down, queue, amount, axis, flags); + } + + /** + * Appends Payload for a Button Packet (this method is used by the different Constructors of this Packet) + * @param code raw button code (default: 0) + * @param map_name a combination of map_name and button_name refers to a + * mapping in the user's Keymap.xml or Lircmap.xml. + * map_name can be one of the following: + * <ul> + * <li>"KB" => standard keyboard map ( <keyboard> section )</li> + * <li>"XG" => xbox gamepad map ( <gamepad> section )</li> + * <li>"R1" => xbox remote map ( <remote> section )</li> + * <li>"R2" => xbox universal remote map ( <universalremote> section )</li> + * <li>"LI:devicename" => LIRC remote map where 'devicename' is the + * actual device's name</li></ul> + * @param button_name a button name defined in the map specified in map_name. + * For example, if map_name is "KB" refering to the <keyboard> section in Keymap.xml + * then, valid button_names include "printscreen", "minus", "x", etc. + * @param repeat this key press should repeat until released (default: 1) + * Note that queued pressed cannot repeat. + * @param down if this is 1, it implies a press event, 0 implies a release + * event. (default: 1) + * @param queue a queued key press means that the button event is + * executed just once after which the next key press is processed. + * It can be used for macros. Currently there is no support for + * time delays between queued presses. (default: 0) + * @param amount unimplemented for now; in the future it will be used for + * specifying magnitude of analog key press events + * @param axis + * @param flags Packet specific flags + */ + private void appendPayload(short code, String map_name, String button_name, boolean repeat, boolean down, boolean queue, short amount, byte axis, short flags) + { + if(amount>0) + flags |= BT_USE_AMOUNT; + else + amount = 0; + + if(down) + flags |= BT_DOWN; + else + flags |= BT_UP; + + if(!repeat) + flags |= BT_NO_REPEAT; + + if(queue) + flags |= BT_QUEUE; + + if(axis == 1) + flags |= BT_AXISSINGLE; + else if (axis == 2) + flags |= BT_AXIS; + + + appendPayload(code); + appendPayload(flags); + appendPayload(amount); + appendPayload(map_name); + appendPayload(button_name); + } +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBYE.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBYE.java new file mode 100755 index 0000000000..8c831b1ac0 --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBYE.java @@ -0,0 +1,19 @@ +package org.xbmc.eventclient; +/** + * XBMC Event Client Class + * + * A BYE packet terminates the connection to XBMC. + * @author Stefan Agner + * + */ +public class PacketBYE extends Packet +{ + + /** + * A BYE packet terminates the connection to XBMC. + */ + public PacketBYE() + { + super(PT_BYE); + } +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketHELO.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketHELO.java new file mode 100755 index 0000000000..f68ba46421 --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketHELO.java @@ -0,0 +1,46 @@ +package org.xbmc.eventclient; +import java.nio.charset.Charset; + +/** + * XBMC Event Client Class + * + * A HELO packet establishes a valid connection to XBMC. It is the + * first packet that should be sent. + * @author Stefan Agner + * + */ +public class PacketHELO extends Packet { + + + /** + * A HELO packet establishes a valid connection to XBMC. + * @param devicename Name of the device which connects to XBMC + */ + public PacketHELO(String devicename) + { + super(PT_HELO); + this.appendPayload(devicename); + this.appendPayload(ICON_NONE); + this.appendPayload((short)0); // port no + this.appendPayload(0); // reserved1 + this.appendPayload(0); // reserved2 + } + + /** + * A HELO packet establishes a valid connection to XBMC. + * @param devicename Name of the device which connects to XBMC + * @param iconType Type of the icon (Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF) + * @param iconData The icon as a Byte-Array + */ + public PacketHELO(String devicename, byte iconType, byte[] iconData) + { + super(PT_HELO); + this.appendPayload(devicename); + this.appendPayload(iconType); + this.appendPayload((short)0); // port no + this.appendPayload(0); // reserved1 + this.appendPayload(0); // reserved2 + this.appendPayload(iconData); // reserved2 + } + +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketLOG.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketLOG.java new file mode 100755 index 0000000000..693ad71ea6 --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketLOG.java @@ -0,0 +1,30 @@ +package org.xbmc.eventclient; +/** + * XBMC Event Client Class + * + * A LOG packet tells XBMC to log the message to xbmc.log with the loglevel as specified. + * @author Stefan Agner + * + */ +public class PacketLOG extends Packet { + + /** + * A LOG packet tells XBMC to log the message to xbmc.log with the loglevel as specified. + * @param loglevel the loglevel, follows XBMC standard. + * <ul> + * <li>0 = DEBUG</li> + * <li>1 = INFO</li> + * <li>2 = NOTICE</li> + * <li>3 = WARNING</li> + * <li>4 = ERROR</li> + * <li>5 = SEVERE</li> + * </ul> + * @param logmessage the message to log + */ + public PacketLOG(byte loglevel, String logmessage) + { + super(PT_LOG); + appendPayload(loglevel); + appendPayload(logmessage); + } +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketMOUSE.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketMOUSE.java new file mode 100755 index 0000000000..d7755ef0cc --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketMOUSE.java @@ -0,0 +1,27 @@ +package org.xbmc.eventclient; +/** + * XBMC Event Client Class + * + * A MOUSE packets sets the mouse position in XBMC + * @author Stefan Agner + * + */ +public class PacketMOUSE extends Packet { + + protected final static byte MS_ABSOLUTE = 0x01; + + /** + * A MOUSE packets sets the mouse position in XBMC + * @param x horitontal position ranging from 0 to 65535 + * @param y vertical position ranging from 0 to 65535 + */ + public PacketMOUSE(int x, int y) + { + super(PT_MOUSE); + byte flags = 0; + flags |= MS_ABSOLUTE; + appendPayload(flags); + appendPayload((short)x); + appendPayload((short)y); + } +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketNOTIFICATION.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketNOTIFICATION.java new file mode 100755 index 0000000000..15a5ec8f27 --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketNOTIFICATION.java @@ -0,0 +1,53 @@ +package org.xbmc.eventclient; +/** + * XBMC Event Client Class + * + * This packet displays a notification window in XBMC. It can contain + * a caption, a message and an icon. + * @author Stefan Agner + * + */ +public class PacketNOTIFICATION extends Packet { + + /** + * This packet displays a notification window in XBMC. + * @param title Message title + * @param message The actual message + * @param iconType Type of the icon (Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF) + * @param iconData The icon as a Byte-Array + */ + public PacketNOTIFICATION(String title, String message, byte iconType, byte[] iconData) + { + super(PT_NOTIFICATION); + appendPayload(title, message, iconType, iconData); + } + + /** + * This packet displays a notification window in XBMC. + * @param title Message title + * @param message The actual message + */ + public PacketNOTIFICATION(String title, String message) + { + super(PT_NOTIFICATION); + appendPayload(title, message, Packet.ICON_NONE, null); + } + + /** + * Appends the payload to the packet... + * @param title Message title + * @param message The actual message + * @param iconType Type of the icon (Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF) + * @param iconData The icon as a Byte-Array + */ + private void appendPayload(String title, String message, byte iconType, byte[] iconData) + { + appendPayload(title); + appendPayload(message); + appendPayload(iconType); + appendPayload(0); // reserved + if(iconData!=null) + appendPayload(iconData); + + } +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketPING.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketPING.java new file mode 100755 index 0000000000..e405812f32 --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketPING.java @@ -0,0 +1,19 @@ +package org.xbmc.eventclient; +/** + * XBMC Event Client Class + * + * A PING packet tells XBMC that the client is still alive. All valid + * packets act as ping (not just this one). A client needs to ping + * XBMC at least once in 60 seconds or it will time + * @author Stefan Agner + * + */ +public class PacketPING extends Packet { + /** + * A PING packet tells XBMC that the client is still alive. + */ + public PacketPING() + { + super(PT_PING); + } +} diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/XBMCClient.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/XBMCClient.java new file mode 100755 index 0000000000..4a0f85fd02 --- /dev/null +++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/XBMCClient.java @@ -0,0 +1,300 @@ +package org.xbmc.eventclient; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.InetAddress; + +/** + * XBMC Event Client Class + * + * Implements an XBMC-Client. This class can be used to implement your own application which + * should act as a Input device for XBMC. Also starts a Ping-Thread, which tells the XBMC EventServer + * that the client is alive. Therefore if you close your application you SHOULD call stopClient()! + * @author Stefan Agner + * + */ +public class XBMCClient +{ + private boolean hasIcon = false; + private String deviceName; + private PingThread oPingThread; + private byte iconType = Packet.ICON_PNG; + private byte[] iconData; + private InetAddress hostAddress; + private int hostPort; + + /** + * Starts a XBMC EventClient. + * @param hostAddress Address of the Host running XBMC + * @param hostPort Port of the Host running XBMC (default 9777) + * @param deviceName Name of the Device + * @param iconFile Path to the Iconfile (PNG, JPEG or GIF) + * @throws IOException + */ + public XBMCClient(InetAddress hostAddress, int hostPort, String deviceName, String iconFile) throws IOException + { + byte iconType = Packet.ICON_PNG; + // Assume png as icon type + if(iconFile.toLowerCase().endsWith(".jpeg")) + iconType = Packet.ICON_JPEG; + if(iconFile.toLowerCase().endsWith(".jpg")) + iconType = Packet.ICON_JPEG; + if(iconFile.toLowerCase().endsWith(".gif")) + iconType = Packet.ICON_GIF; + + // Read the icon file to the byte array... + FileInputStream iconFileStream = new FileInputStream(iconFile); + byte[] iconData = new byte[iconFileStream.available()]; + iconFileStream.read(iconData); + + hasIcon = true; + + // Call start-Method... + startClient(hostAddress, hostPort, deviceName, iconType, iconData); + } + + + /** + * Starts a XBMC EventClient. + * @param hostAddress Address of the Host running XBMC + * @param hostPort Port of the Host running XBMC (default 9777) + * @param deviceName Name of the Device + * @param iconType Type of the icon file (see Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF) + * @param iconData The icon itself as a Byte-Array + * @throws IOException + */ + public XBMCClient(InetAddress hostAddress, int hostPort, String deviceName, byte iconType, byte[] iconData) throws IOException + { + hasIcon = true; + startClient(hostAddress, hostPort, deviceName, iconType, iconData); + } + + /** + * Starts a XBMC EventClient without an icon. + * @param hostAddress Address of the Host running XBMC + * @param hostPort Port of the Host running XBMC (default 9777) + * @param deviceName Name of the Device + * @throws IOException + */ + public XBMCClient(InetAddress hostAddress, int hostPort, String deviceName) throws IOException + { + hasIcon = false; + byte iconType = Packet.ICON_NONE; + byte[] iconData = null; + startClient(hostAddress, hostPort, deviceName, iconType, iconData); + } + + + /** + * Starts a XBMC EventClient. + * @param hostAddress Address of the Host running XBMC + * @param hostPort Port of the Host running XBMC (default 9777) + * @param deviceName Name of the Device + * @param iconType Type of the icon file (see Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF) + * @param iconData The icon itself as a Byte-Array + * @throws IOException + */ + private void startClient(InetAddress hostAddress, int hostPort, String deviceName, byte iconType, byte[] iconData) throws IOException + { + // Save host address and port + this.hostAddress = hostAddress; + this.hostPort = hostPort; + this.deviceName = deviceName; + + this.iconType = iconType; + this.iconData = iconData; + + // Send Hello Packet... + PacketHELO p; + if(hasIcon) + p = new PacketHELO(deviceName, iconType, iconData); + else + p = new PacketHELO(deviceName); + + p.send(hostAddress, hostPort); + + // Start Thread (for Ping packets...) + oPingThread = new PingThread(hostAddress, hostPort, 20000); + oPingThread.start(); + } + + /** + * Stops the XBMC EventClient (especially the Ping-Thread) + * @throws IOException + */ + public void stopClient() throws IOException + { + // Stop Ping-Thread... + oPingThread.giveup(); + oPingThread.interrupt(); + + PacketBYE p = new PacketBYE(); + p.send(hostAddress, hostPort); + } + + + /** + * Displays a notification window in XBMC. + * @param title Message title + * @param message The actual message + */ + public void sendNotification(String title, String message) throws IOException + { + PacketNOTIFICATION p; + if(hasIcon) + p = new PacketNOTIFICATION(title, message, iconType, iconData); + else + p = new PacketNOTIFICATION(title, message); + p.send(hostAddress, hostPort); + } + + /** + * Sends a Button event + * @param code raw button code (default: 0) + * @param repeat this key press should repeat until released (default: 1) + * Note that queued pressed cannot repeat. + * @param down if this is 1, it implies a press event, 0 implies a release + * event. (default: 1) + * @param queue a queued key press means that the button event is + * executed just once after which the next key press is processed. + * It can be used for macros. Currently there is no support for + * time delays between queued presses. (default: 0) + * @param amount unimplemented for now; in the future it will be used for + * specifying magnitude of analog key press events + * @param axis + */ + public void sendButton(short code, boolean repeat, boolean down, boolean queue, short amount, byte axis) throws IOException + { + PacketBUTTON p = new PacketBUTTON(code, repeat, down, queue, amount, axis); + p.send(hostAddress, hostPort); + } + + /** + * Sends a Button event + * @param map_name a combination of map_name and button_name refers to a + * mapping in the user's Keymap.xml or Lircmap.xml. + * map_name can be one of the following: + * <ul> + * <li>"KB" => standard keyboard map ( <keyboard> section )</li> + * <li>"XG" => xbox gamepad map ( <gamepad> section )</li> + * <li>"R1" => xbox remote map ( <remote> section )</li> + * <li>"R2" => xbox universal remote map ( <universalremote> section )</li> + * <li>"LI:devicename" => LIRC remote map where 'devicename' is the + * actual device's name</li></ul> + * @param button_name a button name defined in the map specified in map_name. + * For example, if map_name is "KB" refering to the <keyboard> section in Keymap.xml + * then, valid button_names include "printscreen", "minus", "x", etc. + * @param repeat this key press should repeat until released (default: 1) + * Note that queued pressed cannot repeat. + * @param down if this is 1, it implies a press event, 0 implies a release + * event. (default: 1) + * @param queue a queued key press means that the button event is + * executed just once after which the next key press is processed. + * It can be used for macros. Currently there is no support for + * time delays between queued presses. (default: 0) + * @param amount unimplemented for now; in the future it will be used for + * specifying magnitude of analog key press events + * @param axis + */ + public void sendButton(String map_name, String button_name, boolean repeat, boolean down, boolean queue, short amount, byte axis) throws IOException + { + PacketBUTTON p = new PacketBUTTON(map_name, button_name, repeat, down, queue, amount, axis); + p.send(hostAddress, hostPort); + } + + /** + * Sets the mouse position in XBMC + * @param x horitontal position ranging from 0 to 65535 + * @param y vertical position ranging from 0 to 65535 + */ + public void sendMouse(int x, int y) throws IOException + { + PacketMOUSE p = new PacketMOUSE(x, y); + p.send(hostAddress, hostPort); + } + + /** + * Sends a ping to the XBMC EventServer + * @throws IOException + */ + public void ping() throws IOException + { + PacketPING p = new PacketPING(); + p.send(hostAddress, hostPort); + } + + /** + * Tells XBMC to log the message to xbmc.log with the loglevel as specified. + * @param loglevel the loglevel, follows XBMC standard. + * <ul> + * <li>0 = DEBUG</li> + * <li>1 = INFO</li> + * <li>2 = NOTICE</li> + * <li>3 = WARNING</li> + * <li>4 = ERROR</li> + * <li>5 = SEVERE</li> + * </ul> + * @param logmessage the message to log + */ + public void sendLog(byte loglevel, String logmessage) throws IOException + { + PacketLOG p = new PacketLOG(loglevel, logmessage); + p.send(hostAddress, hostPort); + } + + /** + * Tells XBMC to do the action specified, based on the type it knows were it needs to be sent. + * @param actionmessage Actionmessage (as in scripting/skinning) + */ + public void sendAction(String actionmessage) throws IOException + { + PacketACTION p = new PacketACTION(actionmessage); + p.send(hostAddress, hostPort); + } + + /** + * Implements a PingThread which tells XBMC EventServer that the Client is alive (this should + * be done at least every 60 seconds! + * @author Stefan Agner + * + */ + class PingThread extends Thread + { + private InetAddress hostAddress; + private int hostPort; + private int sleepTime; + private boolean giveup = false; + + public PingThread(InetAddress hostAddress, int hostPort, int sleepTime) + { + super("XBMC EventClient Ping-Thread"); + this.hostAddress = hostAddress; + this.hostPort = hostPort; + this.sleepTime = sleepTime; + } + + public void giveup() + { + giveup = true; + } + + public void run() + { + while(!giveup) + { + try { + PacketPING p = new PacketPING(); + p.send(hostAddress, hostPort); + } catch (IOException e) { + + e.printStackTrace(); + } + + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + } + } + } + } +} diff --git a/tools/EventClients/lib/python/__init__.py b/tools/EventClients/lib/python/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tools/EventClients/lib/python/__init__.py diff --git a/tools/EventClients/lib/python/bt/__init__.py b/tools/EventClients/lib/python/bt/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tools/EventClients/lib/python/bt/__init__.py diff --git a/tools/EventClients/lib/python/bt/bt.py b/tools/EventClients/lib/python/bt/bt.py new file mode 100644 index 0000000000..de4fd1bb65 --- /dev/null +++ b/tools/EventClients/lib/python/bt/bt.py @@ -0,0 +1,65 @@ +BLUEZ=0 + +try: + import bluetooth + BLUEZ=1 +except: + try: + import lightblue + except: + print "ERROR: You need to have either LightBlue or PyBluez installed\n"\ + " in order to use this program." + print "- PyBluez (Linux / Windows XP) http://org.csail.mit.edu/pybluez/" + print "- LightBlue (Mac OS X / Linux) http://lightblue.sourceforge.net/" + exit() + +def bt_create_socket(): + if BLUEZ: + sock = bluetooth.BluetoothSocket(bluetooth.L2CAP) + else: + sock = lightblue.socket(lightblue.L2CAP) + return sock + +def bt_create_rfcomm_socket(): + if BLUEZ: + sock = bluetooth.BluetoothSocket( bluetooth.RFCOMM ) + sock.bind(("",bluetooth.PORT_ANY)) + else: + sock = lightblue.socket(lightblue.RFCOMM) + sock.bind(("",0)) + return sock + +def bt_discover_devices(): + if BLUEZ: + nearby = bluetooth.discover_devices() + else: + nearby = lightblue.finddevices() + return nearby + +def bt_lookup_name(bdaddr): + if BLUEZ: + bname = bluetooth.lookup_name( bdaddr ) + else: + bname = bdaddr[1] + return bname + +def bt_lookup_addr(bdaddr): + if BLUEZ: + return bdaddr + else: + return bdaddr[0] + +def bt_advertise(name, uuid, socket): + if BLUEZ: + bluetooth.advertise_service( socket, name, + service_id = uuid, + service_classes = [ uuid, bluetooth.SERIAL_PORT_CLASS ], + profiles = [ bluetooth.SERIAL_PORT_PROFILE ] ) + else: + lightblue.advertise(name, socket, lightblue.RFCOMM) + +def bt_stop_advertising(socket): + if BLUEZ: + stop_advertising(socket) + else: + lightblue.stopadvertise(socket) diff --git a/tools/EventClients/lib/python/bt/hid.py b/tools/EventClients/lib/python/bt/hid.py new file mode 100644 index 0000000000..7017185dc4 --- /dev/null +++ b/tools/EventClients/lib/python/bt/hid.py @@ -0,0 +1,54 @@ +from bluetooth import * + +class HID: + def __init__(self, bdaddress=None): + self.cport = 0x11 # HID's control PSM + self.iport = 0x13 # HID' interrupt PSM + self.backlog = 1 + + self.address = "" + if bdaddress: + self.address = bdaddress + + # create the HID control socket + self.csock = BluetoothSocket( L2CAP ) + self.csock.bind((self.address, self.cport)) + set_l2cap_mtu(self.csock, 64) + self.csock.settimeout(2) + self.csock.listen(self.backlog) + + # create the HID interrupt socket + self.isock = BluetoothSocket( L2CAP ) + self.isock.bind((self.address, self.iport)) + set_l2cap_mtu(self.isock, 64) + self.isock.settimeout(2) + self.isock.listen(self.backlog) + + self.connected = False + + + def listen(self): + try: + (self.client_csock, self.caddress) = self.csock.accept() + print "Accepted Control connection from %s" % self.caddress[0] + (self.client_isock, self.iaddress) = self.isock.accept() + print "Accepted Interrupt connection from %s" % self.iaddress[0] + self.connected = True + return True + except Exception, e: + self.connected = False + return False + + + def get_control_socket(self): + if self.connected: + return (self.client_csock, self.caddress) + else: + return None + + + def get_interrupt_socket(self): + if self.connected: + return (self.client_isock, self.iaddress) + else: + return None diff --git a/tools/EventClients/lib/python/ps3/__init__.py b/tools/EventClients/lib/python/ps3/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tools/EventClients/lib/python/ps3/__init__.py diff --git a/tools/EventClients/lib/python/ps3/keymaps.py b/tools/EventClients/lib/python/ps3/keymaps.py new file mode 100644 index 0000000000..abe7dd6427 --- /dev/null +++ b/tools/EventClients/lib/python/ps3/keymaps.py @@ -0,0 +1,118 @@ +# PS3 Remote and Controller Keymaps + +keymap_remote = { + "16": 'power' ,#EJECT + "64": None ,#AUDIO + "65": None ,#ANGLE + "63": None ,#SUBTITLE + "0f": None ,#CLEAR + "28": None ,#TIME + + "00": 'one' ,#1 + "01": 'two' ,#2 + "02": 'three' ,#3 + "03": 'four' ,#4 + "04": 'five' ,#5 + "05": 'six' ,#6 + "06": 'seven' ,#7 + "07": 'eight' ,#8 + "08": 'nine' ,#9 + "09": 'zero' ,#0 + + "81": 'mytv' ,#RED + "82": 'mymusic' ,#GREEN + "80": 'mypictures' ,#BLUE + "83": 'myvideo' ,#YELLOW + + "70": 'display' ,#DISPLAY + "1a": None ,#TOP MENU + "40": 'menu' ,#POP UP/MENU + "0e": None ,#RETURN + + "5c": 'menu' ,#OPTIONS/TRIANGLE + "5d": 'back' ,#BACK/CIRCLE + "5e": 'info' ,#X + "5f": 'title' ,#VIEW/SQUARE + + "54": 'up' ,#UP + "55": 'right' ,#RIGHT + "56": 'down' ,#DOWN + "57": 'left' ,#LEFT + "0b": 'select' ,#ENTER + + "5a": 'volumeplus' ,#L1 + "58": 'volumeminus' ,#L2 + "51": 'Mute' ,#L3 + "5b": 'pageplus' ,#R1 + "59": 'pageminus' ,#R2 + "52": None ,#R3 + + "43": None ,#PLAYSTATION + "50": None ,#SELECT + "53": None ,#START + + "33": 'reverse' ,#<-SCAN + "34": 'forward' ,# SCAN-> + "30": 'skipminus' ,#PREV + "31": 'skipplus' ,#NEXT + "60": None ,#<-SLOW/STEP + "61": None ,# SLOW/STEP-> + "32": 'play' ,#PLAY + "38": 'stop' ,#STOP + "39": 'pause' ,#PAUSE + } + + +SX_SQUARE = 32768 +SX_X = 16384 +SX_CIRCLE = 8192 +SX_TRIANGLE = 4096 +SX_R1 = 2048 +SX_R2 = 512 +SX_R3 = 4 +SX_L1 = 1024 +SX_L2 = 256 +SX_L3 = 2 +SX_DUP = 16 +SX_DDOWN = 64 +SX_DLEFT = 128 +SX_DRIGHT = 32 +SX_SELECT = 1 +SX_START = 8 + +SX_LSTICK_X = 0 +SX_LSTICK_Y = 1 +SX_RSTICK_X = 2 +SX_RSTICK_Y = 3 + +# (map, key, amount index, axis) +keymap_sixaxis = { + SX_X : ('XG', 'A', 0, 0), + SX_CIRCLE : ('XG', 'B', 0, 0), + SX_SQUARE : ('XG', 'X', 0, 0), + SX_TRIANGLE : ('XG', 'Y', 0, 0), + + SX_DUP : ('XG', 'dpadup', 0, 0), + SX_DDOWN : ('XG', 'dpaddown', 0, 0), + SX_DLEFT : ('XG', 'dpadleft', 0, 0), + SX_DRIGHT : ('XG', 'dpadright', 0, 0), + + SX_START : ('XG', 'start', 0, 0), + SX_SELECT : ('XG', 'back', 0, 0), + + SX_R1 : ('XG', 'white', 0, 0), + SX_R2 : ('XG', 'rightanalogtrigger', 6, 1), + SX_L2 : ('XG', 'leftanalogtrigger', 5, 1), + SX_L1 : ('XG', 'black', 0, 0), + + SX_L3 : ('XG', 'leftthumbbutton', 0, 0), + SX_R3 : ('XG', 'rightthumbbutton', 0, 0), +} + +# (data index, left map, left action, right map, right action) +axismap_sixaxis = { + SX_LSTICK_X : ('XG', 'leftthumbstickleft' , 'leftthumbstickright'), + SX_LSTICK_Y : ('XG', 'leftthumbstickup' , 'leftthumbstickdown'), + SX_RSTICK_X : ('XG', 'rightthumbstickleft', 'rightthumbstickright'), + SX_RSTICK_Y : ('XG', 'rightthumbstickup' , 'rightthumbstickdown'), +} diff --git a/tools/EventClients/lib/python/ps3/sixaxis.py b/tools/EventClients/lib/python/ps3/sixaxis.py new file mode 100644 index 0000000000..15014b8ea0 --- /dev/null +++ b/tools/EventClients/lib/python/ps3/sixaxis.py @@ -0,0 +1,206 @@ +#!/usr/bin/python + +import time +import sys +import struct +import math +import binascii +from bluetooth import set_l2cap_mtu +from keymaps import keymap_sixaxis +from keymaps import axismap_sixaxis + +xval = 0 +yval = 0 +num_samples = 16 +sumx = [0] * num_samples +sumy = [0] * num_samples +sumr = [0] * num_samples +axis_amount = [0, 0, 0, 0] + +def normalize(val): + upperlimit = 65281 + lowerlimit = 2 + val_range = upperlimit - lowerlimit + offset = 10000 + + val = (val + val_range / 2) % val_range + upperlimit -= offset + lowerlimit += offset + + if val < lowerlimit: + val = lowerlimit + if val > upperlimit: + val = upperlimit + + val = ((float(val) - offset) / (float(upperlimit) - + lowerlimit)) * 65535.0 + if val <= 0: + val = 1 + return val + +def normalize_axis(val, deadzone): + + val = float(val) - 127.5 + val = val / 127.5 + + if abs(val) < deadzone: + return 0.0 + + if val > 0.0: + val = (val - deadzone) / (1.0 - deadzone) + else: + val = (val + deadzone) / (1.0 - deadzone) + + return 65536.0 * val + +def normalize_angle(val, valrange): + valrange *= 2 + + val = val / valrange + if val > 1.0: + val = 1.0 + if val < -1.0: + val = -1.0 + return (val + 0.5) * 65535.0 + +def initialize(control_sock, interrupt_sock): + # sixaxis needs this to enable it + # 0x53 => HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE + control_sock.send("\x53\xf4\x42\x03\x00\x00") + time.sleep(0.25) + data = control_sock.recv(1) + + set_l2cap_mtu(control_sock, 64) + set_l2cap_mtu(interrupt_sock, 64) + + # This command will turn on the gyro and set the leds + # I wonder if turning on the gyro makes it draw more current?? + # it's probably a flag somewhere in the following command + + # HID Command: HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUTPUT + # HID Report:1 + bytes = [0x52, 0x1] + bytes.extend([0x00, 0x00, 0x00]) + bytes.extend([0xFF, 0x72]) + bytes.extend([0x00, 0x00, 0x00, 0x00]) + bytes.extend([0x02]) # 0x02 LED1, 0x04 LED2 ... 0x10 LED4 + # The following sections should set the blink frequncy of + # the leds on the controller, but i've not figured out how. + # These values where suggusted in a mailing list, but no explination + # for how they should be combined to the 5 bytes per led + #0xFF = 0.5Hz + #0x80 = 1Hz + #0x40 = 2Hz + bytes.extend([0xFF, 0x00, 0x01, 0x00, 0x01]) #LED4 [0xff, 0xff, 0x10, 0x10, 0x10] + bytes.extend([0xFF, 0x00, 0x01, 0x00, 0x01]) #LED3 [0xff, 0x40, 0x08, 0x10, 0x10] + bytes.extend([0xFF, 0x00, 0x01, 0x00, 0x01]) #LED2 [0xff, 0x00, 0x10, 0x30, 0x30] + bytes.extend([0xFF, 0x00, 0x01, 0x00, 0x01]) #LED1 [0xff, 0x00, 0x10, 0x40, 0x10] + bytes.extend([0x00, 0x00, 0x00, 0x00, 0x00]) + bytes.extend([0x00, 0x00, 0x00, 0x00, 0x00]) + + control_sock.send(struct.pack("42B", *bytes)) + time.sleep(0.25) + data = control_sock.recv(1) + + + return data + + +def read_input(isock): + return isock.recv(50) + + +def process_input(data, xbmc=None, mouse_enabled=0): + if len(data) < 3: + return (0, 0, 0) + + # make sure this is the correct report + if struct.unpack("BBB", data[0:3]) != (0xa1, 0x01, 0x00): + return (0, 0, 0) + + if len(data) >= 48: + v1 = struct.unpack("h", data[42:44]) + v2 = struct.unpack("h", data[44:46]) + v3 = struct.unpack("h", data[46:48]) + else: + v1 = [0,0] + v2 = [0,0] + v3 = [0,0] + + if len(data) >= 50: + v4 = struct.unpack("h", data[48:50]) + else: + v4 = [0,0] + + ax = float(v1[0]) + ay = float(v2[0]) + az = float(v3[0]) + rz = float(v4[0]) + at = math.sqrt(ax*ax + ay*ay + az*az) + + bflags = struct.unpack("H", data[3:5])[0] + psflags = struct.unpack("B", data[5:6])[0] + if len(data) > 27: + pressure = struct.unpack("BBBBBBBBBBBB", data[15:27]) + else: + pressure = [0,0,0,0,0,0,0,0,0,0,0,0,0] + + roll = -math.atan2(ax, math.sqrt(ay*ay + az*az)) + pitch = math.atan2(ay, math.sqrt(ax*ax + az*az)) + + pitch -= math.radians(20); + + xpos = normalize_angle(roll, math.radians(30)) + ypos = normalize_angle(pitch, math.radians(30)) + + # update our sliding window array + sumx.insert(0, xpos) + sumy.insert(0, ypos) + sumx.pop(num_samples) + sumy.pop(num_samples) + + # reset average + xval = 0 + yval = 0 + + # do a sliding window average to remove high frequency + # noise in accelerometer sampling + for i in range(0, num_samples): + xval += sumx[i] + yval += sumy[i] + + axis = struct.unpack("BBBB", data[7:11]) + if xbmc: + for i in range(4): + config = axismap_sixaxis[i] + axis_amount[i] = send_singleaxis(xbmc, axis[i], axis_amount[i], config[0], config[1], config[2]) + + # send the mouse position to xbmc + if mouse_enabled == 1: + xbmc.send_mouse_position(xval/num_samples, yval/num_samples) + + return (bflags, psflags, pressure) + +def send_singleaxis(xbmc, axis, last_amount, mapname, action_min, action_pos): + amount = normalize_axis(axis, 0.30) + if last_amount < 0: + last_action = action_min + elif last_amount > 0: + last_action = action_pos + else: + last_action = None + + if amount < 0: + new_action = action_min + elif amount > 0: + new_action = action_pos + else: + new_action = None + + if last_action and new_action != last_action: + xbmc.send_button_state(map=mapname, button=last_action, amount=0, axis=1) + + if new_action and amount != last_amount: + xbmc.send_button_state(map=mapname, button=new_action, amount=abs(amount), axis=1) + + return amount diff --git a/tools/EventClients/lib/python/xbmcclient.py b/tools/EventClients/lib/python/xbmcclient.py new file mode 100644 index 0000000000..d62f2b9ee3 --- /dev/null +++ b/tools/EventClients/lib/python/xbmcclient.py @@ -0,0 +1,621 @@ +#!/usr/bin/python + +""" +Implementation of XBMC's UDP based input system. + +A set of classes that abstract the various packets that the event server +currently supports. In addition, there's also a class, XBMCClient, that +provides functions that sends the various packets. Use XBMCClient if you +don't need complete control over packet structure. + +The basic workflow involves: + +1. Send a HELO packet +2. Send x number of valid packets +3. Send a BYE packet + +IMPORTANT NOTE ABOUT TIMEOUTS: +A client is considered to be timed out if XBMC doesn't received a packet +at least once every 60 seconds. To "ping" XBMC with an empty packet use +PacketPING or XBMCClient.ping(). See the documentation for details. +""" + +__author__ = "d4rk@xbmc.org" +__version__ = "0.0.3" + +from struct import pack +from socket import * +import time + +MAX_PACKET_SIZE = 1024 +HEADER_SIZE = 32 +MAX_PAYLOAD_SIZE = MAX_PACKET_SIZE - HEADER_SIZE +UNIQUE_IDENTIFICATION = (int)(time.time()) + +PT_HELO = 0x01 +PT_BYE = 0x02 +PT_BUTTON = 0x03 +PT_MOUSE = 0x04 +PT_PING = 0x05 +PT_BROADCAST = 0x06 +PT_NOTIFICATION = 0x07 +PT_BLOB = 0x08 +PT_LOG = 0x09 +PT_ACTION = 0x0A +PT_DEBUG = 0xFF + +ICON_NONE = 0x00 +ICON_JPEG = 0x01 +ICON_PNG = 0x02 +ICON_GIF = 0x03 + +BT_USE_NAME = 0x01 +BT_DOWN = 0x02 +BT_UP = 0x04 +BT_USE_AMOUNT = 0x08 +BT_QUEUE = 0x10 +BT_NO_REPEAT = 0x20 +BT_VKEY = 0x40 +BT_AXIS = 0x80 +BT_AXISSINGLE = 0x100 + +MS_ABSOLUTE = 0x01 + +LOGDEBUG = 0x00 +LOGINFO = 0x01 +LOGNOTICE = 0x02 +LOGWARNING = 0x03 +LOGERROR = 0x04 +LOGSEVERE = 0x05 +LOGFATAL = 0x06 +LOGNONE = 0x07 + +ACTION_EXECBUILTIN = 0x01 +ACTION_BUTTON = 0x02 + +###################################################################### +# Helper Functions +###################################################################### + +def format_string(msg): + """ """ + return msg + "\0" + +def format_uint32(num): + """ """ + return pack ("!I", num) + +def format_uint16(num): + """ """ + if num<0: + num = 0 + elif num>65535: + num = 65535 + return pack ("!H", num) + + +###################################################################### +# Packet Classes +###################################################################### + +class Packet: + """Base class that implements a single event packet. + + - Generic packet structure (maximum 1024 bytes per packet) + - Header is 32 bytes long, so 992 bytes available for payload + - large payloads can be split into multiple packets using H4 and H5 + H5 should contain total no. of packets in such a case + - H6 contains length of P1, which is limited to 992 bytes + - if H5 is 0 or 1, then H4 will be ignored (single packet msg) + - H7 must be set to zeros for now + + ----------------------------- + | -H1 Signature ("XBMC") | - 4 x CHAR 4B + | -H2 Version (eg. 2.0) | - 2 x UNSIGNED CHAR 2B + | -H3 PacketType | - 1 x UNSIGNED SHORT 2B + | -H4 Sequence number | - 1 x UNSIGNED LONG 4B + | -H5 No. of packets in msg | - 1 x UNSIGNED LONG 4B + | -H7 Client's unique token | - 1 x UNSIGNED LONG 4B + | -H8 Reserved | - 10 x UNSIGNED CHAR 10B + |---------------------------| + | -P1 payload | - + ----------------------------- + """ + def __init__(self): + self.sig = "XBMC" + self.minver = 0 + self.majver = 2 + self.seq = 1 + self.maxseq = 1 + self.payloadsize = 0 + self.uid = UNIQUE_IDENTIFICATION + self.reserved = "\0" * 10 + self.payload = "" + return + + + def append_payload(self, blob): + """Append to existing payload + + Arguments: + blob -- binary data to append to the current payload + """ + self.set_payload(self.payload + blob) + + + def set_payload(self, payload): + """Set the payload for this packet + + Arguments: + payload -- binary data that contains the payload + """ + self.payload = payload + self.payloadsize = len(self.payload) + self.maxseq = int((self.payloadsize + (MAX_PAYLOAD_SIZE - 1)) / MAX_PAYLOAD_SIZE) + + + def num_packets(self): + """ Return the number of packets required for payload """ + return self.maxseq + + def get_header(self, packettype=-1, seq=1, maxseq=1, payload_size=0): + """Construct a header and return as string + + Keyword arguments: + packettype -- valid packet types are PT_HELO, PT_BYE, PT_BUTTON, + PT_MOUSE, PT_PING, PT_BORADCAST, PT_NOTIFICATION, + PT_BLOB, PT_DEBUG + seq -- the sequence of this packet for a multi packet message + (default 1) + maxseq -- the total number of packets for a multi packet message + (default 1) + payload_size -- the size of the payload of this packet (default 0) + """ + if packettype < 0: + packettype = self.packettype + header = self.sig + header += chr(self.majver) + header += chr(self.minver) + header += format_uint16(packettype) + header += format_uint32(seq) + header += format_uint32(maxseq) + header += format_uint16(payload_size) + header += format_uint32(self.uid) + header += self.reserved + return header + + def get_payload_size(self, seq): + """Returns the calculated payload size for the particular packet + + Arguments: + seq -- the sequence number + """ + if self.maxseq == 1: + return self.payloadsize + + if seq < self.maxseq: + return MAX_PAYLOAD_SIZE + + return self.payloadsize % MAX_PAYLOAD_SIZE + + + def get_udp_message(self, packetnum=1): + """Construct the UDP message for the specified packetnum and return + as string + + Keyword arguments: + packetnum -- the packet no. for which to construct the message + (default 1) + """ + if packetnum > self.num_packets() or packetnum < 1: + return "" + header = "" + if packetnum==1: + header = self.get_header(self.packettype, packetnum, self.maxseq, + self.get_payload_size(packetnum)) + else: + header = self.get_header(PT_BLOB, packetnum, self.maxseq, + self.get_payload_size(packetnum)) + + payload = self.payload[ (packetnum-1) * MAX_PAYLOAD_SIZE : + (packetnum-1) * MAX_PAYLOAD_SIZE+ + self.get_payload_size(packetnum) ] + return header + payload + + def send(self, sock, addr, uid=UNIQUE_IDENTIFICATION): + """Send the entire message to the specified socket and address. + + Arguments: + sock -- datagram socket object (socket.socket) + addr -- address, port pair (eg: ("127.0.0.1", 9777) ) + uid -- unique identification + """ + self.uid = uid + for a in range ( 0, self.num_packets() ): + try: + sock.sendto(self.get_udp_message(a+1), addr) + return True + except: + return False + + +class PacketHELO (Packet): + """A HELO packet + + A HELO packet establishes a valid connection to XBMC. It is the + first packet that should be sent. + """ + def __init__(self, devicename=None, icon_type=ICON_NONE, icon_file=None): + """ + Keyword arguments: + devicename -- the string that identifies the client + icon_type -- one of ICON_NONE, ICON_JPEG, ICON_PNG, ICON_GIF + icon_file -- location of icon file with respect to current working + directory if icon_type is not ICON_NONE + """ + Packet.__init__(self) + self.packettype = PT_HELO + self.icontype = icon_type + self.set_payload ( format_string(devicename)[0:128] ) + self.append_payload( chr (icon_type) ) + self.append_payload( format_uint16 (0) ) # port no + self.append_payload( format_uint32 (0) ) # reserved1 + self.append_payload( format_uint32 (0) ) # reserved2 + if icon_type != ICON_NONE and icon_file: + self.append_payload( file(icon_file).read() ) + +class PacketNOTIFICATION (Packet): + """A NOTIFICATION packet + + This packet displays a notification window in XBMC. It can contain + a caption, a message and an icon. + """ + def __init__(self, title, message, icon_type=ICON_NONE, icon_file=None): + """ + Keyword arguments: + title -- the notification caption / title + message -- the main text of the notification + icon_type -- one of ICON_NONE, ICON_JPEG, ICON_PNG, ICON_GIF + icon_file -- location of icon file with respect to current working + directory if icon_type is not ICON_NONE + """ + Packet.__init__(self) + self.packettype = PT_NOTIFICATION + self.title = title + self.message = message + self.set_payload ( format_string(title) ) + self.append_payload( format_string(message) ) + self.append_payload( chr (icon_type) ) + self.append_payload( format_uint32 (0) ) # reserved + if icon_type != ICON_NONE and icon_file: + self.append_payload( file(icon_file).read() ) + +class PacketBUTTON (Packet): + """A BUTTON packet + + A button packet send a key press or release event to XBMC + """ + def __init__(self, code=0, repeat=1, down=1, queue=0, + map_name="", button_name="", amount=0, axis=0): + """ + Keyword arguments: + code -- raw button code (default: 0) + repeat -- this key press should repeat until released (default: 1) + Note that queued pressed cannot repeat. + down -- if this is 1, it implies a press event, 0 implies a release + event. (default: 1) + queue -- a queued key press means that the button event is + executed just once after which the next key press is + processed. It can be used for macros. Currently there + is no support for time delays between queued presses. + (default: 0) + map_name -- a combination of map_name and button_name refers to a + mapping in the user's Keymap.xml or Lircmap.xml. + map_name can be one of the following: + "KB" => standard keyboard map ( <keyboard> section ) + "XG" => xbox gamepad map ( <gamepad> section ) + "R1" => xbox remote map ( <remote> section ) + "R2" => xbox universal remote map ( <universalremote> + section ) + "LI:devicename" => LIRC remote map where 'devicename' is the + actual device's name + button_name -- a button name defined in the map specified in map_name. + For example, if map_name is "KB" refering to the + <keyboard> section in Keymap.xml then, valid + button_names include "printscreen", "minus", "x", etc. + amount -- unimplemented for now; in the future it will be used for + specifying magnitude of analog key press events + """ + Packet.__init__(self) + self.flags = 0 + self.packettype = PT_BUTTON + if type (code ) == str: + code = ord(code) + + # assign code only if we don't have a map and button name + if not (map_name and button_name): + self.code = code + else: + self.flags |= BT_USE_NAME + self.code = 0 + if (amount != None): + self.flags |= BT_USE_AMOUNT + self.amount = int(amount) + else: + self.amount = 0 + + if down: + self.flags |= BT_DOWN + else: + self.flags |= BT_UP + if not repeat: + self.flags |= BT_NO_REPEAT + if queue: + self.flags |= BT_QUEUE + if axis == 1: + self.flags |= BT_AXISSINGLE + elif axis == 2: + self.flags |= BT_AXIS + + self.set_payload ( format_uint16(self.code) ) + self.append_payload( format_uint16(self.flags) ) + self.append_payload( format_uint16(self.amount) ) + self.append_payload( format_string (map_name) ) + self.append_payload( format_string (button_name) ) + +class PacketMOUSE (Packet): + """A MOUSE packet + + A MOUSE packets sets the mouse position in XBMC + """ + def __init__(self, x, y): + """ + Arguments: + x -- horitontal position ranging from 0 to 65535 + y -- vertical position ranging from 0 to 65535 + + The range will be mapped to the screen width and height in XBMC + """ + Packet.__init__(self) + self.packettype = PT_MOUSE + self.flags = MS_ABSOLUTE + self.append_payload( chr (self.flags) ) + self.append_payload( format_uint16(x) ) + self.append_payload( format_uint16(y) ) + +class PacketBYE (Packet): + """A BYE packet + + A BYE packet terminates the connection to XBMC. + """ + def __init__(self): + Packet.__init__(self) + self.packettype = PT_BYE + + +class PacketPING (Packet): + """A PING packet + + A PING packet tells XBMC that the client is still alive. All valid + packets act as ping (not just this one). A client needs to ping + XBMC at least once in 60 seconds or it will time out. + """ + def __init__(self): + Packet.__init__(self) + self.packettype = PT_PING + +class PacketLOG (Packet): + """A LOG packet + + A LOG packet tells XBMC to log the message to xbmc.log with the loglevel as specified. + """ + def __init__(self, loglevel=0, logmessage="", autoprint=True): + """ + Keyword arguments: + loglevel -- the loglevel, follows XBMC standard. + logmessage -- the message to log + autoprint -- if the logmessage should automaticly be printed to stdout + """ + Packet.__init__(self) + self.packettype = PT_LOG + self.append_payload( chr (loglevel) ) + self.append_payload( format_string(logmessage) ) + if (autoprint): + print logmessage + +class PacketACTION (Packet): + """An ACTION packet + + An ACTION packet tells XBMC to do the action specified, based on the type it knows were it needs to be sent. + The idea is that this will be as in scripting/skining and keymapping, just triggered from afar. + """ + def __init__(self, actionmessage="", actiontype=ACTION_EXECBUILTIN): + """ + Keyword arguments: + loglevel -- the loglevel, follows XBMC standard. + logmessage -- the message to log + autoprint -- if the logmessage should automaticly be printed to stdout + """ + Packet.__init__(self) + self.packettype = PT_ACTION + self.append_payload( chr (actiontype) ) + self.append_payload( format_string(actionmessage) ) + +###################################################################### +# XBMC Client Class +###################################################################### + +class XBMCClient: + """An XBMC event client""" + + def __init__(self, name ="", icon_file=None, broadcast=False, uid=UNIQUE_IDENTIFICATION, + ip="127.0.0.1"): + """ + Keyword arguments: + name -- Name of the client + icon_file -- location of an icon file, if any (png, jpg or gif) + uid -- unique identification + """ + self.name = str(name) + self.icon_file = icon_file + self.icon_type = self._get_icon_type(icon_file) + self.ip = ip + self.port = 9777 + self.sock = socket(AF_INET,SOCK_DGRAM) + if broadcast: + self.sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) + self.uid = uid + + + def connect(self, ip=None, port=None): + """Initialize connection to XBMC + ip -- IP Address of XBMC + port -- port that the event server on XBMC is listening on + """ + if ip: + self.ip = ip + if port: + self.port = int(port) + self.addr = (self.ip, self.port) + packet = PacketHELO(self.name, self.icon_type, self.icon_file) + return packet.send(self.sock, self.addr, self.uid) + + + def close(self): + """Close the current connection""" + packet = PacketBYE() + return packet.send(self.sock, self.addr, self.uid) + + + def ping(self): + """Send a PING packet""" + packet = PacketPING() + return packet.send(self.sock, self.addr, self.uid) + + + def send_notification(self, title="", message="", icon_file=None): + """Send a notification to the connected XBMC + Keyword Arguments: + title -- The title/heading for the notifcation + message -- The message to be displayed + icon_file -- location of an icon file, if any (png, jpg, gif) + """ + self.connect() + packet = PacketNOTIFICATION(title, message, + self._get_icon_type(icon_file), + icon_file) + return packet.send(self.sock, self.addr, self.uid) + + + def send_keyboard_button(self, button=None): + """Send a keyboard event to XBMC + Keyword Arguments: + button -- name of the keyboard button to send (same as in Keymap.xml) + """ + if not button: + return + return self.send_button(map="KB", button=button) + + + def send_remote_button(self, button=None): + """Send a remote control event to XBMC + Keyword Arguments: + button -- name of the remote control button to send (same as in Keymap.xml) + """ + if not button: + return + return self.send_button(map="R1", button=button) + + + def release_button(self): + """Release all buttons""" + packet = PacketBUTTON(code=0x01, down=0) + return packet.send(self.sock, self.addr, self.uid) + + + def send_button(self, map="", button="", amount=0): + """Send a button event to XBMC + Keyword arguments: + map -- a combination of map_name and button_name refers to a + mapping in the user's Keymap.xml or Lircmap.xml. + map_name can be one of the following: + "KB" => standard keyboard map ( <keyboard> section ) + "XG" => xbox gamepad map ( <gamepad> section ) + "R1" => xbox remote map ( <remote> section ) + "R2" => xbox universal remote map ( <universalremote> + section ) + "LI:devicename" => LIRC remote map where 'devicename' is the + actual device's name + button -- a button name defined in the map specified in map, above. + For example, if map is "KB" refering to the <keyboard> + section in Keymap.xml then, valid buttons include + "printscreen", "minus", "x", etc. + """ + packet = PacketBUTTON(map_name=str(map), button_name=str(button), amount=amount) + return packet.send(self.sock, self.addr, self.uid) + + def send_button_state(self, map="", button="", amount=0, down=0, axis=0): + """Send a button event to XBMC + Keyword arguments: + map -- a combination of map_name and button_name refers to a + mapping in the user's Keymap.xml or Lircmap.xml. + map_name can be one of the following: + "KB" => standard keyboard map ( <keyboard> section ) + "XG" => xbox gamepad map ( <gamepad> section ) + "R1" => xbox remote map ( <remote> section ) + "R2" => xbox universal remote map ( <universalremote> + section ) + "LI:devicename" => LIRC remote map where 'devicename' is the + actual device's name + button -- a button name defined in the map specified in map, above. + For example, if map is "KB" refering to the <keyboard> + section in Keymap.xml then, valid buttons include + "printscreen", "minus", "x", etc. + """ + if axis: + if amount == 0: + down = 0 + else: + down = 1 + + packet = PacketBUTTON(map_name=str(map), button_name=str(button), amount=amount, down=down, queue=1, axis=axis) + return packet.send(self.sock, self.addr, self.uid) + + def send_mouse_position(self, x=0, y=0): + """Send a mouse event to XBMC + Keywords Arguments: + x -- absolute x position of mouse ranging from 0 to 65535 + which maps to the entire screen width + y -- same a 'x' but relates to the screen height + """ + packet = PacketMOUSE(int(x), int(y)) + return packet.send(self.sock, self.addr, self.uid) + + def send_log(self, loglevel=0, logmessage="", autoprint=True): + """ + Keyword arguments: + loglevel -- the loglevel, follows XBMC standard. + logmessage -- the message to log + autoprint -- if the logmessage should automaticly be printed to stdout + """ + packet = PacketLOG(loglevel, logmessage) + return packet.send(self.sock, self.addr, self.uid) + + def send_action(self, actionmessage="", actiontype=ACTION_EXECBUILTIN): + """ + Keyword arguments: + actionmessage -- the ActionString + actiontype -- The ActionType the ActionString should be sent to. + """ + packet = PacketACTION(actionmessage, actiontype) + return packet.send(self.sock, self.addr, self.uid) + + def _get_icon_type(self, icon_file): + if icon_file: + if icon_file.lower()[-3:] == "png": + return ICON_PNG + elif icon_file.lower()[-3:] == "gif": + return ICON_GIF + elif icon_file.lower()[-3:] == "jpg": + return ICON_JPG + return ICON_NONE diff --git a/tools/EventClients/lib/python/zeroconf.py b/tools/EventClients/lib/python/zeroconf.py new file mode 100644 index 0000000000..9fc82f5909 --- /dev/null +++ b/tools/EventClients/lib/python/zeroconf.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python +""" +Simple wrapper around Avahi +""" + +__author__ = "d4rk@xbmc.org" +__version__ = "0.1" + +try: + import time + import dbus, gobject, avahi + from dbus import DBusException + from dbus.mainloop.glib import DBusGMainLoop +except Exception, e: + print "Zeroconf support disabled. To enable, install the following Python modules:" + print " dbus, gobject, avahi" + pass + +SERVICE_FOUND = 1 +SERVICE_LOST = 2 + +class Browser: + """ Simple Zeroconf Browser """ + + def __init__( self, service_types = {} ): + """ + service_types - dictionary of services => handlers + """ + self._stop = False + self.loop = DBusGMainLoop() + self.bus = dbus.SystemBus( mainloop=self.loop ) + self.server = dbus.Interface( self.bus.get_object( avahi.DBUS_NAME, '/' ), + 'org.freedesktop.Avahi.Server') + self.handlers = {} + + for type in service_types.keys(): + self.add_service( type, service_types[ type ] ) + + + def add_service( self, type, handler = None ): + """ + Add a service that the browser should watch for + """ + self.sbrowser = dbus.Interface( + self.bus.get_object( + avahi.DBUS_NAME, + self.server.ServiceBrowserNew( + avahi.IF_UNSPEC, + avahi.PROTO_UNSPEC, + type, + 'local', + dbus.UInt32(0) + ) + ), + avahi.DBUS_INTERFACE_SERVICE_BROWSER) + self.handlers[ type ] = handler + self.sbrowser.connect_to_signal("ItemNew", self._new_item_handler) + self.sbrowser.connect_to_signal("ItemRemove", self._remove_item_handler) + + + def run(self): + """ + Run the gobject event loop + """ + # Don't use loop.run() because Python's GIL will block all threads + loop = gobject.MainLoop() + context = loop.get_context() + while not self._stop: + if context.pending(): + context.iteration( True ) + else: + time.sleep(1) + + def stop(self): + """ + Stop the gobject event loop + """ + self._stop = True + + + def _new_item_handler(self, interface, protocol, name, stype, domain, flags): + if flags & avahi.LOOKUP_RESULT_LOCAL: + # local service, skip + pass + + self.server.ResolveService( + interface, + protocol, + name, + stype, + domain, + avahi.PROTO_UNSPEC, + dbus.UInt32(0), + reply_handler = self._service_resolved_handler, + error_handler = self._error_handler + ) + return + + + def _remove_item_handler(self, interface, protocol, name, stype, domain, flags): + if self.handlers[ stype ]: + # FIXME: more details needed here + try: + self.handlers[ stype ]( SERVICE_LOST, { 'type' : stype, 'name' : name } ) + except: + pass + + + def _service_resolved_handler( self, *args ): + service = {} + service['type'] = str( args[3] ) + service['name'] = str( args[2] ) + service['address'] = str( args[7] ) + service['hostname'] = str( args[5] ) + service['port'] = int( args[8] ) + + # if the service type has a handler call it + try: + if self.handlers[ args[3] ]: + self.handlers[ args[3] ]( SERVICE_FOUND, service ) + except: + pass + + + def _error_handler( self, *args ): + print 'ERROR: %s ' % str( args[0] ) + + +if __name__ == "__main__": + def service_handler( found, service ): + print "---------------------" + print ['Found Service', 'Lost Service'][found-1] + for key in service.keys(): + print key+" : "+str( service[key] ) + + browser = Browser( { + '_xbmc-events._udp' : service_handler, + '_xbmc-web._tcp' : service_handler + } ) + browser.run() + diff --git a/tools/Fake Episode Maker/main.py b/tools/Fake Episode Maker/main.py new file mode 100644 index 0000000000..7680fa9bfd --- /dev/null +++ b/tools/Fake Episode Maker/main.py @@ -0,0 +1,46 @@ +import urllib
+import os
+import openAnything
+from xml.dom import minidom
+
+def parseShow(seriesID, show_name):
+ safe_show_name = show_name.replace(":", "")
+ details_url = "http://thetvdb.com/api/EB49E8B9E78EBEE1/series/"+seriesID+"/all/en.xml"
+ details = openAnything.fetch(details_url)
+ details_xml = minidom.parseString(details['data'])
+ seasons = details_xml.getElementsByTagName("SeasonNumber")
+ episodes = details_xml.getElementsByTagName("EpisodeNumber")
+ # check to see if parent show path needs to be made
+ if not os.access(safe_show_name, os.F_OK):
+ os.makedirs(safe_show_name)
+ i = 0
+ for item in episodes:
+ season = seasons[i].firstChild.data
+ episode = item.firstChild.data
+ filename = safe_show_name+" S"+season+"E"+episode+".avi"
+ # seeif season path exists or not, and make it if not
+ if os.access(safe_show_name + "\\Season " + season, os.F_OK):
+ # just go ahead and create the file
+ file = open(safe_show_name + "\\Season " + season + "\\" + filename, "w")
+ file.close()
+ else:
+ os.makedirs(safe_show_name + "\\Season " + season)
+ file = open(safe_show_name + "\\Season " + season + "\\" + filename, "w")
+ file.close()
+ print "Creating %s" % filename
+ i = i + 1
+
+show_file = open("shows.txt")
+shows = show_file.read().split("\n")
+show_file.close()
+for item in shows:
+ show_url = "http://thetvdb.com/api/GetSeries.php?"+urllib.urlencode({"seriesname":item})
+ print "Building "+item+"..."
+ show_xml = openAnything.fetch(show_url)
+ xmldoc = minidom.parseString(show_xml['data'])
+ node = xmldoc.getElementsByTagName("seriesid")
+ if ("node" in dir()):
+ seriesID = node[0].firstChild.data
+ parseShow(seriesID, item)
+ else:
+ print "Could not find any data for "+show_name+" on TVDB.\nURL: "+show_url
diff --git a/tools/Fake Episode Maker/openAnything.py b/tools/Fake Episode Maker/openAnything.py new file mode 100644 index 0000000000..12abe74dd6 --- /dev/null +++ b/tools/Fake Episode Maker/openAnything.py @@ -0,0 +1,93 @@ +import urllib2, urlparse, gzip
+from StringIO import StringIO
+
+USER_AGENT = 'OpenAnything/1.0 +http://diveintopython.org/http_web_services/'
+
+class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
+ def http_error_301(self, req, fp, code, msg, headers):
+ result = urllib2.HTTPRedirectHandler.http_error_301(
+ self, req, fp, code, msg, headers)
+ result.status = code
+ return result
+
+ def http_error_302(self, req, fp, code, msg, headers):
+ result = urllib2.HTTPRedirectHandler.http_error_302(
+ self, req, fp, code, msg, headers)
+ result.status = code
+ return result
+
+class DefaultErrorHandler(urllib2.HTTPDefaultErrorHandler):
+ def http_error_default(self, req, fp, code, msg, headers):
+ result = urllib2.HTTPError(
+ req.get_full_url(), code, msg, headers, fp)
+ result.status = code
+ return result
+
+def openAnything(source, etag=None, lastmodified=None, agent=USER_AGENT):
+ '''URL, filename, or string --> stream
+
+ This function lets you define parsers that take any input source
+ (URL, pathname to local or network file, or actual data as a string)
+ and deal with it in a uniform manner. Returned object is guaranteed
+ to have all the basic stdio read methods (read, readline, readlines).
+ Just .close() the object when you're done with it.
+
+ If the etag argument is supplied, it will be used as the value of an
+ If-None-Match request header.
+
+ If the lastmodified argument is supplied, it must be a formatted
+ date/time string in GMT (as returned in the Last-Modified header of
+ a previous request). The formatted date/time will be used
+ as the value of an If-Modified-Since request header.
+
+ If the agent argument is supplied, it will be used as the value of a
+ User-Agent request header.
+ '''
+
+ if hasattr(source, 'read'):
+ return source
+
+ if source == '-':
+ return sys.stdin
+
+ if urlparse.urlparse(source)[0] == 'http':
+ # open URL with urllib2
+ request = urllib2.Request(source)
+ request.add_header('User-Agent', agent)
+ if etag:
+ request.add_header('If-None-Match', etag)
+ if lastmodified:
+ request.add_header('If-Modified-Since', lastmodified)
+ request.add_header('Accept-encoding', 'gzip')
+ opener = urllib2.build_opener(SmartRedirectHandler(), DefaultErrorHandler())
+ return opener.open(request)
+
+ # try to open with native open function (if source is a filename)
+ try:
+ return open(source)
+ except (IOError, OSError):
+ pass
+
+ # treat source as string
+ return StringIO(str(source))
+
+def fetch(source, etag=None, last_modified=None, agent=USER_AGENT):
+ '''Fetch data and metadata from a URL, file, stream, or string'''
+ result = {}
+ f = openAnything(source, etag, last_modified, agent)
+ result['data'] = f.read()
+ if hasattr(f, 'headers'):
+ # save ETag, if the server sent one
+ result['etag'] = f.headers.get('ETag')
+ # save Last-Modified header, if the server sent one
+ result['lastmodified'] = f.headers.get('Last-Modified')
+ if f.headers.get('content-encoding', '') == 'gzip':
+ # data came back gzip-compressed, decompress it
+ result['data'] = gzip.GzipFile(fileobj=StringIO(result['data'])).read()
+ if hasattr(f, 'url'):
+ result['url'] = f.url
+ result['status'] = 200
+ if hasattr(f, 'status'):
+ result['status'] = f.status
+ f.close()
+ return result
\ No newline at end of file diff --git a/tools/Fake Episode Maker/readme.txt b/tools/Fake Episode Maker/readme.txt new file mode 100644 index 0000000000..e78904ed98 --- /dev/null +++ b/tools/Fake Episode Maker/readme.txt @@ -0,0 +1,7 @@ +This is a small python program I made to quickly and easily create dummy TV show episode files for XBMC testing. + +Simply place a list of TV show titles, one per line, in shows.txt, and run main.py + +NOTE: There isn't a lot of error checking here, so its a tad touchy. You will want to put the EXACT show title as given on TVDB, and i've only tested this on windows. + +This was my first ever python program so if you can improve it feel free :)
\ No newline at end of file diff --git a/tools/Fake Episode Maker/shows.txt b/tools/Fake Episode Maker/shows.txt new file mode 100644 index 0000000000..360efaafe3 --- /dev/null +++ b/tools/Fake Episode Maker/shows.txt @@ -0,0 +1,31 @@ +24 +Alias +Andromeda +Babylon 5 +Battlestar Galactica 2003 +Cheers +Doctor Who 2005 +Enterprise +Justice League Unlimited +Lois & Clark The New Adventures of Superman +Lost +NCIS +Smallville +Star Trek: Voyager +Stargate Atlantis +Stargate SG-1 +Star Trek: Deep Space Nine +Star Trek +Star Trek: The Next Generation +CSI +CSI: Miami +CSI: NY +Knight Rider +Team Knight Rider +Knight rider 1982 +Frasier +Seinfeld +Batman: The Animated Series +Spiderman: The Animated Series +Airwolf +Fall Guy
\ No newline at end of file diff --git a/tools/HardwareConfigure/AvailableRemotes b/tools/HardwareConfigure/AvailableRemotes new file mode 100644 index 0000000000..18ff89c6ae --- /dev/null +++ b/tools/HardwareConfigure/AvailableRemotes @@ -0,0 +1 @@ +mceusb2 1137 2069 diff --git a/tools/HardwareConfigure/HardwareConfigure.cpp b/tools/HardwareConfigure/HardwareConfigure.cpp new file mode 100644 index 0000000000..85b127abda --- /dev/null +++ b/tools/HardwareConfigure/HardwareConfigure.cpp @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "HardwareConfigure.h" +#include <libhal-storage.h> +#include <iostream> +#include <fstream> +#include <string.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> + +//#define HAL_HANDLEMOUNT + +bool CHalManager::NewMessage; +DBusError CHalManager::m_Error; + +/* A Removed device, It isn't possible to make a LibHalVolume from a removed device therefor + we catch the UUID from the udi on the removal */ +void CHalManager::DeviceRemoved(LibHalContext *ctx, const char *udi) +{ + NewMessage = true; + printf("HAL: Device (%s) Removed\n", udi); +// g_HalManager.RemoveDevice(udi); +} + +void CHalManager::DeviceNewCapability(LibHalContext *ctx, const char *udi, const char *capability) +{ + NewMessage = true; + printf("HAL: Device (%s) gained capability %s\n", udi, capability); + g_HalManager.ParseDevice(udi); +} + +void CHalManager::DeviceLostCapability(LibHalContext *ctx, const char *udi, const char *capability) +{ + NewMessage = true; + printf("HAL: Device (%s) lost capability %s\n", udi, capability); + g_HalManager.ParseDevice(udi); +} + +/* HAL Property modified callback. If a device is mounted. This is called. */ +void CHalManager::DevicePropertyModified(LibHalContext *ctx, const char *udi, const char *key, dbus_bool_t is_removed, dbus_bool_t is_added) +{ + NewMessage = true; + printf("HAL: Device (%s) Property %s modified\n", udi, key); + g_HalManager.ParseDevice(udi); +} + +void CHalManager::DeviceCondition(LibHalContext *ctx, const char *udi, const char *condition_name, const char *condition_details) +{ + printf("HAL: Device (%s) Condition %s | %s\n", udi, condition_name, condition_details); + NewMessage = true; + g_HalManager.ParseDevice(udi); +} + +/* HAL Device added. This is before mount. And here is the place to mount the volume in the future */ +void CHalManager::DeviceAdded(LibHalContext *ctx, const char *udi) +{ + NewMessage = true; + printf("HAL: Device (%s) Added\n", udi); + g_HalManager.ParseDevice(udi); +} + +CHalManager g_HalManager; + +/* Iterate through all devices currently on the computer. Needed mostly at startup */ +void CHalManager::GenerateGDL() +{ + if (m_Context == NULL) + return; + + char **GDL; + int i = 0; + printf("HAL: Generating global device list\n"); + GDL = libhal_get_all_devices(g_HalManager.m_Context, &i, &m_Error); + + if (!ReadAvailableRemotes()) + return; + + for (i = 0; GDL[i]; i++) + { + if (ParseDevice(GDL[i])) + break; + } + + printf("HAL: Generated global device list, found %i\n", i); +} + +CHalManager::CHalManager() +{ +} + +// Shutdown the connection and free the context +CHalManager::~CHalManager() +{ + if (m_Context != NULL) + libhal_ctx_shutdown(m_Context, NULL); + if (m_Context != NULL) + libhal_ctx_free(m_Context); + + if (m_DBusSystemConnection != NULL) + { + dbus_connection_unref(m_DBusSystemConnection); + m_DBusSystemConnection = NULL; + } + dbus_error_free(&m_Error); // Needed? +} + +// Initialize +void CHalManager::Initialize(const char *LircConfPath) +{ + printf("HAL: Starting initializing\n"); + strcpy(m_LircConfPath, LircConfPath); + + g_HalManager.m_Context = g_HalManager.InitializeHal(); + if (g_HalManager.m_Context == NULL) + { + printf("HAL: no Hal context\n"); + return; + } + + GenerateGDL(); + + printf("HAL: Sucessfully initialized\n"); +} + +// Initialize basic DBus connection +bool CHalManager::InitializeDBus() +{ + if (m_DBusSystemConnection != NULL) + return true; + + dbus_error_init (&m_Error); + if (m_DBusSystemConnection == NULL && !(m_DBusSystemConnection = dbus_bus_get (DBUS_BUS_SYSTEM, &m_Error))) + { + printf("DBus: Could not get system bus: %s\n", m_Error.message); + dbus_error_free (&m_Error); + } + + if (m_DBusSystemConnection != NULL) + return true; + else + return false; +} + +// Initialize basic HAL connection +LibHalContext *CHalManager::InitializeHal() +{ + LibHalContext *ctx; + char **devices; + int nr; + + if (!InitializeDBus()) + return NULL; + + if (!(ctx = libhal_ctx_new())) + { + printf("HAL: failed to create a HAL context!\n"); + return NULL; + } + + if (!libhal_ctx_set_dbus_connection(ctx, m_DBusSystemConnection)) + printf("HAL: Failed to connect with dbus\n"); + + libhal_ctx_set_device_added(ctx, DeviceAdded); + libhal_ctx_set_device_removed(ctx, DeviceRemoved); + libhal_ctx_set_device_new_capability(ctx, DeviceNewCapability); + libhal_ctx_set_device_lost_capability(ctx, DeviceLostCapability); + libhal_ctx_set_device_property_modified(ctx, DevicePropertyModified); + libhal_ctx_set_device_condition(ctx, DeviceCondition); + + if (!libhal_device_property_watch_all(ctx, &m_Error)) + { + printf("HAL: Failed to set property watch %s\n", m_Error.message); + dbus_error_free(&m_Error); + libhal_ctx_free(ctx); + return NULL; + } + + if (!libhal_ctx_init(ctx, &m_Error)) + { + printf("HAL: Failed to initialize hal context: %s\n", m_Error.message); + dbus_error_free(&m_Error); + libhal_ctx_free(ctx); + return NULL; + } + + /* + * Do something to ping the HAL daemon - the above functions will + * succeed even if hald is not running, so long as DBUS is. But we + * want to exit silently if hald is not running, to behave on + * pre-2.6 systems. + */ + if (!(devices = libhal_get_all_devices(ctx, &nr, &m_Error))) + { + printf("HAL: seems that Hal daemon is not running: %s\n", m_Error.message); + dbus_error_free(&m_Error); + + libhal_ctx_shutdown(ctx, NULL); + libhal_ctx_free(ctx); + return NULL; + } + + libhal_free_string_array(devices); + + return ctx; +} + +// Called from ProcessSlow to trigger the callbacks from DBus +bool CHalManager::Update() +{ + if (m_Context == NULL) + return false; + + if (!dbus_connection_read_write_dispatch(m_DBusSystemConnection, 0)) // We choose 0 that means we won't wait for a message + { + printf("DBus: System - read/write dispatch\n"); + return false; + } + if (NewMessage) + { + NewMessage = false; + return true; + } + else + return false; +} + +/* Parse newly found device and add it to our remembered devices */ +bool CHalManager::ParseDevice(const char *udi) +{ + int VendorID, ProductID; + + VendorID = libhal_device_get_property_int(m_Context, udi, "usb.vendor_id", NULL); + ProductID = libhal_device_get_property_int(m_Context, udi, "usb.product_id", NULL); + + const char *name = IsAllowedRemote(VendorID, ProductID); + + if (name != NULL) + { + printf("HAL: Found %s - %s\n", name, udi); + if (MoveConfigs(name)) + { + printf("HAL: Sucessfully created config for %s\n", name); + return true; + + RunCommand(name); + } + else + printf("HAL: Failed to create config for %s\n", name); + } + + return false; +} + +void Tokenize(const string& path, vector<string>& tokens, const string& delimiters) +{ + // Tokenize ripped from http://www.linuxselfhelp.com/HOWTO/C++Programming-HOWTO-7.html + // Skip delimiters at beginning. + string::size_type lastPos = path.find_first_not_of(delimiters, 0); + // Find first "non-delimiter". + string::size_type pos = path.find_first_of(delimiters, lastPos); + + while (string::npos != pos || string::npos != lastPos) + { + // Found a token, add it to the vector. + tokens.push_back(path.substr(lastPos, pos - lastPos)); + // Skip delimiters. Note the "not_of" + lastPos = path.find_first_not_of(delimiters, pos); + // Find next "non-delimiter" + pos = path.find_first_of(delimiters, lastPos); + } +} + +bool CHalManager::ReadAvailableRemotes() +{ + ifstream inputfile("AvailableRemotes"); + string line; + + m_AllowedRemotes.clear(); + + if (inputfile.is_open()) + { + while (!inputfile.eof()) + { + getline(inputfile, line); + if (line.size() > 0) + { + vector<string> tokens; + Tokenize(line, tokens, " "); + + if (tokens[1].size() > 0 && tokens[0].size() > 0) + { + CHalDevice dev(atoi(tokens[1].c_str()), atoi(tokens[2].c_str()), tokens[0].c_str()); + printf("AvailableRemote: (%s) (%i) (%i)\n", dev.FriendlyName, dev.VendorID, dev.ProductID); + m_AllowedRemotes.push_back(dev); + } + } + } + inputfile.close(); + + return true; + } + return false; +} + +const char *CHalManager::IsAllowedRemote(int VendorID, int ProductID) +{ + for (unsigned int i = 0; i < m_AllowedRemotes.size(); i++) + { + if (VendorID == m_AllowedRemotes[i].VendorID && ProductID == m_AllowedRemotes[i].ProductID) + return m_AllowedRemotes[i].FriendlyName; + } + return NULL; +} + +void CHalManager::RunCommand(const char *name) +{ + char script[1024]; + sprintf(script, "%s.sh", name); + if (Exists(script)) + { + popen(script, "r"); + } +} + +bool CHalManager::MoveConfigs(const char *name) +{ + char lircd[1024], hardware[1024], lircdout[1024], hardwareout[1024]; + + sprintf(lircd, "%s.lircd.conf", name); + sprintf(lircdout, "%s/lircd.conf", m_LircConfPath); + sprintf(hardware, "%s.hardware.conf", name); + sprintf(hardwareout, "%s/hardware.conf", m_LircConfPath); + + bool temp = true; + if (!Exists(lircd)) + { + temp = false; + printf("%s didn't exist\n", lircd); + } + if (!Exists(hardware)) + { + temp = false; + printf("%s didn't exist\n", hardware); + } + if (temp) + { + bool temp2 = true; + printf("Copying %s -> %s\n", lircd, lircdout); + if (!MoveConfig(lircd, lircdout)) + { + printf("Failed to move %s -> %s\n", lircd, lircdout); + temp2 = false; + } + printf("Copying %s -> %s\n", hardware, hardwareout); + if (!MoveConfig(hardware, hardwareout)) + { + printf("Failed to move %s -> %s\n", hardware, hardwareout); + temp2 = false; + } + return temp2; + } + else + return false; +} + +bool CHalManager::Exists(const char *path) +{ + struct stat stFileInfo; + + if (stat(path, &stFileInfo) == 0) + return true; + else + return false; +} + +bool CHalManager::MoveConfig(const char *InputConfig, const char *OutputConfig) +{ + string line; + + ifstream inputfile(InputConfig); + ofstream outputfile(OutputConfig, ios_base::out); + + if (inputfile.is_open() && outputfile.is_open()) + { + while (!inputfile.eof()) + { + getline(inputfile, line); + outputfile << line <<"\n"; + } + inputfile.close(); + outputfile.close(); + return true; + } + else + return false; +} + +int main(int argc, char* argv[]) +{ + if (argc == 2) + g_HalManager.Initialize(argv[1]); + else + printf("Usage: %s PathToLircConf\n", argv[0]); +} diff --git a/tools/HardwareConfigure/HardwareConfigure.h b/tools/HardwareConfigure/HardwareConfigure.h new file mode 100644 index 0000000000..6871bda893 --- /dev/null +++ b/tools/HardwareConfigure/HardwareConfigure.h @@ -0,0 +1,81 @@ +#ifndef HARDWARECONFIGURE_H +#define HARDWARECONFIGURE_H + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include <string.h> +#include <stdio.h> +#include <dbus/dbus.h> +#include <libhal.h> +#include <vector> + +using namespace std; + +class CHalDevice +{ +public: + int ProductID; + int VendorID; + char FriendlyName[1024]; + CHalDevice(int vendorID, int productID, const char *friendlyName) { ProductID = productID; VendorID = vendorID; strcpy(FriendlyName, friendlyName); } +}; + +class CHalManager +{ +public: + bool Update(); + + void Initialize(const char *LircConfPath); + CHalManager(); + ~CHalManager(); +protected: + DBusConnection *m_DBusSystemConnection; + LibHalContext *m_Context; + static DBusError m_Error; + static bool NewMessage; + + bool ParseDevice(const char *udi); +private: + char m_LircConfPath[1024]; + vector<CHalDevice> m_AllowedRemotes; + + LibHalContext *InitializeHal(); + bool InitializeDBus(); + void GenerateGDL(); + bool MoveConfigs(const char *udi); + bool MoveConfig(const char *InputConfig, const char *OutputConfig); + bool Exists(const char *path); + const char *IsAllowedRemote(int VendorID, int ProductID); + bool ReadAvailableRemotes(); + void RunCommand(const char *name); + + //Callbacks HAL + static void DeviceRemoved(LibHalContext *ctx, const char *udi); + static void DeviceNewCapability(LibHalContext *ctx, const char *udi, const char *capability); + static void DeviceLostCapability(LibHalContext *ctx, const char *udi, const char *capability); + static void DevicePropertyModified(LibHalContext *ctx, const char *udi, const char *key, dbus_bool_t is_removed, dbus_bool_t is_added); + static void DeviceCondition(LibHalContext *ctx, const char *udi, const char *condition_name, const char *condition_details); + static void DeviceAdded(LibHalContext *ctx, const char *udi); +}; + +extern CHalManager g_HalManager; +#endif diff --git a/tools/HardwareConfigure/README b/tools/HardwareConfigure/README new file mode 100644 index 0000000000..e0fd4fb377 --- /dev/null +++ b/tools/HardwareConfigure/README @@ -0,0 +1,12 @@ +The HardwareConfigure is meant to look up known LIRC devices and copy the needed configure files for it. It will need root privelieges and it is only meant to be run at startup, no hotplugging. + +to compile it: +./build.sh + +to run it: +./HardwareConfigure PathToLIRC +PathToLIRC in ubuntu is /etc/lirc/ + +How to expand it: +Add the usb.vendor_id and usb.product_id tag in AvailableRemotes along with a FriendlyName, FriendlyName udi (ie mceusb2 would be: mceusb2 mceusb2 1137 2069), these can be found in ie gnome-device-manager. +Add friendlyname.hardware.conf and friendlyname.lircd.conf in the folder of HardwareConfigure and it will copy it if it finds the Hardware. also it's optional to add a friendlyname.sh that will be run at the time of configuration. diff --git a/tools/HardwareConfigure/build.sh b/tools/HardwareConfigure/build.sh new file mode 100755 index 0000000000..8ead12b857 --- /dev/null +++ b/tools/HardwareConfigure/build.sh @@ -0,0 +1 @@ +g++ HardwareConfigure.cpp -lhal-storage -ldbus-1 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -DDBUS_API_SUBJECT_TO_CHANGE -I/usr/include/hal -o HardwareConfigure diff --git a/tools/HardwareConfigure/mceusb2.hardware.conf b/tools/HardwareConfigure/mceusb2.hardware.conf new file mode 100644 index 0000000000..ba85300572 --- /dev/null +++ b/tools/HardwareConfigure/mceusb2.hardware.conf @@ -0,0 +1,39 @@ +# /etc/lirc/hardware.conf +# +#Chosen Remote Control +REMOTE="Windows Media Center Remotes (new version Philips et al.)" +REMOTE_MODULES="lirc_dev lirc_mceusb2" +REMOTE_DRIVER="" +REMOTE_DEVICE="/dev/lirc0" +REMOTE_LIRCD_CONF="mceusb/lircd.conf.mceusb" +REMOTE_LIRCD_ARGS="" + +#Chosen IR Transmitter +TRANSMITTER="None" +TRANSMITTER_MODULES="" +TRANSMITTER_DRIVER="" +TRANSMITTER_DEVICE="" +TRANSMITTER_LIRCD_CONF="" +TRANSMITTER_LIRCD_ARGS="" + +#Enable lircd +START_LIRCD="true" + +#Don't start lircmd even if there seems to be a good config file +#START_LIRCMD="false" + +#Try to load appropriate kernel modules +LOAD_MODULES="true" + +# Default configuration files for your hardware if any +LIRCMD_CONF="" + +#Forcing noninteractive reconfiguration +#If lirc is to be reconfigured by an external application +#that doesn't have a debconf frontend available, the noninteractive +#frontend can be invoked and set to parse REMOTE and TRANSMITTER +#It will then populate all other variables without any user input +#If you would like to configure lirc via standard methods, be sure +#to leave this set to "false" +FORCE_NONINTERACTIVE_RECONFIGURATION="false" +START_LIRCMD="" diff --git a/tools/HardwareConfigure/mceusb2.lircd.conf b/tools/HardwareConfigure/mceusb2.lircd.conf new file mode 100644 index 0000000000..041c2cbaf1 --- /dev/null +++ b/tools/HardwareConfigure/mceusb2.lircd.conf @@ -0,0 +1,104 @@ +# +# RC-6 config file +# +# source: http://home.hccnet.nl/m.majoor/projects__remote_control.htm +# http://home.hccnet.nl/m.majoor/pronto.pdf +# +# used by: Philips +# +######### +# +# Philips Media Center Edition remote control +# For use with the USB MCE ir receiver +# +# Dan Conti dconti|acm.wwu.edu +# +# Updated with codes for MCE 2005 Remote additional buttons +# *, #, Teletext, Red, Green, Yellow & Blue Buttons +# Note: TV power button transmits no code until programmed. +# Updated 12th September 2005 +# Graham Auld - mce|graham.auld.me.uk +# +# Radio, Print, RecTV are only available on the HP Media Center remote control +# + +begin remote + + name mceusb + bits 16 + flags RC6|CONST_LENGTH + eps 30 + aeps 100 + + header 2667 889 + one 444 444 + zero 444 444 + pre_data_bits 21 + pre_data 0x37FF0 + gap 105000 + toggle_bit 22 + rc6_mask 0x100000000 + + + begin codes + + Blue 0x00007ba1 + Yellow 0x00007ba2 + Green 0x00007ba3 + Red 0x00007ba4 + Teletext 0x00007ba5 + +# starts at af + Radio 0x00007baf + Print 0x00007bb1 + Videos 0x00007bb5 + Pictures 0x00007bb6 + RecTV 0x00007bb7 + Music 0x00007bb8 + TV 0x00007bb9 +# no ba - d8 + + Guide 0x00007bd9 + LiveTV 0x00007bda + DVD 0x00007bdb + Back 0x00007bdc + OK 0x00007bdd + Right 0x00007bde + Left 0x00007bdf + Down 0x00007be0 + Up 0x00007be1 + + Star 0x00007be2 + Hash 0x00007be3 + + Replay 0x00007be4 + Skip 0x00007be5 + Stop 0x00007be6 + Pause 0x00007be7 + Record 0x00007be8 + Play 0x00007be9 + Rewind 0x00007bea + Forward 0x00007beb + ChanDown 0x00007bec + ChanUp 0x00007bed + VolDown 0x00007bee + VolUp 0x00007bef + More 0x00007bf0 + Mute 0x00007bf1 + Home 0x00007bf2 + Power 0x00007bf3 + Enter 0x00007bf4 + Clear 0x00007bf5 + Nine 0x00007bf6 + Eight 0x00007bf7 + Seven 0x00007bf8 + Six 0x00007bf9 + Five 0x00007bfa + Four 0x00007bfb + Three 0x00007bfc + Two 0x00007bfd + One 0x00007bfe + Zero 0x00007bff + end codes + +end remote diff --git a/tools/Linux/FEH.py b/tools/Linux/FEH.py new file mode 100644 index 0000000000..bf83f57efc --- /dev/null +++ b/tools/Linux/FEH.py @@ -0,0 +1,173 @@ +import os +import sys +import re + +AvailableOutputs = [] +Output = None + +try: + from qt import * + AvailableOutputs.append("--error-output=Qt") +except: + pass +try: + import pygtk + pygtk.require('2.0') + import gtk + AvailableOutputs.append("--error-output=GTK") +except: + pass +try: + import pygame + import datetime + AvailableOutputs.append("--error-output=SDL") +except: + pass + +def error(errorLine): + if Output == "--error-output=Qt": + createQt(errorLine) + elif Output == "--error-output=GTK": + createGTK(errorLine) + elif Output == "--error-output=SDL": + createSDL(errorLine) + else: + print errorLine + + exit(1) + +def createQt(errorLine): + app = QApplication(sys.argv) + QObject.connect(app, SIGNAL('lastWindowClosed()') + , app + , SLOT('quit()') + ) + + dialog = QDialog(None, "Error", 0, 0) + dialog.setCaption(dialog.tr("Error")) + layout=QVBoxLayout(dialog) + layout.setSpacing(6) + layout.setMargin(5) + + label=QLabel(errorLine, dialog) + + layout.addWidget(label) + + bnExit=QPushButton("Quit", dialog, "add") + dialog.connect(bnExit, SIGNAL("clicked()"), qApp, SLOT("quit()")) + + layout.addWidget(bnExit) + + app.setMainWidget(dialog) + dialog.show() + app.exec_loop() + +def createGTK(errorLine): + window = gtk.Window(gtk.WINDOW_TOPLEVEL) + window.connect("destroy", lambda w: gtk.main_quit()) + + window.set_title("Error") + vbox = gtk.VBox(False, 5) + window.add(vbox) + window.set_border_width(5) + + frame = gtk.Frame() + frame.set_shadow_type(gtk.SHADOW_NONE) + label = gtk.Label(errorLine) + frame.add(label) + vbox.pack_start(frame, False, False, 0) + + button = gtk.Button("Quit") + button.connect_object("clicked", gtk.Widget.destroy, window) + + vbox.pack_start(button, False, False, 0) + + window.show_all () + + gtk.main() + +def createSDL(errorLine): + pygame.init() + pygame.font.init() + pygame.display.set_caption("Error") + + size = width, height = 800, 600 + speed = [2, 2] + black = 0, 0, 0 + + screen = pygame.display.set_mode(size) + font = pygame.font.Font(None, 32) + + autoQuit = 10 + start = datetime.datetime.now() + finish = datetime.datetime.now() + delta = finish - start + while delta.seconds < autoQuit: + for event in pygame.event.get(): + if event.type == pygame.QUIT or event.type == pygame.KEYDOWN: + sys.exit() + + screen.fill(black) + + place = [200, 200] + for line in errorLine.split('\n'): + text = font.render(line, 1, (255,255,255) ) + place[1] += font.size(line)[1] + screen.blit(text, text.get_rect().move(place)) + + + quitline = "Press any button to continue (" + quitline += str(autoQuit - delta.seconds) + quitline += ")" + text = font.render(quitline, 1, (255,255,255) ) + screen.blit(text, text.get_rect().move(200,400)) + + pygame.display.flip() + + finish = datetime.datetime.now() + delta = finish - start + +def badDirectRendering(): + out = os.popen("glxinfo | grep \"direct rendering\"", 'r') + line = out.read() + direct = "Yes" not in line + out.close() + + return direct + +def badColorDepth(): + out = os.popen('xdpyinfo | grep "depth of root"', 'r') + + p = re.compile("([0-9]*) planes") + for line in out.readlines(): + match = p.search(line) + if (match is not None): + if int(match.group(1)) > 16: + bitDepth = False + else: + bitDepth = True + out.close() + + return bitDepth + +def possibleOutput(text): + return text in sys.argv and text in AvailableOutputs + +if __name__=="__main__": + if len(AvailableOutputs) > 0: + Output = AvailableOutputs[0] + else: + Output = None + + for text in sys.argv: + if possibleOutput(text): + Output = text + + if "--no-test" in sys.argv: + exit(0) + + if (badDirectRendering()): + error("XBMC needs hardware accelerated OpenGL rendering.\nInstall an appropriate graphics driver.\n\nPlease consult XBMC Wiki for supported hardware\nhttp://xbmc.org/wiki/?title=Supported_hardware") + + if (badColorDepth()): + error("XBMC cannot run unless the\nscreen color depth is atleast 24 bit.\n\nPlease reconfigure your screen.") diff --git a/tools/Linux/debian/README.Debian b/tools/Linux/debian/README.Debian new file mode 100644 index 0000000000..9b390d62e7 --- /dev/null +++ b/tools/Linux/debian/README.Debian @@ -0,0 +1,11 @@ +XBMC for different Kernels and Architectures +-------------------------------------------- + +Currently, the configure scripts for XBMC is configured to only allow XBMC to +build on i386, amd64, powerpc, and powerpc64 on Linux, and i386 and powerpc on +Darwin. If you are able to build and run XBMC on other architectures and/or +kernels, please provide patches of configure.in and any other files you may have +modified to the Debian BTS. + +There is ongoing work to get XBMC to run on ARM. Please take a look at +http://xbmc.svn.sourceforge.net/viewvc/xbmc/branches/xbmc_on_arm/. diff --git a/tools/Linux/debian/README.source b/tools/Linux/debian/README.source new file mode 100644 index 0000000000..f67c0d6d95 --- /dev/null +++ b/tools/Linux/debian/README.source @@ -0,0 +1,12 @@ +The following is done to the upstream tarball or SVN checkout when creating +the orig tarball used in creating XBMC packages for Debian. + +- libdvdcss is removed from xbmc/cores/dvdplayer/Codecs/libdvd/libdvdcss. +- The empty directories xbmc/cores/dvdplayer/Codecs/libDVDCSS and + xbmc/cores/dvdplayer/Codecs/libdvdnav are removed. + +Also, the upstream source version is appended with '~debN' where 'N' is some +integer. This is done to mark that the XBMC source in Debian is modified from +upstream. Note that we do not use '~dfsgN' or something similar since there +is currently code in XBMC that does not meet the guidelines of the open source +definition. diff --git a/tools/Linux/debian/changelog b/tools/Linux/debian/changelog new file mode 100644 index 0000000000..53e1089adc --- /dev/null +++ b/tools/Linux/debian/changelog @@ -0,0 +1,104 @@ +xbmc (1:9.04.1+svn22158~deb1-1) experimental; urgency=low + + * Package XBMC for Debian. (Closes: #469397) + (LP: #307162) + * Start using an epoch for use better package versioning. + * Add Debian Multimedia team to Maintainers field. + * Add Ouattara and myself to Uploaders field. + * Add DM-Upload-Allowed: yes field. + * Switch to debhelper 7. + * Switch to quilt. + * Remove unused patch. + * Completely rewrite debian/rules to take advantage of debhelper 7 and quilt. + * Bump to Standards-Version 3.8.2. + * Changed Architecture field for arch-indep packages to 'all'. + * Included powerpc and ppc64 for binary packages. + * Use ${shlibs:Depends} for all binary packages. + * Add ${misc:Depends} to all packages. + * Changed Section to video. + * Changed Priority to optional. + * No need for debian/dirs file, so removing. + * Rename docs to xbmc-common.docs so documentation installs to xbmc-common. + * Rename debug package to xbmc-dbg. Have it debugging symbols for all binary + packages. + * Rewrite the Build-Depends field, modeling it in order from what is needed + by configure scripts. + * Fix --prefix option when calling make install* in debian/rules. + * Ensure no 'Thumbs.db' files are installed. + * Do not use cp -a, just cp. + * Rewrite Description fields for each package. + * Add Depends on python-bluez | python-lightblue for xbmc-eventclients-ps3. + * Add manpages for the programs installed in /usr/bin. + * Split xmbc-common into xbmc-bin for binary data and xbmc-data for + arch-independent data. This is done to save space in the Debian archive. + * Add Provides, Replaces, and Conflicts field in xbmc-data for xbmc-common. + * Placing packages into non-free because of various non-DFSG licensed code + * being used in XBMC. + * Various fixes for lintian warnings and errors. + + Fix not-binnmuable-all-depends-any lintian errors. + + Fix not-binnmuable-any-depends-all lintian errors. + + Fix extended-description-line-too-long lintian warnings. + + Fix python-script-but-no-python-dep lintian errors. + + Change debug package to Section 'debug' and Priority 'extra'. + + Fix maintainer-script-needs-depends-on-adduser lintian warning. + + Don't install License information as documentation. It will go in + debian/copyright. + + Rewrite copyright file. + + Include the same copyright file for all packages. + + Make sure the menu file is installed in xbmc-common package. + + Fix "needs" variable in menu file. + + Install the subdirectories of tools/EventClients/examples/ in examples for + xbmc-eventclients-dev package. + + Create a symlink to LiberationSans-Regular.ttf. + + -- Andres Mejia <mcitadel@gmail.com> Thu, 16 Jul 2009 22:50:52 -0400 + +xbmc (9.04.1.0.20670-jaunty1) jaunty; urgency=low + + * Build of 9.04.1.0.20670 + + -- Ouattara Oumar Aziz (alias wattazoum) <wattazoum@gmail.com> Tue, 26 May 2009 20:09:45 +0200 + +xbmc (2.1a2-hardy2) hardy; urgency=low + + * XBMC Alpha 2 + + -- Ouattara Oumar Aziz (alias wattazoum) <wattazoum@gmail.com> Sat, 17 May 2008 19:40:06 +0200 + +xbmc (2.1a1svn12983-hardy1) hardy; urgency=low + + * hardy port of XBMC latest svn 12983 + * added eventclients packages + + -- Ouattara Oumar Aziz (alias wattazoum) <wattazoum@gmail.com> Mon, 12 May 2008 10:50:46 +0200 + +xbmc (2.1a1b2-gutsy1) gutsy; urgency=low + + * add the debug symbol package + * change the launcher icon to the one provided by djdafreund + * create the log file by default and give it the universal rigths + * Activate support for WII remote + + -- Ouattara Oumar Aziz (alias wattazoum) <wattazoum@gmail.com> Mon, 31 Mar 2008 19:33:14 +0200 + +xbmc (2.1a1b1-gutsy3) gutsy; urgency=low + + * Release from revision 12195 + * MythTV support + * Added a launcher for xbmc + + -- Ouattara Oumar Aziz (alias wattazoum) <wattazoum@gmail.com> Sat, 29 Mar 2008 20:28:47 +0100 + +xbmc (2.1a1-gutsy2) gutsy; urgency=low + + * Release Made on Revision 12195 + * No Myth TV support + + -- Ouattara Oumar Aziz (alias wattazoum) <wattazoum@gmail.com> Sat, 29 Mar 2008 01:49:20 +0100 + +xbmc (0.1-1gutsy~ppa1) gutsy; urgency=low + + * Initial release for GUTSY : first ppa package for XBMC + + -- Ouattara Oumar Aziz (alias wattazoum) <wattazoum@gmail.com> Fri, 28 Mar 2008 21:17:01 +0100 + diff --git a/tools/Linux/debian/compat b/tools/Linux/debian/compat new file mode 100644 index 0000000000..7f8f011eb7 --- /dev/null +++ b/tools/Linux/debian/compat @@ -0,0 +1 @@ +7 diff --git a/tools/Linux/debian/control b/tools/Linux/debian/control new file mode 100644 index 0000000000..c2689e0635 --- /dev/null +++ b/tools/Linux/debian/control @@ -0,0 +1,497 @@ +Source: xbmc +Section: non-free/video +Priority: optional +Maintainer: Debian Multimedia Maintainers <pkg-multimedia-maintainers@lists.alioth.debian.org> +Uploaders: Ouattara Oumar Aziz (alias wattazoum) <wattazoum@gmail.com>, + Andres Mejia <mcitadel@gmail.com> +DM-Upload-Allowed: yes +Build-Depends: debhelper (>= 7.0.50), quilt, python-support, cmake, + autotools-dev, autoconf, automake, unzip, libboost-dev, + libgl1-mesa-dev | libgl-dev, libglu-dev, libglew-dev, libmad0-dev, libjpeg-dev, + libsamplerate-dev, libogg-dev, libvorbis-dev, libfreetype6-dev, + libfontconfig-dev, libbz2-dev, libfribidi-dev, libsqlite3-dev, + libmysqlclient-dev, libasound-dev, libpng-dev, libpcre3-dev, liblzo2-dev, + libcdio-dev, libsdl-dev, libsdl-image1.2-dev, libsdl-mixer1.2-dev, libenca-dev, + libjasper-dev, libxt-dev, libxtst-dev, libxmu-dev, libxinerama-dev, + libcurl4-gnutls-dev | libcurl-dev, libdbus-1-dev, libhal-storage-dev, + libhal-dev, libpulse-dev, libavahi-common-dev, libavahi-client-dev, + libxrandr-dev, libavcodec-dev, libavformat-dev, libavutil-dev, libpostproc-dev, + libswscale-dev, liba52-dev, libdts-dev, libmpeg2-4-dev, libass-dev, + libmpcdec-dev, libflac-dev, libwavpack-dev, python-dev, gawk, gperf, + nasm [!amd64], libcwiid1-dev, libbluetooth-dev, zlib1g-dev, libmms-dev, + libsmbclient-dev, libfaad-dev, +Standards-Version: 3.8.2 +Homepage: http://xbmc.org/ +Vcs-Git: git://git.debian.org/git/pkg-multimedia/xbmc.git +Vcs-Browser: http://git.debian.org/?p=pkg-multimedia/xbmc.git;a=summary + +Package: xbmc +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + xbmc-skin-pm3-hd (= ${binary:Version}), + xbmc-web-pm3 (= ${binary:Version}), + ${misc:Depends} +Suggests: xbmc-third-parties +Description: XBMC Media Center (full metapackage) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package is a metapackage aimed at users wanting to quickly get started + with using XBMC Media Center. + +Package: xbmc-live +Architecture: all +Depends: xbmc-standalone (= ${binary:Version}), + policykit, + openssh-server, + ${python:Depends}, + python-apt, + adduser, + ${misc:Depends} +Conflicts: kdm, gdm, xdm, wdm +Description: XBMC Media Center (XBMC Live package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package is used to setup the XBMC Live environment. + +Package: xbmc-standalone +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + xbmc-skin-pm3-hd (= ${binary:Version}), + xbmc-web-pm3 (= ${binary:Version}), + ${misc:Depends} +Suggests: xbmc-third-parties +Description: XBMC Media Center (standalone program) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package will install files that would permit to launch XBMC without + having a desktop manager. + +Package: xbmc-data +Architecture: all +Depends: xbmc-bin (>= ${source:Version}), + xbmc-bin (<< ${source:Version}.1~), + ${python:Depends}, + ${misc:Depends} +Provides: xbmc-common +Replaces: xbmc-common +Conflicts: xbmc-common +Suggests: xbmc-test-helper +Recommends: python-qt3 +Description: XBMC Media Center (arch-independent data package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains all the archiecture independent data needed to have a + working XBMC. + +Package: xbmc-bin +Architecture: i386 amd64 powerpc ppc64 +Depends: ${shlibs:Depends}, + ${misc:Depends} +Description: XBMC Media Center (binary data package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains all the binary data needed to have a working XBMC. + +Package: xbmc-dbg +Architecture: i386 amd64 powerpc ppc64 +Section: non-free/debug +Priority: extra +Depends: xbmc-bin (= ${binary:Version}), + ${misc:Depends} +Description: XBMC Media Center (debug package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains debugging symbols for XBMC. + +Package: xbmc-scripts-example +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + ${misc:Depends} +Description: XBMC Media Center (example scripts) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains scripts shipped with XBMC for user conveniance. + +Package: xbmc-skin-pm3 +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + ${misc:Depends} +Replaces: xbmc-skin-default +Conflicts: xbmc-skin-default +Description: XBMC Media Center (Project Mahem III skin) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains the XBMC PM3 Skin package (aka Project Mahem III). + +Package: xbmc-skin-pm3-hd +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + ttf-liberation, + ${misc:Depends} +Description: XBMC Media Center (PM3 HD skin) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains the XBMC PM3 HD Skin package (aka Project Mahem III + High Definition). + +Package: xbmc-web-pm3 +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + ${misc:Depends} +Description: XBMC Media Center (Project Mahem III web skin) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains the PM3 (aka Project Mahem III) Skin for the XBMC web + server. + +Package: xbmc-web-pm +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + ${misc:Depends} +Conflicts: xbmc-web-pm3 +Description: XBMC Media Center (Project Mahem web skin) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains the PM (aka Project Mahem) Skin for the XBMC web + server. + +Package: xbmc-web-eflexweb +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + ${misc:Depends} +Conflicts: xbmc-web-pm3, xbmc-web-pm, xbmc-web-iphone-tlrobinson +Description: XBMC Media Center (Eflex web skin) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains the XBMC Webserver Eflex web Skin for the XBMC web + server. + +Package: xbmc-web-iphone-tlrobinson +Architecture: all +Depends: xbmc-data (= ${binary:Version}), + ${misc:Depends} +Description: XBMC Media Center (Iphone web skin) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package contains the Iphone skin for the XBMC Webserver. + +Package: xbmc-eventclients-common +Architecture: all +Depends: ${python:Depends}, ${misc:Depends} +Description: XBMC Media Center (Event Client Common package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package is the common package for XBMC Event Client. + +Package: xbmc-eventclients-dev +Architecture: all +Section: non-free/libdevel +Depends: xbmc-eventclients-common (= ${binary:Version}), + ${misc:Depends} +Description: XBMC Media Center (Event Client Dev package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This is the Development package for XBMC Event Client. + +Package: xbmc-eventclients-wiiremote +Architecture: i386 amd64 powerpc ppc64 +Depends: xbmc-eventclients-common (= ${source:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: XBMC Media Center (Event Client WII Remote support package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package is the Wii Remote client package for XBMC. + +Package: xbmc-eventclients-j2me +Architecture: all +Depends: xbmc-eventclients-common (= ${binary:Version}), + ${python:Depends}, + python-bluez, + ${misc:Depends} +Description: XBMC Media Center (Event Client J2ME package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package is the J2ME package for XBMC Event Client. This is meant to + provide a server that communicate with a mobile tool supporting Java ME. + +Package: xbmc-eventclients-ps3 +Architecture: all +Depends: xbmc-eventclients-common (= ${binary:Version}), + python-bluez | python-lightblue, + ${python:Depends}, + ${misc:Depends} +Description: XBMC Media Center (Event Client PS3 package) + XBMC, recursive acronym for "XBMC Media Center", is an award winning free and + open source software media-player and entertainment hub for all your digital + media. XBMC is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) + and Microsoft Windows, as well as the original Xbox game console. Created in + 2003 by a group of like minded programmers, XBMC is a non-profit project run + and developed by volunteers located around the world. More than 50 software + developers have contributed to XBMC, and 100-plus translators have worked to + expand its reach, making it available in more than 30 languages. + . + While XBMC functions very well as a standard media player application for + your computer, it has been designed to be the perfect companion for your + HTPC. Supporting an almost endless range of remote controls, and combined + with its beautiful interface and powerful skinning engine, XBMC feels very + natural to use from the couch and is the ideal solution for your home + theater. Once installed, your computer will become a fully functional + multimedia jukebox. + . + This package is the PS3 package for XBMC Event Client. diff --git a/tools/Linux/debian/copyright b/tools/Linux/debian/copyright new file mode 100644 index 0000000000..d05eb995e5 --- /dev/null +++ b/tools/Linux/debian/copyright @@ -0,0 +1,3304 @@ +XBMC is downloaded from http://xbmc.org/. +SVN snapshots are generated from +https://xbmc.svn.sourceforge.net/svnroot/xbmc/branches/linuxport. + +Main Contact: "Team-XBMC" <team at xbmc dot org> + +Upstream Authors: Andreas Setterlind [Gamester17] + Staffan Lindberg [pike] + Arne Morten Kvarving [cptspiff] + Anoop Menon [d4rk] + Joakim Plate [elupus] + Jonathan Marshall [jmarshall] + Tobias Arrskog [Topfs2] + Roee Vulkan [vulkanr] + Winfried Soltys [WiSo] + Yuval Tal [yuvalt] + John W Vanderbeck [agathorn] + Trent Nelson [AlTheKiller] + Andres Mejia [ceros] + Gunnar Norin [blittan] + Dean Ross Parry [C-Quel] + Sylvain Rebaud [c0diq] + Martin van Beurden [chadoe] + Scott Davilla [davilla] + Stephan Diederich [MaestroDD] + Benjamin Bertrand [Beenje] + Benjamin Dickgiesser [DonJ] + [GeminiServer] + Christian Granqvist [Granqvist] + Dave [kraqh3d] + Luigi Capriotti [l.capriotti] + Sean [malloc] + Kyle Hill [monkeyman] + [MrC] + [nad] + [nuka1195] + Vincent Blackwell-Price [Voinage] + Robert Parris [rwparris2] + Sigurdur H. Olafsson [sho] + Alasdair Campbell [Alcoheca] + Georgy Yunaev [oldnemesis] + Chris [phi2039] + Bob [bobo1on1] + David Allonby [motd2k] + Robert Rudd [Rudd] + Eric G [Tslayer] + Amund Scharning [tut-ankh-amon] + Matthias Kortstiege [VDRfan] + Daniel Mehrwald [AreaScout] + Oumar Aziz Outtara [wattazoum] + Chris Haley [CHI3f] + [Jezz_X] + [Smokehead] + Darren [Bizzeh] + Marc [Bobbin007] + Richard [Butcher] + Jan-Willem [Darkie] + Chris Branson [forza] + [Kreet] + [Ysbox] + Erwin Beckers [Frodo] + Albert Griscti-Soler [RUNTiME] + Phil Burr [d7o3g4q] (a.k.a. Duo Egaq) + Mathias Mahling [chokemaniac] + +Credits: + +XBMC - Cross-platform Media Center +<http://xbmc.org/> + + Copyright © 2005-2009 Team XBMC http://www.xbmc.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. + +Generic classes for raster images + + Copyright © 2000, Juan Soulie <jsoulie@cplusplus.com> + + Permission to use, copy, modify, distribute and sell this software or any + part thereof and/or its documentation for any purpose is granted without fee + provided that the above copyright notice and this permission notice appear + in all copies. + + This software is provided "as is" without express or implied warranty of + any kind. The author shall have no liability with respect to the + infringement of copyrights or patents that any modification to the content + of this file or this file itself may incur. + +The FreeType Project +<http://www.freetype.org/> + + Copyright © 1996-2006, by David Turner, Robert Wilhelm, and Werner Lemberg + + This file is part of the FreeType project, and may only be used, + modified, and distributed under the terms of the FreeType project + license, LICENSE.TXT. By continuing to use, modify, or distribute + this file you indicate that you have read the license and + understand and accept it fully. + + A full copy of the FreeType License (FTL) is provided under section + "Licenses". + +TinyXML - simple, small, C++ XML Parser +<http://www.grinninglizard.com/tinyxml/> + + Copyright © 2000-2006 Lee Thomason (www.grinninglizard.com) + Copyright © 2005 Tyge Lovset + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +CString Class + + Copyright © 2002 Joseph M. O'Leary + + This code is 100% free. Use it anywhere you want. Rewrite it, restructure + it, whatever. If you can write software that makes money off of it, good for + you. I kinda like capitalism. Please don't blame me if it causes your $30 + billion dollar satellite explode in orbit. If you redistribute it in any + form, I'd appreciate it if you would leave this notice here. + +Spyce - Server-side Python-based dynamic HTML generation +<http://spyce.sourceforge.net/> + + Copyright © 2002-03 Rimon Barr. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice and + this LICENCE in its entirety including the disclaimer. The LICENCE of this + product may only be modified by the Copyright holder. + + 2. Redistributions in binary form must reproduce the above copyright notice + and this LICENCE in its entirety including the disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product uses Spyce, Copyright + Rimon Barr." Alternately, this acknowledgment may appear in the software + itself, wherever such third-party acknowledgments normally appear. The + documentation must also provide a instructions on how to receive an original + Spyce distribution, preferably a link to the website + http://spyce.sourceforge.net. + + 4. The names "Spyce", or "Rimon Barr" must not be used to endorse or promote + products derived from this software without prior written permission. For + written permission, please contact rimon-AT-acm.org. + + 5. Products derived from this software may not be called "Spyce", nor may + "Spyce" appear in their names, without prior written permission of the + Copyright holder. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RIMON + BARR OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Mach-O library symbol mapping Ruby Scripts + + Copyright © 2008 Elan Feingold (elan at bluemandrill dot com) + + 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. + +Wiimote C Library +<http://www.wiiuse.net/> + + Copyright © Michael Laforest < para > + < thepara (--AT--) g m a i l [--DOT--] com > + + 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 3 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, see <http://www.gnu.org/licenses/>. + +Wiiuse Class for XBMC + + Copyright © 2009 by Cory Fields + + 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 3 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, see <http://www.gnu.org/licenses/>. + +Apple Remote Control Wrapper Classes + + Copyright © 2006 Martin Kahr martinkahr.com. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +Class to Display events received from the Apple Infrared Remote. + + Copyright © 2006-2008 Amit Singh. All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +ISO C9x compliant stdint.h and inttypes.h for Microsoft Visual Studio + + Copyright © 2006 Alexander Chemeris + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cURL - library and command line tool for transferring files with URL syntax +<http://curl.haxx.se/> + + Copyright © 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al. + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of a copyright holder shall not + be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization of the + copyright holder. + +RegExp.h + + Copyright © 1986, 1993, 1995 by University of Toronto. + + Permission is granted to anyone to use this software for any + purpose on any computer system, and to redistribute it in any way, + subject to the following restrictions: + + 1. The author is not responsible for the consequences of use of + this software, no matter how awful, even if they arise + from defects in it. + + 2. The origin of this software must not be misrepresented, either + by explicit claim or by omission. + + 3. Altered versions must be plainly marked as such, and must not + be misrepresented (by explicit claim or omission) as being + the original software. + + 4. This notice must not be removed or altered. + +GNU gettext - internationalization aids +<http://www.gnu.org/software/gettext/> + + Copyright © 1988, 1989, 1992, 1993, 1995 Free Software Foundation, Inc. + + 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. + +SNTP Protocol C++ Implementation +<http://www.naughter.com/sntp.html> + + Copyright © 1998 - 2003 by PJ Naughter. + (Web: www.naughter.com, Email: pjna@naughter.com) + + You are allowed to include the source code in any product (commercial, + shareware, freeware or otherwise) when your product is released in binary + form. You are allowed to modify the source code in any way you want except + you cannot modify the copyright details at the top of each module. If you + want to distribute source code with your application, then you are only + allowed to distribute versions released by the author. This is to maintain a + single distribution point for the source code. + +RSA Data Security, Inc. MD5 Implementation +<http://www.rsa.com/> + + Copyright © 1990, RSA Data Security, Inc. All rights reserved. + + The RSA Data Security license is known to be GPL incompatible. Suggest to use + the public domain implementation found in dpkg and adopted by mediatomb. + + License to copy and use this software is granted provided that + it is identified as the "RSA Data Security, Inc. MD5 Message + Digest Algorithm" in all material mentioning or referencing this + software or this function. + + License is also granted to make and use derivative works + provided that such works are identified as "derived from the RSA + Data Security, Inc. MD5 Message Digest Algorithm" in all + material mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning + either the merchantability of this software or the suitability + of this software for any particular purpose. It is provided "as + is" without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +DBUSServer Class +<http://www.azurdigitalnetworks.net/> + + Copyright © 2009 Azur Digital Networks + + 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. + +Really Slick X Screensavers +<http://www.reallyslick.com/> + + Copyright © 2002-2006 Michael Chapman + Copyright © 2002 Terence M. Welsh + + 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. + +SDLMain.h + + Copyright © Darrell Walisser <dwaliss1@purdue.edu> + Copyright © Max Horn <max@quendi.de> + + Feel free to customize this file to suit your needs. + +XKGeneral.h - General Utility and Helper function Class' Header + + Copyright © TEAM ASSEMBLY www.team-assembly.com + + 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. + +Goom 2k4 +<http://www.ios-software.com/index.php3?page=projet&quoi=1&lg=AN> + + Copyright © 2000-2004, Jean-Christophe Hoelt <jeko@ios-software.com> + Copyright © 2000-2004, Guillaume Borios <gyom@ios-software.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +XAnalyser, frequence spectrum analyser for X Window +<http://arvin.schnell-web.net/xanalyser/> + + Copyright © 1998 Arvin Schnell + + 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. + +XMMS - Cross-platform multimedia player +<http://www.xmms.org/> + + Copyright © 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson + and 4Front Technologies + + 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. + +Pthreads-win32 - POSIX Threads Library for Win32 +<http://sourceware.org/pthreads-win32/> + + Copyright © 1998 John E. Bossom + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +projectM - OpenGL based advanced music visualization program +<http://projectm.sourceforge.net/> + + Copyright © 2003-2007 projectM Team + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +GLEW - The OpenGL Extension Wrangler Library +<http://glew.sourceforge.net/> + + Copyright © 2002-2008, Milan Ikits <milan ikits[]ieee org> + Copyright © 2002-2008, Marcelo E. Magallon <mmagallo[]debian org> + Copyright © 2002, Lev Povalahev + Copyright © 1999-2007 Brian Paul + Copyright © 2007 The Khronos Group Inc. + All Rights Reserved. + + Falls under three licenses, which are the Modified BSD License, the Mesa 3-D + License (MIT License), and the Khronos License (MIT License). + + Modified BSD License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + + Mesa 3-D License (MIT License) + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Khronos License (MIT License) + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and/or associated documentation files (the + "Materials"), to deal in the Materials without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Materials, and to + permit persons to whom the Materials are furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Materials. + + THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +ftpparse +<http://cr.yp.to/ftpparse.html> + + Copyright © D. J. Bernstein, djb@cr.yp.to http://cr.yp.to/ftpparse.html + + There is only a disclaimer at http://cr.yp.to/ftpparse.html. + Here's the disclaimer. + + Commercial use of ftpparse is fine, as long as you let me know what programs + you're using it in. + +OpenDAAP +<http://www.opendaap.org/> + + Copyright © 2004 Forza (Chris Barnett) + Copyright © the authors of libOpenDAAP + + 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. + +RingBuffer.h: Interface and implementation of CRingBuffer, an MFC ring buffer +class. + + Copyright © Larry Antram (larrya@sdust.com) + Copyright © 2001-2002 Stardust Software. All Rights Reserved. + + This code may be used in compiled form in any way you desire + and may be redistributed unmodified by any means PROVIDING it + is not sold for profit without the authors written consent, and + providing that this entire notice and the authors name and all + copyright notices remains intact. + + This file is provided "as is" with no expressed or implied + warranty. The author accepts no liability for any damage/loss + of business that this product may cause. + +zlib - A Massively Spiffy Yet Delicately Unobtrusive Compression Library +<http://www.zlib.net/> + + Copyright © 1995-2002 Jean-loup Gailly and Mark Adler. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +iso9660.h + + Copyright © The Joker / Avalaunch team + + 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. + +Neptune Portable C++ Runtime Library +<http://neptune.sourceforge.net/> + + Copyright © 2001-2006 Gilles Boccon-Gibod + Copyright © 2002-2008, Axiomatic Systems, LLC. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +MMST implementation taken from the xine-mms plugin made by Major MMS +(http://geocities.com/majormms/). + + Copyright © 2005-2008 Team XBMC + Copyright © 2002 Abhijeet Phatak <abhijeetphatak@yahoo.com> + Copyright © 2002 the xine project + Copyright © 2000-2001 major mms + + 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. + +Ogg Bitstream Library +<http://www.xiph.org/> + + Copyright © 1994-2002 Xiph.Org Foundation http://www.xiph.org/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + This software is provided by the copyright holders and contributors “as is†+ and any express or implied warranties, including, but not limited to, the + implied warranties of merchantability and fitness for a particular purpose + are disclaimed. In no event shall the foundation or contributors be liable + for any direct, indirect, incidental, special, exemplary, or consequential + damages (including, but not limited to, procurement of substitute goods or + services; loss of use, data, or profits; or business interruption) however + caused and on any theory of liability, whether in contract, strict + liability, or tort (including negligence or otherwise) arising in any way + out of the use of this software, even if advised of the possibility of such + damage. + +The Vorbis General Audio Compression Codec +<http://www.xiph.org/> + + Copyright © 2002, Xiph.org Foundation + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + This software is provided by the copyright holders and contributors “as is†+ and any express or implied warranties, including, but not limited to, the + implied warranties of merchantability and fitness for a particular purpose + are disclaimed. In no event shall the foundation or contributors be liable + for any direct, indirect, incidental, special, exemplary, or consequential + damages (including, but not limited to, procurement of substitute goods or + services; loss of use, data, or profits; or business interruption) however + caused and on any theory of liability, whether in contract, strict + liability, or tort (including negligence or otherwise) arising in any way + out of the use of this software, even if advised of the possibility of such + damage. + +LAME Ain't an Mp3 Encoder +<http://lame.sourceforge.net/> + + Copyright © 1999 Mark Taylor + + 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. + +GoAhead WebServer +<http://www.goahead.com/products/webserver/default.aspx> + + Copyright © GoAhead Software Inc., 1995-2000. All Rights Reserved. + + This software is distributed under the GoAhead Open Source License + Agreement. + + A copy of this license may be downloaded from + http://www.goahead.com/pdf/opensourcewebserver.pdf and under the section + "License: GoAhead Open Source License". + +Python Programming Language +<http://www.python.org/> + + Copyright © 2001-2008 Python Software Foundation. All rights reserved. + Copyright © 2000 BeOpen.com. All rights reserved. + Copyright © 1995-2001 Corporation for National Research Initiatives. All + rights reserved. + Copyright © 1991-1995 Stichting Mathematisch Centrum. All rights reserved. + + Python is distributed under the Python Software Foundation License + version 2. A copy of the license may be retrieved from + http://www.python.org/psf/license/ and is repeated below under the section + "License: PSF License for Python 2.4". + +libshout - Library which can be used to write a source client like ices +<http://www.icecast.org/> + + Copyright © 2004 the Icecast team <team@icecast.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +libopendaap - library which enables applications to discover, and connect to, +iTunes music shares. +<http://craz.net/programs/itunes/libopendaap.html> + + Copyright © 2004 David Hammerton. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + +libsamplerate - audio rate conversion library +<http://www.mega-nerd.com/SRC/> + + Copyright © 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com> + + 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. + +MediaMVP Media Center +<http://www.mvpmc.org/> + + Copyright © 2004-2006, Eric Lund, Jon Gettler, Sergio Slobodrian + http://www.mvpmc.org/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +MySQL +<http://www.mysql.com/> + + Copyright © 2000-2003 MySQL AB + + 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. + + 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. + +libid3tag - ID3 tag manipulation library +<http://www.underbit.com/products/mad/> + + Copyright © 2000-2004 Underbit Technologies, Inc. + + 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. + +Simple DirectMedia Layer +<http://www.libsdl.org/> + + Copyright © 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +libfribidi - Free Implementation of the Unicode BiDi algorithm +<http://www.fribidi.org/> + + Copyright © 1999,2000 Dov Grobgeld + Copyright © 2001,2002 Behdad Esfahbod + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +CDRip - library that provides methods for extracting data from audio CDs +<http://libcdrip.sourceforge.net/> + + Copyright © 1999 - 2002 Albert L. Faber + + 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. + +Platinum - UPnP library +<http://www.plutinosoft.com/> + + Copyright © 2004-2008, Plutinosoft, LLC. All rights reserved. + + 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. + +SQLite - library that implements a self-contained, serverless, +zero-configuration, transactional SQL database engine. +<http://www.sqlite.org/> + + Copyright © 2004, Leo Seib, Hannover + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + +CxImage - C++ image processing and conversion library +<http://www.xdp.it/cximage.htm> + + Copyright © 2001 - 2008, Davide Pizzolato + + Original CImage and CImageIterator implementation are: + Copyright © 1995, Alejandro Aguilar Sierra + (asierra(at)servidor(dot)unam(dot)mx) + + Covered code is provided under this license on an "as is" basis, without + warranty of any kind, either expressed or implied, including, without + limitation, warranties that the covered code is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the covered code is with you. + Should any covered code prove defective in any respect, you (not the initial + developer or any other contributor) assume the cost of any necessary + servicing, repair or correction. This disclaimer of warranty constitutes an + essential part of this license. No use of any covered code is authorized + hereunder except under this disclaimer. + + Permission is hereby granted to use, copy, modify, and distribute this + source code, or portions hereof, for any purpose, including commercial + applications, freely and without fee, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + Portions of CxImage are under different copyright and under different + licenses. + + JasPer + Copyright © 2001-2006 Michael David Adams + Copyright © 1999-2000 Image Power, Inc. + Copyright © 1999-2000 The University of British Columbia + All Rights Reserved. + + Permission is hereby granted, free of charge, to any person (the + "User") obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + 1. The above copyright notices and this permission notice (which + includes the disclaimer below) shall be included in all copies or + substantial portions of the Software. + + 2. The name of a copyright holder shall not be used to endorse or + promote products derived from the Software without specific prior + written permission. + + THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS + LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER + THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS + "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE + PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE + THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. + EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS + BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL + PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS + GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE + ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE + IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL + SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, + AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL + SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH + THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, + PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH + RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY + EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. + + JBIG + Copyright © Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/ + + 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. + + MNG + Copyright © 2000-2007 Gerard Juyn (gerard@libmng.com) + + For the purposes of this copyright and license, "Contributing Authors" + is defined as the following set of individuals: + + Gerard Juyn + Glenn Randers-Pehrson + + The MNG Library is supplied "AS IS". The Contributing Authors + disclaim all warranties, expressed or implied, including, without + limitation, the warranties of merchantability and of fitness for any + purpose. The Contributing Authors assume no liability for direct, + indirect, incidental, special, exemplary, or consequential damages, + which may result from the use of the MNG Library, even if advised of + the possibility of such damage. + + Permission is hereby granted to use, copy, modify, and distribute this + source code, or portions hereof, for any purpose, without fee, subject + to the following restrictions: + + 1. The origin of this source code must not be misrepresented; + you must not claim that you wrote the original software. + + 2. Altered versions must be plainly marked as such and must not be + misrepresented as being the original source. + + 3. This Copyright notice may not be removed or altered from any source + or altered source distribution. + + The Contributing Authors specifically permit, without fee, and + encourage the use of this source code as a component to supporting + MNG and JNG file format in commercial products. If you use this + source code in a product, acknowledgment would be highly appreciated. + + JPEG + Copyright © 1994-1998, Thomas G. Lane. + + JPEG code is under the Independent JPEG Group License which can be found at + http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev=1.2 and is repeated + under the section "License: IJG License". + + TIFF + Copyright © 1988-1997 Sam Leffler + Copyright © 1991-1997 Silicon Graphics, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + + PNG + Copyright © 1998, 1999 Glenn Randers-Pehrson + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Dave Coffin's raw photo decoder + Copyright © 1997-2009 by Dave Coffin, dcoffin a cybercom o net + + Covered code is provided under this license on an "as is" basis, without + warranty of any kind, either expressed or implied, including, without + limitation, warranties that the covered code is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the covered code is with you. + Should any covered code prove defective in any respect, you (not the initial + developer or any other contributor) assume the cost of any necessary + servicing, repair or correction. This disclaimer of warranty constitutes an + essential part of this license. No use of any covered code is authorized + hereunder except under this disclaimer. + + No license is required to download and use libdcr. However, + to lawfully redistribute libdcr, you must either (a) offer, at + no extra charge, full source code for all executable files + containing RESTRICTED functions, (b) distribute this code under + the GPL Version 2 or later, (c) remove all RESTRICTED functions, + re-implement them, or copy them from an earlier, unrestricted + revision of dcraw.c, or (d) purchase a license from the author + of dcraw.c. + +PortAudio - portable cross-platform Audio API +<http://www.portaudio.com/> + + Copyright © 1999-2002 Ross Bencina and Phil Burk + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + +libXBMS + + Copyright © 2002-2003 by PuhPuh + + If what was meant is that we received permission to distributed this code + under the same terms as XBMC (i.e. under GPL-2 or later), than it's best to + remove the first notice. Here's the license below. + + This code is copyrighted property of the author. It can still + be used for any non-commercial purpose following conditions: + + 1) This copyright notice is not removed. + 2) Source code follows any distribution of the software + if possible. + 3) Copyright notice above is found in the documentation + of the distributed software. + + Any express or implied warranties are disclaimed. Author is + not liable for any direct or indirect damages caused by the use + of this software. + + ---------------------------------------------------------------------- + + This code has been integrated into XBMC Media Center. + As such it can me copied, redistributed and modified under + the same conditions as the XBMC itself. + +Audioscrobbler - The Social Music Technology Playground +<http://www.audioscrobbler.net/> + + Copyright © 2003 Russell Garrett (russ-scrobbler@garrett.co.uk) + + 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. + +UnRarX +<http://www.unrarx.com/> + + Copyright © Eugene Roshal + + Section two of this license makes this GPL incompatible. + + The source code of unRAR utility is freeware. This means: + + 1. All copyrights to RAR and the utility unRAR are exclusively + owned by the author - Eugene Roshal. + + 2. The unRAR sources may be used in any software to handle RAR + archives without limitations free of charge, but cannot be used + to re-create the RAR compression algorithm, which is proprietary. + Distribution of modified unRAR sources in separate form or as a + part of other software is permitted, provided that it is clearly + stated in the documentation and source comments that the code may + not be used to develop a RAR (WinRAR) compatible archiver. + + 3. The unRAR utility may be freely distributed. No person or company + may charge a fee for the distribution of unRAR without written + permission from the copyright holder. + + 4. THE RAR ARCHIVER AND THE UNRAR UTILITY ARE DISTRIBUTED "AS IS". + NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT + YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS, + DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING + OR MISUSING THIS SOFTWARE. + + 5. Installing and using the unRAR utility signifies acceptance of + these terms and conditions of the license. + + 6. If you don't agree with terms of the license you must remove + unRAR files from your storage devices and cease to use the + utility. + + Thank you for your interest in RAR and unRAR. + +Samba - Opening Windows to a Wider World +<http://www.samba.org/> + + Copyright © Andrew Tridgell 1998 + Copyright © Richard Sharpe 2000 + Copyright © John Terpsra 2000 + Copyright © Tom Jansen (Ninja ISD) 2002 + Copyright © Derrell Lipman 2003 + + 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. + +PCRE - Perl Compatible Regular Expressions +<http://www.pcre.org/> + + Copyright © 1997-2007 University of Cambridge + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +HDHomeRun - Networked Digital Tuner +<http://www.silicondust.com/> + + Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + + As a special exception to the GNU Lesser General Public License, + you may link, statically or dynamically, an application with a + publicly distributed version of the Library to produce an + executable file containing portions of the Library, and + distribute that executable file under terms of your choice, + without any of the additional requirements listed in clause 4 of + the GNU Lesser General Public License. + + By "a publicly distributed version of the Library", we mean + either the unmodified Library as distributed by Silicondust, or a + modified version of the Library that is distributed under the + conditions defined in the GNU Lesser General Public License. + +LibASS - portable library for SSA/ASS subtitles rendering +<http://sourceforge.net/projects/libass/> + + Copyright © 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> + + 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. + +libRTV - ReplayTV library + + Copyright © 2002 John Todd Larason <jtl@molehill.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. + +libiconv - iconv() implementation +<http://www.gnu.org/software/libiconv/> + + Copyright © 1999-2003 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +Boost C++ Libraries +<http://www.boost.org/> + + Copyright © 2001, 2002 Peter Dimov and Multi Media Ltd. + Copyright © 2007 Peter Dimov + + Permission is hereby granted, free of charge, to any person or organization + obtaining a copy of the software and accompanying documentation covered by + this license (the "Software") to use, reproduce, display, distribute, + execute, and transmit the Software, and to prepare derivative works of the + Software, and to permit third-parties to whom the Software is furnished to + do so, all subject to the following: + + The copyright notices in the Software and this entire statement, including + the above license grant, this restriction and the following disclaimer, + must be included in all copies of the Software, in whole or in part, and + all derivative works of the Software, unless such copies or derivative + works are solely in the form of machine-executable object code generated by + a source language processor. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +HTS Tvheadend - Combined DVB receiver, Digital Video Recorder and Showtime +streaming server for Linux. +<http://www.lonelycoder.com/hts/> + + Copyright © 2008 Andreas Öman + + 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 3 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, see <http://www.gnu.org/licenses/>. + +GNU Compact Disc Input and Control Library +<http://www.gnu.org/software/libcdio/index.html> + + Copyright © 2001 Herbert Valerio Riedel <hvr@gnu.org> + Copyright © 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com> + + 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. + +DUMB - Dynamic Universal Music Bibliotheque +<http://dumb.sourceforge.net/> + + Copyright © 2001-2005 Ben Davis, Robert J Ohannessian and Julien Cugniere + + Licence for DUMB v0.9.3 + + _______ ____ __ ___ ___ + \ _ \ \ / \ / \ \ / / ' ' ' + | | \ \ | | || | \/ | . . + | | | | | | || ||\ /| | + | | | | | | || || \/ | | ' ' ' + | | | | | | || || | | . . + | |_/ / \ \__// || | | + /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque + / \ + / . \ + licence.txt - Conditions for use of DUMB. / / \ \ + | < / \_ + If you do not agree to these terms, please | \/ /\ / + do not use DUMB. \_ / > / + | \ / / + Information in [brackets] is provided to aid | ' / + interpretation of the licence. \__/ + + Dynamic Universal Music Bibliotheque, Version 0.9.3 + + Copyright (C) 2001-2005 Ben Davis, Robert J Ohannessian and Julien Cugniere + + This software is provided 'as-is', without any express or implied warranty. + In no event shall the authors be held liable for any damages arising from + the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, you are requested to acknowledge its use in the product + documentation, along with details on where to get an unmodified version + of this software, but this is not a strict requirement. + + [Note that the above point asks for a link to DUMB, not just a mention. + Googling for DUMB doesn't help much! The URL is "http://dumb.sf.net/".] + + [The link was originally strictly required. This was changed for two + reasons. Firstly, if many projects request an acknowledgement, the list + of acknowledgements can become quite unmanageable. Secondly, DUMB was + placing a restriction on the code using it, preventing people from using + the GNU General Public Licence which disallows any such restrictions. See + http://www.gnu.org/philosophy/bsd.html for more information on this + subject. However, if DUMB plays a significant part in your project, we do + urge you to acknowledge its use.] + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed from or altered in any source + distribution. + + 4. If you are using the Program in someone else's bedroom on any Monday at + 3:05 pm, you are not allowed to modify the Program for ten minutes. [This + clause provided by Inphernic; every licence should contain at least one + clause, the reasoning behind which is far from obvious.] + + 5. Users who wish to use DUMB for the specific purpose of playing music are + required to feed their dog on every full moon (if deemed appropriate). + [This clause provided by Allefant, who couldn't remember what Inphernic's + clause was.] + + 6. No clause in this licence shall prevent this software from being depended + upon by a product licensed under the GNU General Public Licence. If such + a clause is deemed to exist, Debian, then it shall be respected in spirit + as far as possible and all other clauses shall continue to apply in full + force. + + We regret that we cannot provide any warranty, not even the implied warranty + of merchantability or fitness for a particular purpose. + + Some files generated or copied by automake, autoconf and friends are + available in an extra download. These fall under separate licences but are + all free to distribute. Please check their licences as necessary. + + Licence for DUMB-XMMS v0.1 + + DUMB-XMMS v0.1 falls under the GNU General Public License. + + Licence for DUMBOGG v0.5 + + DUMBOGG -- An Ogg Vorbis add-on library for DUMB. + + This package is provided as giftware. You can copy it, redistribute + it, modify it, do whatever you please. The only restriction you have + on what you can do with it is claim you wrote it. You are encouraged, + though not required, to include the name of the library in your credits + page, as well as a web address allowing others to know how they can get + their copy of the library. This library is built on top of the libOgg, + libVorbis, libVorbisFile and DUMB libraries. These libraries come with + additional requirements and restrictions that you must follow in order + to legally use this software. Please read the COPYING files in the + Ogg Vorbis downloads, and please read DUMB's licence.txt file, for full + details on the requirements of those libraries. + + THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +SNESAPU - SNES APU emulator library +<http://www.alpha-ii.com/> + + Copyright © 2001-2006 Alpha-II + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +Musepack Decoder Library +<http://www.musepack.net/> + + Copyright © 2005, The Musepack Development Team. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyrig + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the The Musepack Development Team nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FLAC - Free Lossless Audio Codec + + Copyright © 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + + 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. + +liba52 - a free ATSC A/52 stream decoder +<http://liba52.sourceforge.net/> + + Copyright © 2000-2002 Michel Lespinasse <walken@zoy.org> + Copyright © 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + + 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. + +shnplay.h + + Copyright © 2003-2005 Marc Heubeck and Holger Stenger All rights reserved. + + Redistribution and use in source form, with or without modification, are + permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + Redistribution and use in binary form, without modification, are permitted + for non-commercial purposes provided that the following conditions are met: + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + Redistribution and use under different conditions than the aforementioned + require specific prior written permission by the author. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +Gens APU from Gens +<http://info.sonicretro.org/Gens/GS> + + Copyright © 2002 by Stéphane Dallongeville + + 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. + +FAAD2 - MPEG-4 and MPEG-2 AAC decoder +<http://www.audiocoding.com/faad2.html> + + Copyright © 2002-2005 M. Bakker + Copyright © 2003-2005 Ahead Software AG + Copyright © 2003-2005 Nero AG + + 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. + +vgmstream - library for playback of various video game audio formats +<http://vgmstream.sourceforge.net/> + + Copyright © 2008-2009 Adam Gashlin, Fastelbja, Ronny Elfert + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +nosefart - NES sound format player +<http://nosefart.sourceforge.net/> + + Copyright © 1998-2000 Matthew Conte (matt@conte.com) + + 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. + +MAD - MPEG Audio Decoder +<http://www.underbit.com/products/mad/> + + Copyright © 2000-2004 Underbit Technologies, Inc + + 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. + +SID Player Music Library V2 +<http://sidplay2.sourceforge.net/> + + Copyright © Michael Schwendt <mschwendt@yahoo.com> + Copyright © 2000 by Simon White + Copyright © 2001-2002 by Jarno Paananen + Copyright © 2004 Dag Lem <resid@nimrod.no> + + 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. + +Monkey’s Audio Codec +<http://www.monkeysaudio.com/> + + Copyright © 2000-2002 by Matthew T. Ashland. All rights reserved. + + 1. The Monkey's Audio SDK and source code can be freely used to add APE + format playback, encoding, or tagging support to any product, free or + commercial. Use of the code for proprietary efforts that don't support + the official APE format require written consent of the author. + + 2. Monkey's Audio source can be included in GPL and open-source software, + although Monkey's Audio itself will not be subjected to external + licensing requirements or other viral source restrictions. + + 3. Code changes and improvements must be contributed back to the Monkey's + Audio project free from restrictions or royalties, unless exempted by + express written consent of the author. + + 4. Any source code, ideas, or libraries used must be plainly acknowledged in + the software using the code. + + 5. Although the software has been tested thoroughly, the author is in no way + responsible for damages due to bugs or misuse. + + 6. If you do not completely agree with all of the previous stipulations, you + must cease using this source code and remove it from your storage device. + +Xbox ADPCM audio codec +<http://www.winamp.com/plugins/details/147392> + + Copyright © Luigi Auriemma + + 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. + +ST-Sound - general "Nostalgic" Computer Sound Emulator +<http://leonard.oxg.free.fr> + + Copyright © 1995-1999 Arnaud Carré ( http://leonard.oxg.free.fr ) + + 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. + +TiMidity++ - software synthesizer +<http://timidity.sourceforge.net/> + + Copyright © 1999-2002 Masanao Izumo <mo@goice.co.jp> + Copyright © 1995 Tuukka Toivonen <tt@cgs.fi> + + 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. + +WavPack - an audio codec (lossy and lossless) +<http://www.wavpack.com/> + + Copyright © 1998 - 2006 Conifer Software + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Conifer Software nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +FFmpeg - complete, cross-platform solution to record, convert and stream audio +and video +<http://www.ffmpeg.org/> + + Copyright © Fabrice Bellard + Copyright © Alex Beregszaszi + Copyright © BERO + Copyright © Mario Brito + Copyright © Ronald Bultje + Copyright © Tim Ferguson + Copyright © Brian Foley + Copyright © Arpad Gereoffy + Copyright © Philip Gladstone + Copyright © Vladimir Gneushev + Copyright © Wolfgang Hesseler + Copyright © Falk Hueffner + Copyright © Zdenek Kabelac + Copyright © Robin Kay + Copyright © Todd Kirby + Copyright © Nick Kurshev + Copyright © Mike Melanson + Copyright © Michael Niedermayer + Copyright © François Revol + Copyright © Roman Shaposhnik + Copyright © Dieter Shirley + Copyright © Juan J. Sierralta + Copyright © Ewald Snel + Copyright © Leon van Stuivenberg + Copyright © Roberto Togni + Copyright © Lionel Ulmer + + Falls under two licenses, the LGPL-2.1 and GPL-2. + + LGPL-2.1 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + + GPL-2 + + 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. + +nuttcp - TCP/UDP network testing tool +<http://www.lcp.nrl.navy.mil/nuttcp/> + + Copyright © 1995-1999 WIDE Project. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + Portions have different copyright and license + + Copyright © 1995, 1996, 1997 Kungliga Tekniska Högskolan + (Royal Institute of Technology, Stockholm, Sweden). + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the Kungliga Tekniska + Högskolan and its contributors. + + 4. Neither the name of the Institute nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +libdvdnav and libdvdread - libraries to read DVDs and navigate DVD menus +<http://www.mplayerhq.hu/> + + Copyright © 2001-2004 Rich Wareham <richwareham@users.sourceforge.net> + Copyright © 2000, 2001, 2002 H�kan Hjort <d95hjort@dtek.chalmers.se> + Copyright © 1998, 1999 Eric Smith <eric@brouhaha.com> + Copyright © 2001, 2002 Billy Biggs <vektor@dumbterm.net> + Copyright © 2000, 2001 Martin Norb�ck + Copyright © 2000, 2001 Bj�rn Englund + + 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. + +libdca - free library for decoding DTS Coherent Acoustics streams +<http://www.videolan.org/developers/libdca.html> + + Copyright © 2004 Gildas Bazin <gbazin@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. + +libspucc - library that's part of the Xine project +<http://www.xine-project.org/home> + + Copyright © 2000-2008 the xine project + Copyright © Christian Vogler cvogler@gradient.cis.upenn.edu - December 2001 + + 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. + +libmpeg2 - a free MPEG-2 video stream decoder +<http://libmpeg2.sourceforge.net/> + + Copyright © 2000-2004 Michel Lespinasse <walken@zoy.org> + Copyright © 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + + 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. + +libdvdcss - library designed for accessing encrypted DVDs +<http://www.videolan.org/developers/libdvdcss.html> + + Copyright © 1999-2001 VideoLAN + + 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. + +Sample frequency change classes + + Copyright © Spoon (www.dbpoweramp.com) March 2002 dbpoweramp@dbpoweramp.com + + The code is based on original SSRC by Naoki Shibata + <http://shibatch.sourceforge.net/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +xbmc-xrandr.c + + Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + Copyright © 2002 Hewlett Packard Company, Inc. + Copyright © 2006 Intel Corporation + + Permission to use, copy, modify, distribute, and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice appear in all copies and that both that copyright + notice and this permission notice appear in supporting documentation, and + that the name of the copyright holders not be used in advertising or + publicity pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no representations + about the suitability of this software for any purpose. It is provided "as + is" without express or implied warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + OF THIS SOFTWARE. + +HomeSystemIcon in PM3.HD skin +<http://www.icons-land.com/> + + Copyright © Icons-Land + + This is a legal agreement between you, the purchaser, and the Icons-Land. By + purchasing or downloading any stock icons (The Icons) from our website you + agree to the following: + + All of The Icons remain the property of Icons-Land. + + The Icons can be used royalty-free by the license for any personal or + commercial project including software application, documentation, computer + game, gui design, web design, advertising, film, video. + You may modify The Icons in shape, color, and/or file format and use the + modified icons royalty-free according to the license terms for any personal + or commercial product. + + The license DOES NOT permit following uses: + a) The Icons may no be resold, sublicensed, rented, transferred or otherwise + made available for use or detached from a product, software application + or web page; + b) The Icons may not be placed on any electronic bulletin board or + downloadable format; + c) The Icons may not be included in any web template, including those which + are web based, but not limited to website designs and presentation + templates. + + You may NOT use, or allow anyone else to use The Icons to create + pornographic, libelous, obscene, or defamatory material. + + All icon files are provided "as is". You agree not to hold Icons-Land liable + for any damages that may occur due to use, or inability to use, icons or + image data from Icons-Land. + +xbmc/Crc32.cpp and xbmc/Crc32.h + + Copyright (C) 2005-2009 Team XBMC + http://www.xbmc.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. + + Portion of this code was taken from efone. + efone - Distributed internet phone system. + + (c) 1999,2000 Krzysztof Dabrowski + (c) 1999,2000 ElysiuM deeZine + + 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. + + based on implementation by Finn Yannick Jacobs + +Licenses: + +License: GPL + +A copy of the GPL can be found on Debian systems at +/usr/share/common-licenses/GPL. + +License: LGPL + +A copy of the LGPL can be found on Debian systems at +/usr/share/common-licenses/LGPL. + +License: FTL + The FreeType Project LICENSE + ---------------------------- + + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright © <year> The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace <year> with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + http://www.freetype.org + + +--- end of FTL --- + +License: GoAhead Open Source License + +License Agreement + +THIS LICENSE ALLOWS ONLY THE LIMITED USE OF GO AHEAD SOFTWARE, +INC. PROPRIETARY CODE. PLEASE CAREFULLY READ THIS AGREEMENT AS IT +PERTAINS TO THIS LICENSE, YOU CERTIFY THAT YOU WILL USE THE SOFTWARE +ONLY IN THE MANNER PERMITTED HEREIN. + +1. Definitions. + +1.1 "Documentation" means any documentation GoAhead includes with the + Original Code. + +1.2 "GoAhead" means Go Ahead Software, Inc. + +1.3 "Intellectual Property Rights" means all rights, whether now existing + or hereinafter acquired, in and to trade secrets, patents, copyrights, + trademarks, know-how, as well as moral rights and similar rights of any + type under the laws of any governmental authority, domestic or foreign, + including rights in and to all applications and registrations relating + to any of the foregoing. + +1.4 "License" or "Agreement" means this document. + +1.5 "Modifications" means any addition to or deletion from the substance + or structure of either the Original Code or any previous Modifications. + +1.6 "Original Code" means the Source Code to GoAhead�s proprietary + computer software entitled GoAhead WebServer. + +1.7 "Response Header" means the first portion of the response message + output by the GoAhead WebServer, containing but not limited to, header + fields for date, content-type, server identification and cache control. + +1.8 "Server Identification Field" means the field in the Response Header + which contains the text "Server: GoAhead-Webs". + +1.9 "You" means an individual or a legal entity exercising rights under, + and complying with all of the terms of, this license or a future version + of this license. For legal entities, "You" includes any entity which + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct or + indirect, to cause the direction or management of such entity, whether + by contract or otherwise, or (b) ownership of fifty percent (50%) or + more of the outstanding shares or beneficial ownership of such entity. + +2. Source Code License. + +2.1 Limited Source Code Grant. + +GoAhead hereby grants You a world-wide, royalty-free, non-exclusive +license, subject to third party intellectual property claims, to use, +reproduce, modify, copy and distribute the Original Code. + +2.2 Binary Code. + +GoAhead hereby grants You a world-wide, royalty-free, non-exclusive +license to copy and distribute the binary code versions of the Original +Code together with Your Modifications. + +2.3 License Back to GoAhead. + +You hereby grant in both source code and binary code to GoAhead a +world-wide, royalty-free, non-exclusive license to copy, modify, display, +use and sublicense any Modifications You make that are distributed or +planned for distribution. Within 30 days of either such event, You +agree to ship to GoAhead a file containing the Modifications (in a media +to be determined by the parties), including any programmers� notes and +other programmers� materials. Additionally, You will provide to GoAhead +a complete description of the product, the product code or model number, +the date on which the product is initially shipped, and a contact name, +phone number and e-mail address for future correspondence. GoAhead will +keep confidential all data specifically marked as such. + +2.4 Restrictions on Use. + +You may sublicense Modifications to third parties such as subcontractors +or OEM's provided that You enter into license agreements with such third +parties that bind such third parties to all the obligations under this +Agreement applicable to you and that are otherwise substantially similar +in scope and application to this Agreement. + +3. Term. + +This Agreement and license are effective from the time You accept the +terms of this Agreement until this Agreement is terminated. You may +terminate this Agreement at any time by uninstalling or destroying +all copies of the Original Code including any and all binary versions +and removing any Modifications to the Original Code existing in any +products. This Agreement will terminate immediately and without further +notice if You fail to comply with any provision of this Agreement. All +restrictions on use, and all other provisions that may reasonably +be interpreted to survive termination of this Agreement, will survive +termination of this Agreement for any reason. Upon termination, You agree +to uninstall or destroy all copies of the Original Code, Modifications, +and Documentation. + +4. Trademarks and Brand. + +4.1 License and Use. + +GoAhead hereby grants to You a limited world-wide, royalty-free, +non-exclusive license to use the GoAhead trade names, trademarks, logos, +service marks and product designations posted in Exhibit A (collectively, +the "GoAhead Marks") in connection with the activities by You under this +Agreement. Additionally, GoAhead grants You a license under the terms +above to such GoAhead trademarks as shall be identified at a URL (the +"URL") provided by GoAhead. The use by You of GoAhead Marks shall be in +accordance with GoAhead�s trademark policies regarding trademark usage +as established at the web site designated by the URL, or as otherwise +communicated to You by GoAhead at its sole discretion. You understand and +agree that any use of GoAhead Marks in connection with this Agreement +shall not create any right, title or interest in or to such GoAhead +Marks and that all such use and goodwill associated with GoAhead Marks +will inure to the benefit of GoAhead. + +4.2 Promotion by You of GoAhead WebServer Mark. + +In consideration for the licenses granted by GoAhead to You herein, You +agree to notify GoAhead when You incorporate the GoAhead WebServer in +Your product and to inform GoAhead when such product begins to ship. You +agree to promote the Original Code by prominently and visibly displaying +a graphic of the GoAhead WebServer mark on the initial web page of Your +product that is displayed each time a user connects to it. You also agree +that GoAhead may identify your company as a user of the GoAhead WebServer +in conjunction with its own marketing efforts. You may further promote +the Original Code by displaying the GoAhead WebServer mark in marketing +and promotional materials such as the home page of your web site or web +pages promoting the product. + +4.3 Placement of Copyright Notice by You. + +You agree to include copies of the following notice (the "Notice") +regarding proprietary rights in all copies of the products that You +distribute, as follows: (i) embedded in the object code; and (ii) on +the title pages of all documentation. Furthermore, You agree to use +commercially reasonable efforts to cause any licensees of your products +to embed the Notice in object code and on the title pages or relevant +documentation. The Notice is as follows: Copyright (c) 20xx GoAhead +Software, Inc. All Rights Reserved. Unless GoAhead otherwise instructs, +the year 20xx is to be replaced with the year during which the release of +the Original Code containing the notice is issued by GoAhead. If this year +is not supplied with Documentation, GoAhead will supply it upon request. + +4.4 No Modifications to Server Identification Field. + +You agree not to remove or modify the Server identification Field +contained in the Response Header as defined in Section 1.6 and 1.7. + +5. Warranty Disclaimers. + +THE ORIGINAL CODE, THE DOCUMENTATION AND THE MEDIA UPON WHICH THE ORIGINAL +CODE IS RECORDED (IF ANY) ARE PROVIDED "AS IS" AND WITHOUT WARRANTIES OF +ANY KIND, EXPRESS, STATUTORY OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +The entire risk as to the quality and performance of the Original Code +(including any Modifications You make) and the Documentation is with +You. Should the Original Code or the Documentation prove defective, +You (and not GoAhead or its distributors, licensors or dealers) assume +the entire cost of all necessary servicing or repair. GoAhead does not +warrant that the functions contained in the Original Code will meet your +requirements or operate in the combination that You may select for use, +that the operation of the Original Code will be uninterrupted or error +free, or that defects in the Original Code will be corrected. No oral +or written statement by GoAhead or by a representative of GoAhead shall +create a warranty or increase the scope of this warranty. + +GOAHEAD DOES NOT WARRANT THE ORIGINAL CODE AGAINST INFRINGEMENT OR THE +LIKE WITH RESPECT TO ANY COPYRIGHT, PATENT, TRADE SECRET, TRADEMARK +OR OTHER PROPRIETARY RIGHT OF ANY THIRD PARTY AND DOES NOT WARRANT +THAT THE ORIGINAL CODE DOES NOT INCLUDE ANY VIRUS, SOFTWARE ROUTINE +OR OTHER SOFTWARE DESIGNED TO PERMIT UNAUTHORIZED ACCESS, TO DISABLE, +ERASE OR OTHERWISE HARM SOFTWARE, HARDWARE OR DATA, OR TO PERFORM ANY +OTHER SUCH ACTIONS. + +Any warranties that by law survive the foregoing disclaimers shall +terminate ninety (90) days from the date You received the Original Code. + +6. Limitation of Liability. + +YOUR SOLE REMEDIES AND GOAHEAD'S ENTIRE LIABILITY ARE SET FORTH ABOVE. IN +NO EVENT WILL GOAHEAD OR ITS DISTRIBUTORS OR DEALERS BE LIABLE FOR +DIRECT, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES RESULTING FROM +THE USE OF THE ORIGINAL CODE, THE INABILITY TO USE THE ORIGINAL CODE, +OR ANY DEFECT IN THE ORIGINAL CODE, INCLUDING ANY LOST PROFITS, EVEN IF +THEY HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +You agree that GoAhead and its distributors and dealers will not be +LIABLE for defense or indemnity with respect to any claim against You +by any third party arising from your possession or use of the Original +Code or the Documentation. + +In no event will GoAhead�s total liability to You for all damages, losses, +and causes of action (whether in contract, tort, including negligence, +or otherwise) exceed the amount You paid for this product. + +SOME STATES DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY +LASTS, AND SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION +OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATIONS OR +EXCLUSIONS MAY NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC LEGAL +RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS WHICH VARY FROM STATE TO STATE. + +7. Indemnification by You. + +You agree to indemnify and hold GoAhead harmless against any and all +claims, losses, damages and costs (including legal expenses and reasonable +counsel fees) arising out of any claim of a third party with respect to +the contents of the Your products, and any intellectual property rights +or other rights or interests related thereto. + +8. High Risk Activities. + +The Original Code is not fault-tolerant and is not designed , manufactured +or intended for use or resale as online control equipment in hazardous +environments requiring fail-safe performance, such as in the operation +of nuclear facilities, aircraft navigation or communication systems, +air traffic control, direct life support machines or weapons systems, +in which the failure of the Original Code could lead directly to death, +personal injury, or severe physical or environmental damage. GoAhead and +its suppliers specifically disclaim any express or implied warranty of +fitness for any high risk uses listed above. + +9. Government Restricted Rights. + +For units of the Department of Defense, use, duplication, or disclosure +by the Government is subject to restrictions as set forth in subparagraph +(c)(1)(ii) of the Rights in Technical Data and Computer Software clause +at DFARS 252.227-7013. Contractor/manufacturer is GoAhead Software, +Inc., 10900 N.E. 8th Street, Suite 750, Bellevue, Washington 98004. + +If the Commercial Computer Software Restricted rights clause at FAR +52.227-19 or its successors apply, the Software and Documentation +constitute restricted computer software as defined in that clause and +the Government shall not have the license for published software set +forth in subparagraph (c)(3) of that clause. + +The Original Code (i) was developed at private expense, and no part of it +was developed with governmental funds; (ii) is a trade secret of GoAhead +(or its licensor(s)) for all purposes of the Freedom of Information Act; +(iii) is "restricted computer software" subject to limited utilization as +provided in the contract between the vendor and the governmental entity; +and (iv) in all respects is proprietary data belonging solely to GoAhead +(or its licensor(s)). + +10. Governing Law and Interpretation. + +This Agreement shall be interpreted under and governed by the laws of the +State of Washington, without regard to its rules governing the conflict of +laws. If any provision of this Agreement is held illegal or unenforceable +by a court or tribunal of competent jurisdiction, the remaining provisions +of this Agreement shall remain in effect and the invalid provision deemed +modified to the least degree necessary to remedy such invalidity. + +11. Entire Agreement. + +This Agreement is the complete agreement between GoAhead and You and +supersedes all prior agreements, oral or written, with respect to the +subject matter hereof. + +If You have any questions concerning this Agreement, You may write to +GoAhead Software, Inc., 10900 N.E. 8th Street, Suite 750, Bellevue, +Washington 98004 or send e-mail to info@goahead.com. + +BY CLICKING ON THE "Register" BUTTON ON THE REGISTRATION FORM, YOU +ACCEPT AND AGREE TO BE BOUND BY ALL OF THE TERMS AND CONDITIONS SET +FORTH IN THIS AGREEMENT. IF YOU DO NOT WISH TO ACCEPT THIS LICENSE OR +YOU DO NOT QUALIFY FOR A LICENSE BASED ON THE TERMS SET FORTH ABOVE, +YOU MUST NOT CLICK THE "Register" BUTTON. + +Exhibit A + +GoAhead Trademarks, Logos, and Product Designation Information + + + + +01/28/00 + +-- End of GoAhead Open Source License -- + +License: PSF License for Python 2.4 + +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations (now Zope +Corporation, see http://www.zope.com). In 2001, the Python Software +Foundation (PSF, see http://www.python.org/psf/) was formed, a +non-profit organization created specifically to own Python-related +Intellectual Property. Zope Corporation is a sponsoring member of +the PSF. + +All Python releases are Open Source (see http://www.opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.2 2.1.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2.1 2.2 2002 PSF yes + 2.2.2 2.2.1 2002 PSF yes + 2.2.3 2.2.2 2003 PSF yes + 2.3 2.2.2 2002-2003 PSF yes + 2.3.1 2.3 2002-2003 PSF yes + 2.3.2 2.3.1 2002-2003 PSF yes + 2.3.3 2.3.2 2002-2003 PSF yes + 2.3.4 2.3.3 2004 PSF yes + 2.3.5 2.3.4 2005 PSF yes + 2.4 2.3 2004 PSF yes + 2.4.1 2.4 2005 PSF yes + 2.4.2 2.4.1 2005 PSF yes + 2.4.3 2.4.2 2006 PSF yes + 2.4.4 2.4.3 2006 PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +PSF LICENSE AGREEMENT FOR PYTHON 2.4 +------------------------------------ + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using Python 2.4 software in source or binary form and its +associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 2.4 +alone or in any derivative version, provided, however, that PSF's +License Agreement and PSF's notice of copyright, i.e., "Copyright (c) +2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved" +are retained in Python 2.4 alone or in any derivative version prepared +by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 2.4 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 2.4. + +4. PSF is making Python 2.4 available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.4 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +2.4 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.4, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python 2.4, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the Internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the Internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +-- End of PSF License for Python 2.4 -- + +License: IJG License + +LEGAL ISSUES +============ + +In plain English: + +1. We don't promise that this software works. (But if you find any bugs, + please let us know!) +2. You can use this software for whatever you want. You don't have to pay us. +3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + +In legalese: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + +ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, +sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. +ansi2knr.c is NOT covered by the above copyright and conditions, but instead +by the usual distribution terms of the Free Software Foundation; principally, +that you must include source code if you redistribute it. (See the file +ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part +of any program generated from the IJG code, this does not limit you more than +the foregoing paragraphs do. + +The Unix configuration script "configure" was produced with GNU Autoconf. +It is copyright by the Free Software Foundation but is freely distributable. +The same holds for its supporting scripts (config.guess, config.sub, +ltconfig, ltmain.sh). Another support script, install-sh, is copyright +by M.I.T. but is also freely distributable. + +It appears that the arithmetic coding option of the JPEG spec is covered by +patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot +legally be used without obtaining one or more licenses. For this reason, +support for arithmetic coding has been removed from the free JPEG software. +(Since arithmetic coding provides only a marginal gain over the unpatented +Huffman mode, it is unlikely that very many implementations will support it.) +So far as we are aware, there are no patent restrictions on the remaining +code. + +The IJG distribution formerly included code to read and write GIF files. +To avoid entanglement with the Unisys LZW patent, GIF reading support has +been removed altogether, and the GIF writer has been simplified to produce +"uncompressed GIFs". This technique does not use the LZW algorithm; the +resulting GIF files are larger than usual, but are readable by all standard +GIF decoders. + +We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + +-- End of IJG License -- diff --git a/tools/Linux/debian/patches/series b/tools/Linux/debian/patches/series new file mode 100644 index 0000000000..cafd20572b --- /dev/null +++ b/tools/Linux/debian/patches/series @@ -0,0 +1 @@ +# Nothing to patch diff --git a/tools/Linux/debian/rules b/tools/Linux/debian/rules new file mode 100755 index 0000000000..49b00d2c80 --- /dev/null +++ b/tools/Linux/debian/rules @@ -0,0 +1,92 @@ +#!/usr/bin/make -f + +include /usr/share/quilt/quilt.make + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) + +# Get the SVN revision from the changelog +SVNVERSION ?= $(shell dpkg-parsechangelog | grep '^Version:' | sed 's/.*svn\([[:digit:]]*\).*/\1/') + +# List of options to pass to configure. Can be overridden. +XBMC_CONFIG_OPTIONS ?= --host=$(DEB_HOST_GNU_TYPE) \ + --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --disable-ccache \ + --disable-dvdcss --enable-external-libraries --enable-avahi \ + CFLAGS="$(DEB_CFLAGS)" CXXFLAGS="$(DEB_CXXFLAGS)" + +# Add the SVN revision if it exists in the changelog +ifeq (,$(findstring Version,$(SVNVERSION))) + XBMC_CONFIG_OPTIONS += SVN_REV="$(SVNVERSION)" +endif + +%: + dh $@ + +override_dh_clean: + dh_clean + rm -f debian/xbmc-live.init + debian/rules unpatch + +override_dh_auto_configure: patch + cp -f tools/XBMCLive/xbmc debian/xbmc-live.init + ./configure $(XBMC_CONFIG_OPTIONS) + +override_dh_auto_install: + $(MAKE) install install-livedatas prefix=$(CURDIR)/debian/tmp/usr + $(MAKE) eventclients prefix=$(CURDIR)/debian/tmp/usr \ + installdir=/usr WII_EXTRA_OPTS=-DCWIID_OLD + mkdir -p $(CURDIR)/debian/tmp/usr/share/applications \ + $(CURDIR)/debian/tmp/usr/share/pixmaps + cp $(CURDIR)/tools/Linux/xbmc.png \ + $(CURDIR)/debian/tmp/usr/share/pixmaps/ + cp $(CURDIR)/tools/Linux/xbmc.desktop \ + $(CURDIR)/debian/tmp/usr/share/applications/ + +override_dh_install: + dh_install --sourcedir=$(CURDIR)/debian/tmp -XLICENCE \ + -XLiberationSans-Regular.ttf -XLicence.txt -XLicense.txt + # XBMC WEB EFLEXWEB + mkdir -p $(CURDIR)/debian/xbmc-web-eflexweb/usr/share/xbmc/web + unzip -oq $(CURDIR)/web/WebInterfaceXBMC-0.17.zip \ + -d $(CURDIR)/debian/xbmc-web-eflexweb/usr/share/xbmc/web + # XBMC WEB PM + mkdir -p $(CURDIR)/debian/xbmc-web-pm/usr/share/xbmc/web + unzip -oq $(CURDIR)/web/Project_Mayhem_webserver_V1.1.2.zip \ + -d $(CURDIR)/debian/xbmc-web-pm/usr/share/xbmc/web \ + -x "*/Thumbs.db" + # XBMC WEB Iphone + mkdir -p $(CURDIR)/debian/xbmc-web-iphone-tlrobinson/usr/share/xbmc/web/iphone + unzip -oq $(CURDIR)/web/xbmciphone-0.1.zip \ + -d $(CURDIR)/debian/xbmc-web-iphone-tlrobinson/usr/share/xbmc/web + mkdir -p $(CURDIR)/debian/xbmc-web-iphone-tlrobinson/usr/share/doc/xbmc-web-iphone-tlrobinson/ + mv $(CURDIR)/debian/xbmc-web-iphone-tlrobinson/usr/share/xbmc/web/README \ + $(CURDIR)/debian/xbmc-web-iphone-tlrobinson/usr/share/doc/xbmc-web-iphone-tlrobinson/ + +override_dh_link: + dh_link + install -D "debian/xbmc-data/usr/share/xbmc/xbmc.bin" \ + "debian/xbmc-bin/usr/lib/xbmc/xbmc.bin" + dh_link -pxbmc-data "usr/lib/xbmc/xbmc.bin" \ + "usr/share/xbmc/xbmc.bin" + install -D "debian/xbmc-data/usr/share/xbmc/xbmc-xrandr" \ + "debian/xbmc-bin/usr/lib/xbmc/xbmc-xrandr" + dh_link -pxbmc-data "usr/lib/xbmc/xbmc-xrandr" \ + "usr/share/xbmc/xbmc-xrandr" + find "debian/xbmc-data/usr/share/xbmc" -regextype posix-extended \ + -type f -iregex ".*\.so|.*\.vis|.*\.xbs" | while read FILE; do \ + NEW_LOCATION="$$(echo $$FILE | sed -e 's|/xbmc-data/usr/share|/xbmc-bin/usr/lib|')"; \ + LINK_TARGET="$$(echo "$$NEW_LOCATION" | sed -e 's|debian/xbmc-bin/||')"; \ + LINK_DESTINATION="$$(echo "$$FILE" | sed -e 's|debian/xbmc-data/||')"; \ + install -D "$$FILE" "$$NEW_LOCATION"; \ + dh_link -pxbmc-data "$$LINK_TARGET" "$$LINK_DESTINATION"; \ + done + +override_dh_strip: + dh_strip --dbg-package=xbmc-dbg + +override_dh_makeshlibs: + # We don't install shared libraries in standard locations so don't edit + # postinst/postrm scripts to call ldconfig + dh_makeshlibs -n diff --git a/tools/Linux/debian/watch b/tools/Linux/debian/watch new file mode 100644 index 0000000000..e46e9aadc9 --- /dev/null +++ b/tools/Linux/debian/watch @@ -0,0 +1,4 @@ +version=3 + +opts=uversionmangle=s/\.(tar.*|tgz|zip|gz|bz2)$//i,dversionmangle=s/[-.+~]?(cvs|svn|git|snapshot|pre|hg)(.*)$//i,pasv \ +http://sf.net/xbmc/([\d+\.]+|\d+)-?_?.*?-linux-osx-win32-repack\.(tar.*|tgz|zip|gz|bz2|) debian uupdate diff --git a/tools/Linux/debian/xbmc-data.docs b/tools/Linux/debian/xbmc-data.docs new file mode 100644 index 0000000000..8aea543a3e --- /dev/null +++ b/tools/Linux/debian/xbmc-data.docs @@ -0,0 +1,3 @@ +keymapping.txt +README.linux +keymapping-schematic.pdf diff --git a/tools/Linux/debian/xbmc-data.install b/tools/Linux/debian/xbmc-data.install new file mode 100644 index 0000000000..7265523f26 --- /dev/null +++ b/tools/Linux/debian/xbmc-data.install @@ -0,0 +1,13 @@ +usr/bin/xbmc +usr/share/xbmc/media +usr/share/xbmc/sounds +usr/share/xbmc/language +usr/share/xbmc/userdata +usr/share/xbmc/visualisations +usr/share/xbmc/screensavers +usr/share/xbmc/system +usr/share/pixmaps/xbmc.png +usr/share/applications +usr/share/xbmc/FEH.py +usr/share/xbmc/xbmc.bin +usr/share/xbmc/xbmc-xrandr diff --git a/tools/Linux/debian/xbmc-data.manpages b/tools/Linux/debian/xbmc-data.manpages new file mode 100644 index 0000000000..be7b114687 --- /dev/null +++ b/tools/Linux/debian/xbmc-data.manpages @@ -0,0 +1,2 @@ +docs/manpages/xbmc.bin.1 +docs/manpages/xbmc.1 diff --git a/tools/Linux/debian/xbmc-data.menu b/tools/Linux/debian/xbmc-data.menu new file mode 100644 index 0000000000..50e05291bf --- /dev/null +++ b/tools/Linux/debian/xbmc-data.menu @@ -0,0 +1,2 @@ +?package(xbmc-data):needs="X11" section="Applications/Video" \ + title="xbmc" command="/usr/bin/xbmc" diff --git a/tools/Linux/debian/xbmc-eventclients-common.install b/tools/Linux/debian/xbmc-eventclients-common.install new file mode 100644 index 0000000000..4dbb5060a5 --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-common.install @@ -0,0 +1,2 @@ +usr/lib/python2.5/site-packages/xbmc +usr/share/pixmaps/xbmc diff --git a/tools/Linux/debian/xbmc-eventclients-dev.examples b/tools/Linux/debian/xbmc-eventclients-dev.examples new file mode 100644 index 0000000000..abcee3c87f --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-dev.examples @@ -0,0 +1 @@ +tools/EventClients/examples/* diff --git a/tools/Linux/debian/xbmc-eventclients-dev.install b/tools/Linux/debian/xbmc-eventclients-dev.install new file mode 100644 index 0000000000..23114c9124 --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-dev.install @@ -0,0 +1 @@ +usr/include/xbmc/xbmcclient.h diff --git a/tools/Linux/debian/xbmc-eventclients-j2me.install b/tools/Linux/debian/xbmc-eventclients-j2me.install new file mode 100644 index 0000000000..0a3631dcfb --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-j2me.install @@ -0,0 +1 @@ +usr/bin/xbmc-j2meremote diff --git a/tools/Linux/debian/xbmc-eventclients-j2me.manpages b/tools/Linux/debian/xbmc-eventclients-j2me.manpages new file mode 100644 index 0000000000..0dec8f02d5 --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-j2me.manpages @@ -0,0 +1 @@ +docs/manpages/xbmc-j2meremote.1 diff --git a/tools/Linux/debian/xbmc-eventclients-ps3.install b/tools/Linux/debian/xbmc-eventclients-ps3.install new file mode 100644 index 0000000000..c761b710d8 --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-ps3.install @@ -0,0 +1 @@ +usr/bin/xbmc-ps3remote diff --git a/tools/Linux/debian/xbmc-eventclients-ps3.manpages b/tools/Linux/debian/xbmc-eventclients-ps3.manpages new file mode 100644 index 0000000000..17b0424795 --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-ps3.manpages @@ -0,0 +1 @@ +docs/manpages/xbmc-ps3remote.1 diff --git a/tools/Linux/debian/xbmc-eventclients-wiiremote.install b/tools/Linux/debian/xbmc-eventclients-wiiremote.install new file mode 100644 index 0000000000..f6f7193ee0 --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-wiiremote.install @@ -0,0 +1 @@ +usr/bin/xbmc-wiiremote diff --git a/tools/Linux/debian/xbmc-eventclients-wiiremote.manpages b/tools/Linux/debian/xbmc-eventclients-wiiremote.manpages new file mode 100644 index 0000000000..88aff207ea --- /dev/null +++ b/tools/Linux/debian/xbmc-eventclients-wiiremote.manpages @@ -0,0 +1 @@ +docs/manpages/xbmc-wiiremote.1 diff --git a/tools/Linux/debian/xbmc-get-orig-source b/tools/Linux/debian/xbmc-get-orig-source new file mode 100755 index 0000000000..51c21139cf --- /dev/null +++ b/tools/Linux/debian/xbmc-get-orig-source @@ -0,0 +1,61 @@ +#!/bin/sh + +# This script is used to download the upstream source for xbmc and +# generate it into an orig source tarball for Debian. + +# Common variables used to ease maintenance of this script +XBMC_TARBALL="" +XBMC_TARBALL_CHECKSUM="" +SVN_REVISION="22158" +XBMC_VERSION="9.04.1+svn$SVN_REVISION~deb1" + +USAGE="\n\ +This script is used to generate the orig tarball used in building\n\ +Debian packages for xbmc-$XBMC_VERSION.\n\ +Usage: xbmc-get-orig-source [OPTION]\n\ +\n\ + -h, --help Display this help message.\n\ + --remove-upstream-tarball Remove the upstream source tarball.\n" + +while [ "$#" -gt "0" ] +do + case "$1" in + --remove-upstream-tarball) + REMOVE_UPSTREAM_TARBALL=1 + shift + ;; + -h|--help|*) + echo "${USAGE}" + exit 1 + ;; + esac +done + +# This will generate the orig.tar.gz +make_current_tarball() { + # We do a checkout of the external-libraries-support branch at a specified + # revision + svn co -r$SVN_REVISION http://xbmc.svn.sourceforge.net/svnroot/xbmc/branches/linuxport/XBMC xbmc-$XBMC_VERSION + + # Take out the .svn directories + echo "Removing .svn directories" + find xbmc-$XBMC_VERSION -type d -name .svn | while read TMP; do + rm -rf "$TMP" + done + + # Remove libdvdcss + echo "Remove libdvdcss" + rm -rf xbmc-$XBMC_VERSION/xbmc/cores/dvdplayer/Codecs/libdvd/libdvdcss + + # Remove some empty directories and its empty subdirectories + echo "Remove empty directories and its empty subdirectories" + rm -rf xbmc-$XBMC_VERSION/xbmc/cores/dvdplayer/Codecs/libDVDCSS + rm -rf xbmc-$XBMC_VERSION/xbmc/cores/dvdplayer/Codecs/libdvdnav + + # Create the tarball + echo "Create orig tarball" + tar -czf xbmc_$XBMC_VERSION.orig.tar.gz \ + xbmc-$XBMC_VERSION/ +} + +make_current_tarball diff --git a/tools/Linux/debian/xbmc-live.install b/tools/Linux/debian/xbmc-live.install new file mode 100644 index 0000000000..2732055d9c --- /dev/null +++ b/tools/Linux/debian/xbmc-live.install @@ -0,0 +1,4 @@ +usr/bin/diskmounter +usr/bin/installXBMC +usr/bin/runXBMC +usr/bin/setAlsaVolumes diff --git a/tools/Linux/debian/xbmc-live.manpages b/tools/Linux/debian/xbmc-live.manpages new file mode 100644 index 0000000000..4785b88a73 --- /dev/null +++ b/tools/Linux/debian/xbmc-live.manpages @@ -0,0 +1,4 @@ +docs/manpages/diskmounter.1 +docs/manpages/installXBMC.1 +docs/manpages/runXBMC.1 +docs/manpages/setAlsaVolumes.1 diff --git a/tools/Linux/debian/xbmc-live.postinst b/tools/Linux/debian/xbmc-live.postinst new file mode 100644 index 0000000000..2a59f13a31 --- /dev/null +++ b/tools/Linux/debian/xbmc-live.postinst @@ -0,0 +1,119 @@ +#!/bin/sh + +set -e + +case "$1" in + configure) + # TODO: What's the purpose of this line? As I see it, if 'xbmc' can't + # get a console session going, we're in trouble anyway. ceros + sed -i.bak-xbmc-live s/allowed_users=console/allowed_users=anybody/ /etc/X11/Xwrapper.config + + # Add the 'xbmc' user + if ! getent passwd xbmc >/dev/null; then + adduser \ + --gecos "XBMC Live User" \ + --disabled-password \ + xbmc >/dev/null + fi + # Add 'xbmc' user to the appropriate groups + # TODO: this probably isn't necessary anymore as PolicyKit is now being + # used + # For reading system logs (still not sure why xbmc needs this though) + if ! getent group adm | grep xbmc > /dev/null; then + adduser xbmc adm || true + fi + # For optical disc drive access + if ! getent group cdrom | grep xbmc > /dev/null; then + adduser xbmc cdrom || true + fi + # For floppy drive access + if ! getent group floppy | grep xbmc > /dev/null; then + adduser xbmc floppy || true + fi + # For audio device access + if ! getent group audio | grep xbmc > /dev/null; then + adduser xbmc audio || true + fi + # For video device access + if ! getent group video | grep xbmc > /dev/null; then + adduser xbmc video || true + fi + # To enable automatic notifications of new devices + if ! getent group plugdev | grep xbmc > /dev/null; then + adduser xbmc plugdev || true + fi + # For managing network connections via NetworkManager + if ! getent group netdev | grep xbmc > /dev/null; then + adduser xbmc netdev || true + fi + # To be able to hibernate/suspend + if ! getent group powerdev | grep xbmc > /dev/null; then + adduser xbmc powerdev || true + fi + # To be able to mount filesystems as normal user + if ! getent group fuse | grep xbmc > /dev/null; then + adduser xbmc fuse || true + fi + + # Our set of PolicyKit actions + + # This is a list of actions that the 'xbmc' user should be allowed to + # do. If we missed one, or we have one that's not necessary, please + # submit a bug report. + POLKIT_ACTIONS="org.freedesktop.hal.dockstation.undock + org.freedesktop.hal.wol.enabled + org.freedesktop.hal.wol.enable + org.freedesktop.hal.wol.supported + org.freedesktop.hal.leds.brightness + org.freedesktop.hal.device-access.audio-player + org.freedesktop.hal.device-access.camera + org.freedesktop.hal.device-access.cdrom + org.freedesktop.hal.device-access.dvb + org.freedesktop.hal.device-access.fingerprint-reader + org.freedesktop.hal.device-access.floppy + org.freedesktop.hal.device-access.ieee1394-avc + org.freedesktop.hal.device-access.ieee1394-iidc + org.freedesktop.hal.device-access.joystick + org.freedesktop.hal.device-access.mouse + org.freedesktop.hal.device-access.obex + org.freedesktop.hal.device-access.pda + org.freedesktop.hal.device-access.printer + org.freedesktop.hal.device-access.scanner + org.freedesktop.hal.device-access.sound + org.freedesktop.hal.device-access.video + org.freedesktop.hal.device-access.video4linux + org.freedesktop.hal.lock + org.freedesktop.hal.killswitch.bluetooth + org.freedesktop.hal.killswitch.wlan + org.freedesktop.hal.killswitch.wwan + org.freedesktop.hal.storage.mount-removable + org.freedesktop.hal.storage.eject + org.freedesktop.hal.storage.crypto-setup-removable + org.freedesktop.hal.power-management.shutdown + org.freedesktop.hal.power-management.reboot + org.freedesktop.hal.power-management.set-powersave + org.freedesktop.hal.power-management.suspend + org.freedesktop.hal.power-management.hibernate + org.freedesktop.hal.power-management.cpufreq + org.freedesktop.hal.power-management.lcd-panel + org.freedesktop.hal.power-management.light-sensor + org.freedesktop.hal.power-management.keyboard-backlight" + + # Grant the 'xbmc' user each action from the list + for ACTION in $POLKIT_ACTIONS; do + polkit-auth --user xbmc --grant $ACTION || true + done + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 diff --git a/tools/Linux/debian/xbmc-scripts-example.install b/tools/Linux/debian/xbmc-scripts-example.install new file mode 100644 index 0000000000..a8d3ff846d --- /dev/null +++ b/tools/Linux/debian/xbmc-scripts-example.install @@ -0,0 +1 @@ +usr/share/xbmc/scripts diff --git a/tools/Linux/debian/xbmc-skin-pm3-hd.install b/tools/Linux/debian/xbmc-skin-pm3-hd.install new file mode 100644 index 0000000000..5b8c81ed6c --- /dev/null +++ b/tools/Linux/debian/xbmc-skin-pm3-hd.install @@ -0,0 +1 @@ +usr/share/xbmc/skin/PM3.HD diff --git a/tools/Linux/debian/xbmc-skin-pm3-hd.links b/tools/Linux/debian/xbmc-skin-pm3-hd.links new file mode 100644 index 0000000000..c3b7e2cd06 --- /dev/null +++ b/tools/Linux/debian/xbmc-skin-pm3-hd.links @@ -0,0 +1 @@ +/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Regular.ttf usr/share/xbmc/skin/PM3.HD/fonts/LiberationSans-Regular.ttf diff --git a/tools/Linux/debian/xbmc-skin-pm3.install b/tools/Linux/debian/xbmc-skin-pm3.install new file mode 100644 index 0000000000..8284d6cc24 --- /dev/null +++ b/tools/Linux/debian/xbmc-skin-pm3.install @@ -0,0 +1 @@ +usr/share/xbmc/skin/Project* diff --git a/tools/Linux/debian/xbmc-standalone.install b/tools/Linux/debian/xbmc-standalone.install new file mode 100644 index 0000000000..67465525c9 --- /dev/null +++ b/tools/Linux/debian/xbmc-standalone.install @@ -0,0 +1,2 @@ +usr/bin/xbmc-standalone +usr/share/xsessions diff --git a/tools/Linux/debian/xbmc-standalone.manpages b/tools/Linux/debian/xbmc-standalone.manpages new file mode 100644 index 0000000000..3508af7ca7 --- /dev/null +++ b/tools/Linux/debian/xbmc-standalone.manpages @@ -0,0 +1 @@ +docs/manpages/xbmc-standalone.1 diff --git a/tools/Linux/debian/xbmc-web-pm3.install b/tools/Linux/debian/xbmc-web-pm3.install new file mode 100644 index 0000000000..08f41ed565 --- /dev/null +++ b/tools/Linux/debian/xbmc-web-pm3.install @@ -0,0 +1 @@ +usr/share/xbmc/web diff --git a/tools/Linux/debian/xbmc.lintian-overrides b/tools/Linux/debian/xbmc.lintian-overrides new file mode 100644 index 0000000000..0043e1c5b6 --- /dev/null +++ b/tools/Linux/debian/xbmc.lintian-overrides @@ -0,0 +1,3 @@ +# XBMC is a recursive acronym for "XBMC Media Center", hence why it appears +# at the start of the package description. +xbmc: description-starts-with-package-name diff --git a/tools/Linux/xbmc-standalone.sh b/tools/Linux/xbmc-standalone.sh new file mode 100644 index 0000000000..04d90bd9af --- /dev/null +++ b/tools/Linux/xbmc-standalone.sh @@ -0,0 +1,3 @@ +#!/bin/sh +xbmc --standalone "$@" + diff --git a/tools/Linux/xbmc-xsession.desktop b/tools/Linux/xbmc-xsession.desktop new file mode 100644 index 0000000000..3e5bd49a3f --- /dev/null +++ b/tools/Linux/xbmc-xsession.desktop @@ -0,0 +1,5 @@ +[Desktop Entry] +Type=XSession +Exec=xbmc-standalone +TryExec=xbmc-standalone +Name=XBMC diff --git a/tools/Linux/xbmc.desktop b/tools/Linux/xbmc.desktop new file mode 100644 index 0000000000..a3ac6d423c --- /dev/null +++ b/tools/Linux/xbmc.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Name=XBMC Media Center +GenericName=Media Center +Comment=Manage and view your media +Exec=xbmc +Icon=xbmc.png +Terminal=false +Type=Application +Categories=AudioVideo;Video;Player;TV; diff --git a/tools/Linux/xbmc.png b/tools/Linux/xbmc.png Binary files differnew file mode 100644 index 0000000000..cce81767fb --- /dev/null +++ b/tools/Linux/xbmc.png diff --git a/tools/Linux/xbmc.sh.in b/tools/Linux/xbmc.sh.in new file mode 100644 index 0000000000..1a93b7998a --- /dev/null +++ b/tools/Linux/xbmc.sh.in @@ -0,0 +1,73 @@ +#!/bin/bash + +function print_crash_report() +{ + FILE="xbmc_crashlog-`date +%Y%m%d_%H%M%S`.log" + CORE=`ls -d core* | head -n1` + echo "############## XBMC CRASH LOG ###############" >> $FILE + echo >> $FILE + echo "################ SYSTEM INFO ################" >> $FILE + echo -n " Date: " >> $FILE + date >> $FILE + echo " XBMC Options: $*" >> $FILE + echo -n " Arch: " >> $FILE + uname -m >> $FILE + echo -n " Kernel: " >> $FILE + uname -rvs >> $FILE + echo -n " Release: " >> $FILE + if which lsb_release &> /dev/null; then + echo >> $FILE + lsb_release -a 2> /dev/null | sed -e 's/^/ /' >> $FILE + else + echo "lsb_release not available" >> $FILE + fi + echo "############## END SYSTEM INFO ##############" >> $FILE + echo >> $FILE + echo "############### STACK TRACE #################" >> $FILE + gdb @prefix@/share/xbmc/xbmc.bin --core=$CORE --batch -ex "thread apply all bt" 2> /dev/null >> $FILE + rm -f $CORE + echo "############# END STACK TRACE ###############" >> $FILE + echo >> $FILE + echo "################# LOG FILE ##################" >> $FILE + echo >> $FILE + if [[ -f ~/.xbmc/temp/xbmc.log ]] + then + cat ~/.xbmc/temp/xbmc.log >> $FILE + echo >> $FILE + else + echo "Logfile not found in the usual place." >> $FILE + echo "Please attach it seperately." >> $FILE + echo "Use pastebin.com or similar for forums or IRC." >> $FILE + fi + echo >> $FILE + echo "############### END LOG FILE ################" >> $FILE + echo >> $FILE + echo "############ END XBMC CRASH LOG #############" >> $FILE + echo "Crash report available at $PWD/$FILE" +} + +# Set XBMC_HOME if xbmc.bin is a symlink +if [ -L @prefix@/share/xbmc/xbmc.bin ]; then + export XBMC_HOME="@prefix@/share/xbmc" +fi + +python @prefix@/share/xbmc/FEH.py "$@" +if [ $? -ne 0 ]; then + exit +fi +LOOP=1 +ulimit -c unlimited +while (( $LOOP )) +do + LOOP=0 + @prefix@/share/xbmc/xbmc.bin "$@" + RET=$? + if (( $RET == 65 )) + then + LOOP=1 + elif (( ($RET >= 131 && $RET <= 136) || $RET == 139 )) + then + print_crash_report + fi +done + diff --git a/tools/Mach5/Makefile b/tools/Mach5/Makefile new file mode 100644 index 0000000000..c134f13523 --- /dev/null +++ b/tools/Mach5/Makefile @@ -0,0 +1,5 @@ +default: + +python: ../../xbmc/lib/libPython/Python/python24-osx.so + ./mach5.rb $< + ./mach5.rb output.so libpython diff --git a/tools/Mach5/bit-struct.rb b/tools/Mach5/bit-struct.rb new file mode 100644 index 0000000000..ea2e17d4b9 --- /dev/null +++ b/tools/Mach5/bit-struct.rb @@ -0,0 +1,12 @@ +# A Convenience to load all field classes and yaml handling. + +require 'bit-struct/unsigned-field' +require 'bit-struct/signed-field' +require 'bit-struct/octet-field' +require 'bit-struct/hex-octet-field' +require 'bit-struct/char-field' +require 'bit-struct/text-field' +require 'bit-struct/nested-field' +require 'bit-struct/float-field' +require 'bit-struct/pad-field' +require 'bit-struct/yaml' diff --git a/tools/Mach5/bit-struct/bit-struct.rb b/tools/Mach5/bit-struct/bit-struct.rb new file mode 100644 index 0000000000..27af66bd09 --- /dev/null +++ b/tools/Mach5/bit-struct/bit-struct.rb @@ -0,0 +1,515 @@ +# Class for packed binary data, with defined bitfields and accessors for them. +# See {intro.txt}[link:../doc/files/intro_txt.html] for an overview. +# +# Data after the end of the defined fields is accessible using the +rest+ +# declaration. See examples/ip.rb. Nested fields can be declared using +nest+. +# See examples/nest.rb. +# +# Note that all string methods are still available: length, grep, etc. +# The String#replace method is useful. +# +class BitStruct < String + + class Field + # Offset of field in bits. + attr_reader :offset + + # Length of field in bits. + attr_reader :length + alias size length + + # Name of field (used for its accessors). + attr_reader :name + + # Options, such as :default (varies for each field subclass). + # In general, options can be provided as strings or as symbols. + attr_reader :options + + # Display name of field (used for printing). + attr_reader :display_name + + # Default value. + attr_reader :default + + # Format for printed value of field. + attr_reader :format + + # Subclasses can override this to define a default for all fields of this + # class, not just the one currently being added to a BitStruct class, a + # "default default" if you will. The global default, if #default returns + # nil, is to fill the field with zero. Most field classes just let this + # default stand. The default can be overridden per-field when a BitStruct + # class is defined. + def self.default; nil; end + + # Used in describe. + def self.class_name + @class_name ||= name[/\w+$/] + end + + # Used in describe. Can be overridden per-subclass, as in NestedField. + def class_name + self.class.class_name + end + + # Yield the description of this field, as an array of 5 strings: byte + # offset, type, name, size, and description. The opts hash may have: + # + # :expand :: if the value is true, expand complex fields + # + # (Subclass implementations may yield more than once for complex fields.) + # + def describe opts + bits = size + if bits > 32 and bits % 8 == 0 + len_str = "%dB" % (bits/8) + else + len_str = "%db" % bits + end + + byte_offset = offset / 8 + (opts[:byte_offset] || 0) + + yield ["@%d" % byte_offset, class_name, name, len_str, display_name] + end + + # Options are _display_name_, _default_, and _format_ (subclasses of Field + # may add other options). + def initialize(offset, length, name, opts = {}) + @offset, @length, @name, @options = + offset, length, name, opts + + @display_name = opts[:display_name] || opts["display_name"] + @default = opts[:default] || opts["default"] || self.class.default + @format = opts[:format] || opts["format"] + end + + # Inspect the value of this field in the specified _obj_. + def inspect_in_object(obj, opts) + val = obj.send(name) + str = + begin + val.inspect(opts) + rescue ArgumentError # assume: "wrong number of arguments (1 for 0)" + val.inspect + end + (f=@format) ? (f % str) : str + end + + # Normally, all fields show up in inspect, but some, such as padding, + # should not. + def inspectable?; true; end + end + + NULL_FIELD = Field.new(0, 0, :null, :display_name => "null field") + + # Raised when a field is added after an instance has been created. Fields + # cannot be added after this point. + class ClosedClassError < StandardError; end + + # Raised if the chosen field name is not allowed, either because another + # field by that name exists, or because a method by that name exists. + class FieldNameError < StandardError; end + + @default_options = {} + + class << self + # ------------------------ + # :section: field access methods + # + # For introspection and metaprogramming. + # + # ------------------------ + + # Return the list of fields for this class. + def fields + @fields ||= self == BitStruct ? [] : superclass.fields.dup + end + + # Return the list of fields defined by this class, not inherited + # from the superclass. + def own_fields + @own_fields ||= [] + end + + # Add a field to the BitStruct (usually, this is only used internally). + def add_field(name, length, opts = {}) + round_byte_length ## just to make sure this has been calculated + ## before adding anything + + name = name.to_sym + + if @closed + raise ClosedClassError, "Cannot add field #{name}: " + + "The definition of the #{self.inspect} BitStruct class is closed." + end + + if fields.find {|f|f.name == name} + raise FieldNameError, "Field #{name} is already defined as a field." + end + + if instance_methods(true).find {|m| m == name} + if opts[:allow_method_conflict] || opts["allow_method_conflict"] + warn "Field #{name} is already defined as a method." + else + raise FieldNameError,"Field #{name} is already defined as a method." + end + end + + field_class = opts[:field_class] + + prev = fields[-1] || NULL_FIELD + offset = prev.offset + prev.length + field = field_class.new(offset, length, name, opts) + field.add_accessors_to(self) + fields << field + own_fields << field + @bit_length += field.length + @round_byte_length = (bit_length/8.0).ceil + + if @initial_value + diff = @round_byte_length - @initial_value.length + if diff > 0 + @initial_value << "\0" * diff + end + end + + field + end + + def parse_options(ary, default_name, default_field_class) # :nodoc: + opts = ary.grep(Hash).first || {} + opts = default_options.merge(opts) + + opts[:display_name] = ary.grep(String).first || default_name + opts[:field_class] = ary.grep(Class).first || default_field_class + + opts + end + + # Get or set the hash of default options for the class, which apply to all + # fields. Changes take effect immediately, so can be used alternatingly with + # blocks of field declarations. If +h+ is provided, update the default + # options with that hash. Default options are inherited. + # + # This is especially useful with the <tt>:endian => val</tt> option. + def default_options h = nil + @default_options ||= superclass.default_options.dup + if h + @default_options.merge! h + end + @default_options + end + + # Length, in bits, of this object. + def bit_length + @bit_length ||= fields.inject(0) {|a, f| a + f.length} + end + + # Length, in bytes (rounded up), of this object. + def round_byte_length + @round_byte_length ||= (bit_length/8.0).ceil + end + + def closed! # :nodoc: + @closed = true + end + + def field_by_name name + @field_by_name ||= {} + field = @field_by_name[name] + unless field + field = fields.find {|f| f.name == name} + @field_by_name[name] = field if field + end + field + end + end + + # Return the list of fields for this class. + def fields + self.class.fields + end + + # Return the field with the given name. + def field_by_name name + self.class.field_by_name name + end + + # ------------------------ + # :section: metadata inspection methods + # + # Methods to textually describe the format of a BitStruct subclass. + # + # ------------------------ + + class << self + # Default format for describe. Fields are byte, type, name, size, + # and description. + DESCRIBE_FORMAT = "%8s: %-12s %-14s[%4s] %s" + + # Can be overridden to use a different format. + def describe_format + DESCRIBE_FORMAT + end + + # Textually describe the fields of this class of BitStructs. + # Returns a printable table (array of line strings), based on +fmt+, + # which defaults to #describe_format, which defaults to +DESCRIBE_FORMAT+. + def describe(fmt = nil, opts = {}) + if block_given? + fields.each do |field| + field.describe(opts) do |desc| + yield desc + end + end + nil + + else + fmt ||= describe_format + + result = [] + + unless opts[:omit_header] + result << fmt % ["byte", "type", "name", "size", "description"] + result << "-"*70 + end + + fields.each do |field| + field.describe(opts) do |desc| + result << fmt % desc + end + end + + unless opts[:omit_footer] + result << @note if @note + end + + result + end + end + + # Subclasses can use this to append a string (or several) to the #describe + # output. Notes are not cumulative with inheritance. When used with no + # arguments simply returns the note string + def note(*str) + @note = str unless str.empty? + @note + end + end + + # ------------------------ + # :section: initialization and conversion methods + # + # ------------------------ + + # Initialize the string with the given string or bitstruct, or with a hash of + # field=>value pairs, or with the defaults for the BitStruct subclass. Fields + # can be strings or symbols. Finally, if a block is given, yield the instance + # for modification using accessors. + def initialize(value = nil) # :yields: instance + self << self.class.initial_value + + case value + when Hash + value.each do |k, v| + send "#{k}=", v + end + + when nil + + else + self[0, value.length] = value + end + + self.class.closed! + yield self if block_given? + end + + DEFAULT_TO_H_OPTS = { + :convert_keys => :to_sym, + :include_rest => true + } + + # Returns a hash of {name=>value,...} for each field. By default, include + # the rest field. + # Keys are symbols derived from field names using +to_sym+, unless + # <tt>opts[:convert_keys]<\tt> is set to some other method name. + def to_h(opts = DEFAULT_TO_H_OPTS) + converter = opts[:convert_keys] || :to_sym + + fields_for_to_h = fields + if opts[:include_rest] and (rest_field = self.class.rest_field) + fields_for_to_h += [rest_field] + end + + fields_for_to_h.inject({}) do |h,f| + h[f.name.send(converter)] = send(f.name) + h + end + end + + # Returns an array of values of the fields of the BitStruct. By default, + # include the rest field. + def to_a(include_rest = true) + ary = + fields.map do |f| + send(f.name) + end + + if include_rest and (rest_field = self.class.rest_field) + ary << send(rest_field.name) + end + end + + class << self + # The unique "prototype" object from which new instances are copied. + # The fields of this instance can be modified in the class definition + # to set default values for the fields in that class. (Otherwise, defaults + # defined by the fields themselves are used.) A copy of this object is + # inherited in subclasses, which they may override using defaults and + # by writing to the initial_value object itself. + # + # If called with a block, yield the initial value object before returning + # it. Useful for customization within a class definition. + # + def initial_value # :yields: the initial value + unless @initial_value + iv = defined?(superclass.initial_value) ? + superclass.initial_value.dup : "" + if iv.length < round_byte_length + iv << "\0" * (round_byte_length - iv.length) + end + + @initial_value = "" # Serves as initval while the real initval is inited + @initial_value = new(iv) + @closed = false # only creating the first _real_ instance closes. + + fields.each do |field| + @initial_value.send("#{field.name}=", field.default) if field.default + end + end + yield @initial_value if block_given? + @initial_value + end + + # Take +data+ (a string or BitStruct) and parse it into instances of + # the +classes+, returning them in an array. The classes can be given + # as an array or a separate arguments. (For parsing a string into a _single_ + # BitStruct instance, just use the #new method with the string as an arg.) + def parse(data, *classes) + classes.flatten.map do |c| + c.new(data.slice!(0...c.round_byte_length)) + end + end + + # Join the given structs (array or multiple args) as a string. + # Actually, the inherited String#+ instance method is the same, as is using + # Array#join. + def join(*structs) + structs.flatten.map {|struct| struct.to_s}.join("") + end + end + + # ------------------------ + # :section: inspection methods + # + # ------------------------ + + DEFAULT_INSPECT_OPTS = { + :format => "#<%s %s>", + :field_format => "%s=%s", + :separator => ", ", + :field_name_meth => :name, + :include_rest => true + } + + DETAILED_INSPECT_OPTS = { + :format => "%s:\n%s", + :field_format => "%30s = %s", + :separator => "\n", + :field_name_meth => :display_name, + :include_rest => true + } + + # A standard inspect method which does not add newlines. + def inspect(opts = DEFAULT_INSPECT_OPTS) + field_format = opts[:field_format] + field_name_meth = opts[:field_name_meth] + + fields_for_inspect = fields.select {|field| field.inspectable?} + if opts[:include_rest] and (rest_field = self.class.rest_field) + fields_for_inspect << rest_field + end + + ary = fields_for_inspect.map do |field| + field_format % + [field.send(field_name_meth), + field.inspect_in_object(self, opts)] + end + + body = ary.join(opts[:separator]) + + opts[:format] % [self.class, body] + end + + # A more visually appealing inspect method that puts each field/value on + # a separate line. Very useful when output is scrolling by on a screen. + # + # (This is actually a convenience method to call #inspect with the + # DETAILED_INSPECT_OPTS opts.) + def inspect_detailed + inspect(DETAILED_INSPECT_OPTS) + end + + # ------------------------ + # :section: field declaration methods + # + # ------------------------ + + # Define accessors for a variable length substring from the end of + # the defined fields to the end of the BitStruct. The _rest_ may behave as + # a String or as some other String or BitStruct subclass. + # + # This does not add a field, which is useful because a superclass can have + # a rest method which accesses subclass data. In particular, #rest does + # not affect the #round_byte_length class method. Of course, any data + # in rest does add to the #length of the BitStruct, calculated as a string. + # Also, _rest_ is not inherited. + # + # The +ary+ argument(s) work as follows: + # + # If a class is provided, use it for the Field class (String by default). + # If a string is provided, use it for the display_name (+name+ by default). + # If a hash is provided, use it for options. + # + # *Warning*: the rest reader method returns a copy of the field, so + # accessors on that returned value do not affect the original rest field. + # + def self.rest(name, *ary) + if @rest_field + raise ArgumentError, "Duplicate rest field: #{name.inspect}." + end + + opts = parse_options(ary, name, String) + offset = round_byte_length + byte_range = offset..-1 + class_eval do + field_class = opts[:field_class] + define_method name do || + field_class.new(self[byte_range]) + end + + define_method "#{name}=" do |val| + self[byte_range] = val + end + + @rest_field = Field.new(offset, -1, name, { + :display_name => opts[:display_name], + :rest_class => field_class + }) + end + end + + # Not included with the other fields, but accessible separately. + def self.rest_field; @rest_field; end +end diff --git a/tools/Mach5/bit-struct/char-field.rb b/tools/Mach5/bit-struct/char-field.rb new file mode 100644 index 0000000000..21a835fbb0 --- /dev/null +++ b/tools/Mach5/bit-struct/char-field.rb @@ -0,0 +1,68 @@ +require 'bit-struct/bit-struct' + +class BitStruct + # Class for fixed length binary strings of characters. + # Declared with BitStruct.char. + class CharField < Field + #def self.default + # don't define this, since it must specify N nulls and we don't know N + #end + + # Used in describe. + def self.class_name + @class_name ||= "char" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + unless offset % 8 == 0 + raise ArgumentError, + "Bad offset, #{offset}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + unless length % 8 == 0 + raise ArgumentError, + "Bad length, #{length}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + offset_byte = offset / 8 + length_byte = length / 8 + last_byte = offset_byte + length_byte - 1 + byte_range = offset_byte..last_byte + val_byte_range = 0..length_byte-1 + + cl.class_eval do + define_method attr do || + self[byte_range].to_s + end + + define_method "#{attr}=" do |val| + val = val.to_s + if val.length < length_byte + val += "\0" * (length_byte - val.length) + end + self[byte_range] = val[val_byte_range] + end + end + end + end + + class << self + # Define a char string field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). Trailing nulls _are_ + # considered part of the string. + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # Note that the accessors have COPY semantics, not reference. + # + def char(name, length, *rest) + opts = parse_options(rest, name, CharField) + add_field(name, length, opts) + end + alias string char + end +end diff --git a/tools/Mach5/bit-struct/float-field.rb b/tools/Mach5/bit-struct/float-field.rb new file mode 100644 index 0000000000..c651d51902 --- /dev/null +++ b/tools/Mach5/bit-struct/float-field.rb @@ -0,0 +1,82 @@ +require 'bit-struct/bit-struct' + +class BitStruct + # Class for floats (single and double precision) in network order. + # Declared with BitStruct.float. + class FloatField < Field + # Used in describe. + def self.class_name + @class_name ||= "float" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + unless offset % 8 == 0 + raise ArgumentError, + "Bad offset, #{offset}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + unless length == 32 or length == 64 + raise ArgumentError, + "Bad length, #{length}, for #{self.class} #{name}." + + " Must be 32 or 64." + end + + offset_byte = offset / 8 + length_byte = length / 8 + last_byte = offset_byte + length_byte - 1 + byte_range = offset_byte..last_byte + + endian = (options[:endian] || options["endian"]).to_s + case endian + when "native" + ctl = case length + when 32; "f" + when 64; "d" + end + when "little" + ctl = case length + when 32; "e" + when 64; "E" + end + when "network", "big", "" + ctl = case length + when 32; "g" + when 64; "G" + end + else + raise ArgumentError, + "Unrecognized endian option: #{endian.inspect}" + end + + cl.class_eval do + define_method attr do || + self[byte_range].unpack(ctl).first + end + + define_method "#{attr}=" do |val| + self[byte_range] = [val].pack(ctl) + end + end + end + end + + class << self + # Define a floating point field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # The <tt>:endian => :native</tt> option overrides the default of + # <tt>:network</tt> byte ordering, in favor of native byte ordering. Also + # permitted are <tt>:big</tt> (same as <tt>:network</tt>) and + # <tt>:little</tt>. + # + def float name, length, *rest + opts = parse_options(rest, name, FloatField) + add_field(name, length, opts) + end + end +end diff --git a/tools/Mach5/bit-struct/hex-octet-field.rb b/tools/Mach5/bit-struct/hex-octet-field.rb new file mode 100644 index 0000000000..475a57233e --- /dev/null +++ b/tools/Mach5/bit-struct/hex-octet-field.rb @@ -0,0 +1,36 @@ +require 'bit-struct/char-field' + +class BitStruct + # Class for char fields that can be accessed with values like + # "xx:xx:xx:xx", where each xx is up to 2 hex digits representing a + # single octet. The original string-based accessors are still available with + # the <tt>_chars</tt> suffix. + # + # Declared with BitStruct.hex_octets. + class HexOctetField < BitStruct::OctetField + # Used in describe. + def self.class_name + @class_name ||= "hex_octets" + end + + SEPARATOR = ":" + FORMAT = "%02x" + BASE = 16 + end + + class << self + # Define an octet string field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). Trailing nulls are + # not considered part of the string. The field is accessed using + # period-separated hex digits. + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + def hex_octets(name, length, *rest) + opts = parse_options(rest, name, HexOctetField) + add_field(name, length, opts) + end + end +end diff --git a/tools/Mach5/bit-struct/nested-field.rb b/tools/Mach5/bit-struct/nested-field.rb new file mode 100644 index 0000000000..19b333e5a1 --- /dev/null +++ b/tools/Mach5/bit-struct/nested-field.rb @@ -0,0 +1,125 @@ +require 'bit-struct/bit-struct' + +class BitStruct + # Class for nesting a BitStruct as a field within another BitStruct. + # Declared with BitStruct.nest. + class NestedField < Field + def initialize(*args) + super + end + + # Used in describe. + def self.class_name + @class_name ||= "nest" + end + + def class_name + @class_name ||= nested_class.name[/\w+$/] + end + + def nested_class + @nested_class ||= options[:nested_class] || options["nested_class"] + end + + def describe opts + if opts[:expand] + opts = opts.dup + opts[:byte_offset] = offset / 8 + opts[:omit_header] = opts[:omit_footer] = true + nested_class.describe(nil, opts) {|desc| yield desc} + else + super + end + end + + def add_accessors_to(cl, attr = name) # :nodoc: + unless offset % 8 == 0 + raise ArgumentError, + "Bad offset, #{offset}, for nested field #{name}." + + " Must be multiple of 8." + end + + unless length % 8 == 0 + raise ArgumentError, + "Bad length, #{length}, for nested field #{name}." + + " Must be multiple of 8." + end + + offset_byte = offset / 8 + length_byte = length / 8 + last_byte = offset_byte + length_byte - 1 + byte_range = offset_byte..last_byte + val_byte_range = 0..length_byte-1 + + nc = nested_class + + cl.class_eval do + define_method attr do || + nc.new(self[byte_range]) + end + + define_method "#{attr}=" do |val| + if val.length != length_byte + raise ArgumentError, "Size mismatch in nested struct assignment " + + "to #{attr} with value #{val.inspect}" + end + + if val.class != nc + warn "Type mismatch in nested struct assignment " + + "to #{attr} with value #{val.inspect}" + end + + self[byte_range] = val[val_byte_range] + end + end + end + end + + class << self + # Define a nested field in the current subclass of BitStruct, + # with the given _name_ and _nested_class_. Length is determined from + # _nested_class_. + # + # In _rest_: + # + # If a class is provided, use it for the Field class (i.e. <=NestedField). + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # WARNING: the accessors have COPY semantics, not reference. When you call a + # reader method to get the nested structure, you get a *copy* of that data. + # + # For example: + # + # class Sub < BitStruct + # unsigned :x, 8 + # end + # + # class A < BitStruct + # nest :n, Sub + # end + # + # a = A.new + # + # p a # ==> #<A n=#<Sub x=0>> + # + # # This fails to set x in a. + # a.n.x = 3 + # p a # ==> #<A n=#<Sub x=0>> + # + # # This works + # n = a.n + # n.x = 3 + # a.n = n + # p a # ==> #<A n=#<Sub x=3>> + # + def nest(name, nested_class, *rest) + opts = parse_options(rest, name, NestedField) + opts[:default] ||= nested_class.initial_value.dup + opts[:nested_class] = nested_class + field = add_field(name, nested_class.bit_length, opts) + field + end + alias struct nest + end +end diff --git a/tools/Mach5/bit-struct/octet-field.rb b/tools/Mach5/bit-struct/octet-field.rb new file mode 100644 index 0000000000..d05e868af5 --- /dev/null +++ b/tools/Mach5/bit-struct/octet-field.rb @@ -0,0 +1,61 @@ +require 'bit-struct/char-field' + +class BitStruct + # Class for char fields that can be accessed with values like + # "xxx.xxx.xxx.xxx", where each xxx is up to 3 decimal digits representing a + # single octet. The original string-based accessors are still available with + # the <tt>_chars</tt> suffix. + # + # Declared with BitStruct.octets. + class OctetField < BitStruct::CharField + # Used in describe. + def self.class_name + @class_name ||= "octets" + end + + SEPARATOR = "." + FORMAT = "%d" + BASE = 10 + + def add_accessors_to(cl, attr = name) # :nodoc: + attr_chars = "#{attr}_chars" + super(cl, attr_chars) + sep = self.class::SEPARATOR + base = self.class::BASE + fmt = self.class::FORMAT + + cl.class_eval do + define_method attr do || + ary = [] + send(attr_chars).each_byte do |c| + ary << fmt % c + end + ary.join(sep) + end + + old_writer = "#{attr_chars}=" + + define_method "#{attr}=" do |val| + data = val.split(sep).map{|s|s.to_i(base)}.pack("c*") + send(old_writer, data) + end + end + end + end + + class << self + # Define an octet string field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). Trailing nulls are + # not considered part of the string. The field is accessed using + # period-separated decimal digits. + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + def octets(name, length, *rest) + opts = parse_options(rest, name, OctetField) + add_field(name, length, opts) + end + end +end diff --git a/tools/Mach5/bit-struct/pad-field.rb b/tools/Mach5/bit-struct/pad-field.rb new file mode 100644 index 0000000000..d6265106cd --- /dev/null +++ b/tools/Mach5/bit-struct/pad-field.rb @@ -0,0 +1,32 @@ +require 'bit-struct/bit-struct' + +class BitStruct + # Class for fixed length padding. + class PadField < Field + # Used in describe. + def self.class_name + @class_name ||= "padding" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + # No accessors for padding. + end + + def inspectable?; false; end + end + + class << self + # Define a padding field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + def pad(name, length, *rest) + opts = parse_options(rest, name, PadField) + add_field(name, length, opts) + end + alias padding pad + end +end diff --git a/tools/Mach5/bit-struct/signed-field.rb b/tools/Mach5/bit-struct/signed-field.rb new file mode 100644 index 0000000000..bc17f5e0d2 --- /dev/null +++ b/tools/Mach5/bit-struct/signed-field.rb @@ -0,0 +1,283 @@ +require 'bit-struct/bit-struct' + +class BitStruct + # Class for signed integers in network order, 1-16 bits, or 8n bits. + # Declared with BitStruct.signed. + class SignedField < Field + # Used in describe. + def self.class_name + @class_name ||= "signed" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + offset_byte = offset / 8 + offset_bit = offset % 8 + + length_bit = offset_bit + length + length_byte = (length_bit/8.0).ceil + last_byte = offset_byte + length_byte - 1 + max = 2**length-1 + mid = 2**(length-1) + max_unsigned = 2**length + to_signed = proc {|n| (n>=mid) ? n - max_unsigned : n} +# to_signed = proc {|n| (n>=mid) ? -((n ^ max) + 1) : n} + + divisor = options[:fixed] || options["fixed"] + divisor_f = divisor && divisor.to_f +# if divisor and not divisor.is_a? Fixnum +# raise ArgumentError, "fixed-point divisor must be a fixnum" +# end + + endian = (options[:endian] || options["endian"]).to_s + case endian + when "native" + ctl = length_byte <= 2 ? "s" : "l" + if length == 16 or length == 32 + to_signed = proc {|n| n} + # with pack support, to_signed can be replaced with no-op + end + when "little" + ctl = length_byte <= 2 ? "v" : "V" + when "network", "big", "" + ctl = length_byte <= 2 ? "n" : "N" + else + raise ArgumentError, + "Unrecognized endian option: #{endian.inspect}" + end + + data_is_big_endian = + ([1234].pack(ctl) == [1234].pack(length_byte <= 2 ? "n" : "N")) + + if length_byte == 1 + rest = 8 - length_bit + mask = ["0"*offset_bit + "1"*length + "0"*rest].pack("B8")[0] + mask2 = ["1"*offset_bit + "0"*length + "1"*rest].pack("B8")[0] + + cl.class_eval do + if divisor + define_method attr do || + to_signed[(self[offset_byte] & mask) >> rest] / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[offset_byte] = + (self[offset_byte] & mask2) | ((val<<rest) & mask) + end + + else + define_method attr do || + to_signed[(self[offset_byte] & mask) >> rest] + end + + define_method "#{attr}=" do |val| + self[offset_byte] = + (self[offset_byte] & mask2) | ((val<<rest) & mask) + end + end + end + + elsif offset_bit == 0 and length % 8 == 0 + field_length = length + byte_range = offset_byte..last_byte + + cl.class_eval do + case field_length + when 8 + if divisor + define_method attr do || + to_signed[self[offset_byte]] / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[offset_byte] = val + end + + else + define_method attr do || + to_signed[self[offset_byte]] + end + + define_method "#{attr}=" do |val| + self[offset_byte] = val + end + end + + when 16, 32 + if divisor + define_method attr do || + to_signed[self[byte_range].unpack(ctl).first] / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[byte_range] = [val].pack(ctl) + end + + else + define_method attr do || + to_signed[self[byte_range].unpack(ctl).first] + end + + define_method "#{attr}=" do |val| + self[byte_range] = [val].pack(ctl) + end + end + + else + reader_helper = proc do |substr| + bytes = substr.unpack("C*") + bytes.reverse! unless data_is_big_endian + bytes.inject do |sum, byte| + (sum << 8) + byte + end + end + + writer_helper = proc do |val| + bytes = [] + val += max_unsigned if val < 0 + while val > 0 + bytes.push val % 256 + val = val >> 8 + end + if bytes.length < length_byte + bytes.concat [0] * (length_byte - bytes.length) + end + + bytes.reverse! if data_is_big_endian + bytes.pack("C*") + end + + if divisor + define_method attr do || + to_signed[reader_helper[self[byte_range]] / divisor_f] + end + + define_method "#{attr}=" do |val| + self[byte_range] = writer_helper[(val * divisor).round] + end + + else + define_method attr do || + to_signed[reader_helper[self[byte_range]]] + end + + define_method "#{attr}=" do |val| + self[byte_range] = writer_helper[val] + end + end + end + end + + elsif length_byte == 2 # unaligned field that fits within two whole bytes + byte_range = offset_byte..last_byte + rest = 16 - length_bit + + mask = ["0"*offset_bit + "1"*length + "0"*rest] + mask = mask.pack("B16").unpack(ctl).first + + mask2 = ["1"*offset_bit + "0"*length + "1"*rest] + mask2 = mask2.pack("B16").unpack(ctl).first + + cl.class_eval do + if divisor + define_method attr do || + to_signed[(self[byte_range].unpack(ctl).first & mask) >> rest] / + divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + x = (self[byte_range].unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl) + end + + else + define_method attr do || + to_signed[(self[byte_range].unpack(ctl).first & mask) >> rest] + end + + define_method "#{attr}=" do |val| + x = (self[byte_range].unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl) + end + end + end + + elsif length_byte == 3 # unaligned field that fits within 3 whole bytes + byte_range = offset_byte..last_byte + rest = 32 - length_bit + + mask = ["0"*offset_bit + "1"*length + "0"*rest] + mask = mask.pack("B32").unpack(ctl).first + + mask2 = ["1"*offset_bit + "0"*length + "1"*rest] + mask2 = mask2.pack("B32").unpack(ctl).first + + cl.class_eval do + if divisor + define_method attr do || + bytes = self[byte_range] + bytes << 0 + to_signed[((bytes.unpack(ctl).first & mask) >> rest)] / + divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + bytes = self[byte_range] + bytes << 0 + x = (bytes.unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl)[0..2] + end + + else + define_method attr do || + bytes = self[byte_range] + bytes << 0 + to_signed[(bytes.unpack(ctl).first & mask) >> rest] + end + + define_method "#{attr}=" do |val| + bytes = self[byte_range] + bytes << 0 + x = (bytes.unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl)[0..2] + end + end + end + + else + raise "unsupported: #{inspect}" + end + end + end + + class << self + # Define a signed integer field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # SignedField adds the <tt>:fixed => divisor</tt> option, which specifies + # that the internally stored value is interpreted as a fixed point real + # number with the specified +divisor+. + # + # The <tt>:endian => :native</tt> option overrides the default of + # <tt>:network</tt> byte ordering, in favor of native byte ordering. Also + # permitted are <tt>:big</tt> (same as <tt>:network</tt>) and + # <tt>:little</tt>. + # + def signed name, length, *rest + opts = parse_options(rest, name, SignedField) + add_field(name, length, opts) + end + end +end diff --git a/tools/Mach5/bit-struct/text-field.rb b/tools/Mach5/bit-struct/text-field.rb new file mode 100644 index 0000000000..369981fb69 --- /dev/null +++ b/tools/Mach5/bit-struct/text-field.rb @@ -0,0 +1,63 @@ +require 'bit-struct/bit-struct' + +class BitStruct + # Class for null-terminated printable text strings. + # Declared with BitStruct.text. + class TextField < Field + # Used in describe. + def self.class_name + @class_name ||= "text" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + unless offset % 8 == 0 + raise ArgumentError, + "Bad offset, #{offset}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + unless length % 8 == 0 + raise ArgumentError, + "Bad length, #{length}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + offset_byte = offset / 8 + length_byte = length / 8 + last_byte = offset_byte + length_byte - 1 + byte_range = offset_byte..last_byte + val_byte_range = 0..length_byte-1 + + cl.class_eval do + define_method attr do || + self[byte_range].sub(/\0*$/, "").to_s + end + + define_method "#{attr}=" do |val| + val = val.to_s + if val.length < length_byte + val += "\0" * (length_byte - val.length) + end + self[byte_range] = val[val_byte_range] + end + end + end + end + + class << self + # Define a printable text string field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). Trailing nulls are + # _not_ considered part of the string. + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # Note that the accessors have COPY semantics, not reference. + # + def text(name, length, *rest) + opts = parse_options(rest, name, TextField) + add_field(name, length, opts) + end + end +end diff --git a/tools/Mach5/bit-struct/unsigned-field.rb b/tools/Mach5/bit-struct/unsigned-field.rb new file mode 100644 index 0000000000..41571b1c04 --- /dev/null +++ b/tools/Mach5/bit-struct/unsigned-field.rb @@ -0,0 +1,273 @@ +require 'bit-struct/bit-struct' + +class BitStruct + # Class for unsigned integers in network order, 1-16 bits, or 8n bits. + # Declared with BitStruct.unsigned. + class UnsignedField < Field + # Used in describe. + def self.class_name + @class_name ||= "unsigned" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + offset_byte = offset / 8 + offset_bit = offset % 8 + + length_bit = offset_bit + length + length_byte = (length_bit/8.0).ceil + last_byte = offset_byte + length_byte - 1 + + divisor = options[:fixed] || options["fixed"] + divisor_f = divisor && divisor.to_f +# if divisor and not divisor.is_a? Fixnum +# raise ArgumentError, "fixed-point divisor must be a fixnum" +# end + + endian = (options[:endian] || options["endian"]).to_s + case endian + when "native" + ctl = length_byte <= 2 ? "S" : "L" + when "little" + ctl = length_byte <= 2 ? "v" : "V" + when "network", "big", "" + ctl = length_byte <= 2 ? "n" : "N" + else + raise ArgumentError, + "Unrecognized endian option: #{endian.inspect}" + end + + data_is_big_endian = + ([1234].pack(ctl) == [1234].pack(length_byte <= 2 ? "n" : "N")) + + if length_byte == 1 + rest = 8 - length_bit + mask = ["0"*offset_bit + "1"*length + "0"*rest].pack("B8")[0] + mask2 = ["1"*offset_bit + "0"*length + "1"*rest].pack("B8")[0] + + cl.class_eval do + if divisor + define_method attr do || + ((self[offset_byte] & mask) >> rest) / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[offset_byte] = + (self[offset_byte] & mask2) | ((val<<rest) & mask) + end + + else + define_method attr do || + (self[offset_byte] & mask) >> rest + end + + define_method "#{attr}=" do |val| + self[offset_byte] = + (self[offset_byte] & mask2) | ((val<<rest) & mask) + end + end + end + + elsif offset_bit == 0 and length % 8 == 0 + field_length = length + byte_range = offset_byte..last_byte + + cl.class_eval do + case field_length + when 8 + if divisor + define_method attr do || + self[offset_byte] / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[offset_byte] = val + end + + else + define_method attr do || + self[offset_byte] + end + + define_method "#{attr}=" do |val| + self[offset_byte] = val + end + end + + when 16, 32 + if divisor + define_method attr do || + self[byte_range].unpack(ctl).first / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[byte_range] = [val].pack(ctl) + end + + else + define_method attr do || + self[byte_range].unpack(ctl).first + end + + define_method "#{attr}=" do |val| + self[byte_range] = [val].pack(ctl) + end + end + + else + reader_helper = proc do |substr| + bytes = substr.unpack("C*") + bytes.reverse! unless data_is_big_endian + bytes.inject do |sum, byte| + (sum << 8) + byte + end + end + + writer_helper = proc do |val| + bytes = [] + while val > 0 + bytes.push val % 256 + val = val >> 8 + end + if bytes.length < length_byte + bytes.concat [0] * (length_byte - bytes.length) + end + + bytes.reverse! if data_is_big_endian + bytes.pack("C*") + end + + if divisor + define_method attr do || + reader_helper[self[byte_range]] / divisor_f + end + + define_method "#{attr}=" do |val| + self[byte_range] = writer_helper[(val * divisor).round] + end + + else + define_method attr do || + reader_helper[self[byte_range]] + end + + define_method "#{attr}=" do |val| + self[byte_range] = writer_helper[val] + end + end + end + end + + elsif length_byte == 2 # unaligned field that fits within two whole bytes + byte_range = offset_byte..last_byte + rest = 16 - length_bit + + mask = ["0"*offset_bit + "1"*length + "0"*rest] + mask = mask.pack("B16").unpack(ctl).first + + mask2 = ["1"*offset_bit + "0"*length + "1"*rest] + mask2 = mask2.pack("B16").unpack(ctl).first + + cl.class_eval do + if divisor + define_method attr do || + ((self[byte_range].unpack(ctl).first & mask) >> rest) / + divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + x = (self[byte_range].unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl) + end + + else + define_method attr do || + (self[byte_range].unpack(ctl).first & mask) >> rest + end + + define_method "#{attr}=" do |val| + x = (self[byte_range].unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl) + end + end + end + + elsif length_byte == 3 # unaligned field that fits within 3 whole bytes + byte_range = offset_byte..last_byte + rest = 32 - length_bit + + mask = ["0"*offset_bit + "1"*length + "0"*rest] + mask = mask.pack("B32").unpack(ctl).first + + mask2 = ["1"*offset_bit + "0"*length + "1"*rest] + mask2 = mask2.pack("B32").unpack(ctl).first + + cl.class_eval do + if divisor + define_method attr do || + bytes = self[byte_range] + bytes << 0 + ((bytes.unpack(ctl).first & mask) >> rest) / + divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + bytes = self[byte_range] + bytes << 0 + x = (bytes.unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl)[0..2] + end + + else + define_method attr do || + bytes = self[byte_range] + bytes << 0 + (bytes.unpack(ctl).first & mask) >> rest + end + + define_method "#{attr}=" do |val| + bytes = self[byte_range] + bytes << 0 + x = (bytes.unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl)[0..2] + end + end + end + + else + raise "unsupported: #{inspect}" + end + end + end + + class << self + # Define a unsigned integer field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # UnsignedField adds the <tt>:fixed => divisor</tt> option, which specifies + # that the internally stored value is interpreted as a fixed point real + # number with the specified +divisor+. + # + # The <tt>:endian => :native</tt> option overrides the default of + # <tt>:network</tt> byte ordering, in favor of native byte ordering. Also + # permitted are <tt>:big</tt> (same as <tt>:network</tt>) and + # <tt>:little</tt>. + # + def unsigned name, length, *rest + opts = parse_options(rest, name, UnsignedField) + add_field(name, length, opts) + end + end +end diff --git a/tools/Mach5/bit-struct/yaml.rb b/tools/Mach5/bit-struct/yaml.rb new file mode 100644 index 0000000000..f298ab2b97 --- /dev/null +++ b/tools/Mach5/bit-struct/yaml.rb @@ -0,0 +1,70 @@ +require 'bit-struct/bit-struct' +require 'yaml' + +class BitStruct + if RUBY_VERSION == "1.8.2" + def is_complex_yaml? # :nodoc: + true + end + + YAML.add_ruby_type(/^bitstruct/) do |type, val| + subtype, subclass = YAML.read_type_class(type, Object) + subclass.new(val) + end + + def to_yaml_type # :nodoc: + "!ruby/bitstruct:#{self.class}" + end + + def to_yaml( opts = {} ) # :nodoc: + opts[:DocType] = self.class if Hash === opts + YAML.quick_emit(self.object_id, opts) do |out| + out.map(to_yaml_type) do |map| + fields.each do |field| + fn = field.name + map.add(fn, send(fn)) + end + end + end + end + + else + yaml_as "tag:path.berkeley.edu,2006:bitstruct" + + def to_yaml_properties # :nodoc: + yaml_fields = fields.select {|field| field.inspectable?} + props = yaml_fields.map {|f| f.name.to_s} + if (rest_field = self.class.rest_field) + props << rest_field.name.to_s + end + props + end + + # Return YAML representation of the BitStruct. + def to_yaml( opts = {} ) + YAML::quick_emit( object_id, opts ) do |out| + out.map( taguri, to_yaml_style ) do |map| + to_yaml_properties.each do |m| + map.add( m, send( m ) ) + end + end + end + end + + def self.yaml_new( klass, tag, val ) # :nodoc: + unless Hash === val + raise YAML::TypeError, "Invalid BitStruct: " + val.inspect + end + + bitstruct_name, bitstruct_type = YAML.read_type_class( tag, BitStruct ) + + st = bitstruct_type.new + + val.each do |k,v| + st.send( "#{k}=", v ) + end + + st + end + end +end diff --git a/tools/Mach5/mach5.rb b/tools/Mach5/mach5.rb new file mode 100755 index 0000000000..65fec4b32e --- /dev/null +++ b/tools/Mach5/mach5.rb @@ -0,0 +1,263 @@ +#!/usr/bin/env ruby +# +# Copyright (C) 2008 Elan Feingold (elan at bluemandrill dot com) +# +# 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, 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 GNU Make; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +# +# + +require 'bit-struct' + +# For example, "_calloc" => "_wrap_calloc" +prefix = '___wrap_' +mappings = { +'calloc' => true, +'clearerr' => true, +'close' => true, +'fclose' => true, +'fdopen' => true, +'feof' => true, +'ferror' => true, +'fflush' => true, +'fgetc' => true, +'fgetpos' => true, +'fgets' => true, +'fileno' => true, +'flockfile' => true, +'fopen' => true, +'fopen64' => true, +'fprintf' => true, +'fputc' => true, +'fputs' => true, +'fread' => true, +'free' => true, +'freopen' => true, +'fseek' => true, +'fsetpos' => true, +'fstatvfs64' => true, +'ftell' => true, +'ftrylockfile' => true, +'funlockfile' => true, +'fwrite' => true, +'getc_unlocked' => true, +'ioctl' => true, +'lseek' => true, +'lseek64' => true, +'malloc' => true, +'open' => true, +'open64' => true, +'popen' => true, +'printf' => true, +'read' => true, +'realloc' => true, +'rewind' => true, +'stat' => true, +'fstat' => true, +'ungetc' => true, +'vfprintf' => true, +'write' => true, +'putc' => '___wrap__IO_putc', +'getc' => '___wrap__IO_getc', +'getc_unlocked' => '___wrap__IO_getc_unlocked' +} + +prefix_python = '___py_wrap_' +mappings_python = { + 'getcwd' => true, 'chdir' => true, 'access' => true, 'unlink' => true, 'chmod' => true, + 'rmdir' => true, 'utime' => true, 'rename' => true, 'mkdir' => true, + 'opendir' => true, 'dlopen' => true, 'dlclose' => true, 'dlsym' => true, + 'lstat' => true +} + +LC_SYMTAB = 0x02 +LC_SEGMENT = 0x01 + +class MachHeader < BitStruct + hex_octets :magic, 32, "Magic Number" + unsigned :cputype, 32, "CPU Type", :endian => :native + unsigned :cpusubtype, 32, "CPU Subtype", :endian => :native + unsigned :filetype, 32, "File Type", :endian => :native + unsigned :ncmds, 32, "Number of commands", :endian => :native + unsigned :sizeofcmds, 32, "Size of commands", :endian => :native + unsigned :flags, 32, "Flags", :endian => :native + rest :data, "Data" +end + +class LoadCommand < BitStruct + unsigned :cmd, 32, "Command", :endian => :native + unsigned :cmdsize, 32, "Command Size", :endian => :native +end + +class SymtabCommand < BitStruct + unsigned :cmd, 32, "Command", :endian => :native + unsigned :cmdsize, 32, "Command Size", :endian => :native + unsigned :symoff, 32, "Symbol Offset", :endian => :native + unsigned :nsyms, 32, "Number of Symbols", :endian => :native + unsigned :stroff, 32, "String table offset", :endian => :native + unsigned :strsize, 32, "Size of string table", :endian => :native +end + +class SegmentCommand < BitStruct + unsigned :cmd, 32, "Command", :endian => :native + unsigned :cmdsize, 32, "Command Size", :endian => :native + char :segname, 16*8, "Segment name", :endian => :native + unsigned :vmaddr, 32, "VM Adddress", :endian => :native + unsigned :vmsize, 32, "VM Size", :endian => :native + unsigned :fileoff, 32, "File Offset", :endian => :native + unsigned :filesize, 32, "File Size", :endian => :native +end + +class SymtabEntry < BitStruct + unsigned :strtableoffset, 32, "String table offset", :endian => :native + unsigned :debuggingEntry, 3, "Debugging entry", :endian => :native + unsigned :privateExternal, 1, "Is Private Enternal", :endian => :native + unsigned :type, 3, "Type bits", :endian => :native + unsigned :external, 1, "External symbol", :endian => :native + unsigned :sectionNumber, 8, "Section number", :endian => :native + unsigned :description, 16, "Description", :endian => :native + unsigned :value, 32, "Value", :endian => :native +end + +# Select which mapping to use. +if ARGV.size() > 1 and ARGV[1].index('libpython') == 0 + puts "Using Python mappings." + mappings = mappings_python + #prefix = prefix_python +end + +data = open(ARGV[0]).read +puts "Input file was #{data.length} bytes long." + +# Parse the header. +header = MachHeader.new(data) +sym_cmd = nil + +# String table. +string_table = nil +string_table_offset = nil +string_table_map = {} +offset_map = {} + +# Symbol table. +symbol_table = nil +symbol_table_offset = nil +symbols = [] + +# Link segment. +link_cmd = nil +link_cmd_offset = nil + +# Walk through all the commands. +offset = data.size - header.data.size +header.ncmds.times do |i| + load_cmd = LoadCommand.new(data[offset..-1]) + + if load_cmd.cmd == LC_SEGMENT + seg_cmd = SegmentCommand.new(data[offset..-1]) + if seg_cmd.segname.index('__LINKEDIT') == 0 + puts "Found LINKEDIT segment at offset #{offset}" + link_cmd = seg_cmd + link_cmd_offset = offset + end + end + + if load_cmd.cmd == LC_SYMTAB + # Parse the symbol table command. + sym_cmd = SymtabCommand.new(data[offset..-1]) + symbol_table_offset = offset + + # Parse the string table, store with offsets. + string_table_offset = sym_cmd.stroff + string_table = data[sym_cmd.stroff..sym_cmd.stroff+sym_cmd.strsize-1] + i = 0 + string_table.split("\x00", -1).each do |s| + string_table_map[i] = s + i += s.length + 1 + end + + # Parse the symbol table. + symbol_table = data[sym_cmd.symoff..-1] + i = 0 + puts "Symbol table has #{sym_cmd.nsyms} symbols." + sym_cmd.nsyms.times do |n| + symbols << SymtabEntry.new(symbol_table[i..i+11]) + i += 12 + end + + # Now go through and make renames to the symbols. + size_diff = 0 + + string_table_map.keys.sort.each do |i| + orig_sym = string_table_map[i] + + # Store the offset mapping. + offset_map[i] = (i + size_diff) + + if orig_sym.length > 1 + sym = orig_sym[1..-1].gsub('$UNIX2003','') + if mappings.has_key?(sym) + if mappings[sym] != true + string_table_map[i] = mappings[sym] + else + string_table_map[i] = "#{prefix}#{sym}" + end + puts " - Mapping: #{orig_sym} to #{string_table_map[i]} (offset #{i} -> #{i + size_diff})" + + # Accumulate the offset difference. + size_diff += string_table_map[i].length - orig_sym.length + end + end + end + end + + offset += load_cmd.cmdsize +end + +# OK, now lets rewrite the symbol table. Offsets may have changed, but the size doesn't. +new_symbol_table = '' +i = 0 +symbols.each do |symbol| + puts " - Mapped #{i} symbols..." if i % 10000 == 0 and i > 0 + symbol.strtableoffset = offset_map[symbol.strtableoffset] if symbol.strtableoffset > 1 + new_symbol_table << symbol + i += 1 +end + +# OK, now lets rewrite the string table. The size will be different if mappings have occurred. +new_string_table = string_table_map.keys.sort.collect { |i| string_table_map[i] }.join("\x00") + +# Next, modify the LC_SYMTAB header. +size_diff = new_string_table.length - sym_cmd.strsize +sym_cmd.strsize = new_string_table.length + +# Lastly, modify the LINKEDIT segment if it exists. +if link_cmd + puts "Size changed by #{size_diff} bytes, rewriting LINKEDIT segment." + link_cmd.filesize += size_diff + SegmentCommand.round_byte_length.times { |i| data[link_cmd_offset + i] = link_cmd[i] } +end + +# Create the new file in memory. First, copy the new symbol table header into place. +24.times { |i| data[symbol_table_offset + i] = sym_cmd[i] } + +# Now copy the new symbol table. +new_symbol_table.length.times { |i| data[sym_cmd.symoff + i] = new_symbol_table[i] } + +# Finally, add the new string table. +data = data[0..string_table_offset-1] + new_string_table + +puts "Output file is #{data.length} bytes long." +open("output.so", "wb").write(data) diff --git a/tools/Mach5/wrapper.rb b/tools/Mach5/wrapper.rb new file mode 100755 index 0000000000..3cd1b9a669 --- /dev/null +++ b/tools/Mach5/wrapper.rb @@ -0,0 +1,1873 @@ +#!/usr/bin/env ruby +# Class for packed binary data, with defined bitfields and accessors for them. +# See {intro.txt}[link:../doc/files/intro_txt.html] for an overview. +# +# Data after the end of the defined fields is accessible using the +rest+ +# declaration. See examples/ip.rb. Nested fields can be declared using +nest+. +# See examples/nest.rb. +# +# Note that all string methods are still available: length, grep, etc. +# The String#replace method is useful. +# +class BitStruct < String + + class Field + # Offset of field in bits. + attr_reader :offset + + # Length of field in bits. + attr_reader :length + alias size length + + # Name of field (used for its accessors). + attr_reader :name + + # Options, such as :default (varies for each field subclass). + # In general, options can be provided as strings or as symbols. + attr_reader :options + + # Display name of field (used for printing). + attr_reader :display_name + + # Default value. + attr_reader :default + + # Format for printed value of field. + attr_reader :format + + # Subclasses can override this to define a default for all fields of this + # class, not just the one currently being added to a BitStruct class, a + # "default default" if you will. The global default, if #default returns + # nil, is to fill the field with zero. Most field classes just let this + # default stand. The default can be overridden per-field when a BitStruct + # class is defined. + def self.default; nil; end + + # Used in describe. + def self.class_name + @class_name ||= name[/\w+$/] + end + + # Used in describe. Can be overridden per-subclass, as in NestedField. + def class_name + self.class.class_name + end + + # Yield the description of this field, as an array of 5 strings: byte + # offset, type, name, size, and description. The opts hash may have: + # + # :expand :: if the value is true, expand complex fields + # + # (Subclass implementations may yield more than once for complex fields.) + # + def describe opts + bits = size + if bits > 32 and bits % 8 == 0 + len_str = "%dB" % (bits/8) + else + len_str = "%db" % bits + end + + byte_offset = offset / 8 + (opts[:byte_offset] || 0) + + yield ["@%d" % byte_offset, class_name, name, len_str, display_name] + end + + # Options are _display_name_, _default_, and _format_ (subclasses of Field + # may add other options). + def initialize(offset, length, name, opts = {}) + @offset, @length, @name, @options = + offset, length, name, opts + + @display_name = opts[:display_name] || opts["display_name"] + @default = opts[:default] || opts["default"] || self.class.default + @format = opts[:format] || opts["format"] + end + + # Inspect the value of this field in the specified _obj_. + def inspect_in_object(obj, opts) + val = obj.send(name) + str = + begin + val.inspect(opts) + rescue ArgumentError # assume: "wrong number of arguments (1 for 0)" + val.inspect + end + (f=@format) ? (f % str) : str + end + + # Normally, all fields show up in inspect, but some, such as padding, + # should not. + def inspectable?; true; end + end + + NULL_FIELD = Field.new(0, 0, :null, :display_name => "null field") + + # Raised when a field is added after an instance has been created. Fields + # cannot be added after this point. + class ClosedClassError < StandardError; end + + # Raised if the chosen field name is not allowed, either because another + # field by that name exists, or because a method by that name exists. + class FieldNameError < StandardError; end + + @default_options = {} + + class << self + # ------------------------ + # :section: field access methods + # + # For introspection and metaprogramming. + # + # ------------------------ + + # Return the list of fields for this class. + def fields + @fields ||= self == BitStruct ? [] : superclass.fields.dup + end + + # Return the list of fields defined by this class, not inherited + # from the superclass. + def own_fields + @own_fields ||= [] + end + + # Add a field to the BitStruct (usually, this is only used internally). + def add_field(name, length, opts = {}) + round_byte_length ## just to make sure this has been calculated + ## before adding anything + + name = name.to_sym + + if @closed + raise ClosedClassError, "Cannot add field #{name}: " + + "The definition of the #{self.inspect} BitStruct class is closed." + end + + if fields.find {|f|f.name == name} + raise FieldNameError, "Field #{name} is already defined as a field." + end + + if instance_methods(true).find {|m| m == name} + if opts[:allow_method_conflict] || opts["allow_method_conflict"] + warn "Field #{name} is already defined as a method." + else + raise FieldNameError,"Field #{name} is already defined as a method." + end + end + + field_class = opts[:field_class] + + prev = fields[-1] || NULL_FIELD + offset = prev.offset + prev.length + field = field_class.new(offset, length, name, opts) + field.add_accessors_to(self) + fields << field + own_fields << field + @bit_length += field.length + @round_byte_length = (bit_length/8.0).ceil + + if @initial_value + diff = @round_byte_length - @initial_value.length + if diff > 0 + @initial_value << "\0" * diff + end + end + + field + end + + def parse_options(ary, default_name, default_field_class) # :nodoc: + opts = ary.grep(Hash).first || {} + opts = default_options.merge(opts) + + opts[:display_name] = ary.grep(String).first || default_name + opts[:field_class] = ary.grep(Class).first || default_field_class + + opts + end + + # Get or set the hash of default options for the class, which apply to all + # fields. Changes take effect immediately, so can be used alternatingly with + # blocks of field declarations. If +h+ is provided, update the default + # options with that hash. Default options are inherited. + # + # This is especially useful with the <tt>:endian => val</tt> option. + def default_options h = nil + @default_options ||= superclass.default_options.dup + if h + @default_options.merge! h + end + @default_options + end + + # Length, in bits, of this object. + def bit_length + @bit_length ||= fields.inject(0) {|a, f| a + f.length} + end + + # Length, in bytes (rounded up), of this object. + def round_byte_length + @round_byte_length ||= (bit_length/8.0).ceil + end + + def closed! # :nodoc: + @closed = true + end + + def field_by_name name + @field_by_name ||= {} + field = @field_by_name[name] + unless field + field = fields.find {|f| f.name == name} + @field_by_name[name] = field if field + end + field + end + end + + # Return the list of fields for this class. + def fields + self.class.fields + end + + # Return the field with the given name. + def field_by_name name + self.class.field_by_name name + end + + # ------------------------ + # :section: metadata inspection methods + # + # Methods to textually describe the format of a BitStruct subclass. + # + # ------------------------ + + class << self + # Default format for describe. Fields are byte, type, name, size, + # and description. + DESCRIBE_FORMAT = "%8s: %-12s %-14s[%4s] %s" + + # Can be overridden to use a different format. + def describe_format + DESCRIBE_FORMAT + end + + # Textually describe the fields of this class of BitStructs. + # Returns a printable table (array of line strings), based on +fmt+, + # which defaults to #describe_format, which defaults to +DESCRIBE_FORMAT+. + def describe(fmt = nil, opts = {}) + if block_given? + fields.each do |field| + field.describe(opts) do |desc| + yield desc + end + end + nil + + else + fmt ||= describe_format + + result = [] + + unless opts[:omit_header] + result << fmt % ["byte", "type", "name", "size", "description"] + result << "-"*70 + end + + fields.each do |field| + field.describe(opts) do |desc| + result << fmt % desc + end + end + + unless opts[:omit_footer] + result << @note if @note + end + + result + end + end + + # Subclasses can use this to append a string (or several) to the #describe + # output. Notes are not cumulative with inheritance. When used with no + # arguments simply returns the note string + def note(*str) + @note = str unless str.empty? + @note + end + end + + # ------------------------ + # :section: initialization and conversion methods + # + # ------------------------ + + # Initialize the string with the given string or bitstruct, or with a hash of + # field=>value pairs, or with the defaults for the BitStruct subclass. Fields + # can be strings or symbols. Finally, if a block is given, yield the instance + # for modification using accessors. + def initialize(value = nil) # :yields: instance + self << self.class.initial_value + + case value + when Hash + value.each do |k, v| + send "#{k}=", v + end + + when nil + + else + self[0, value.length] = value + end + + self.class.closed! + yield self if block_given? + end + + DEFAULT_TO_H_OPTS = { + :convert_keys => :to_sym, + :include_rest => true + } + + # Returns a hash of {name=>value,...} for each field. By default, include + # the rest field. + # Keys are symbols derived from field names using +to_sym+, unless + # <tt>opts[:convert_keys]<\tt> is set to some other method name. + def to_h(opts = DEFAULT_TO_H_OPTS) + converter = opts[:convert_keys] || :to_sym + + fields_for_to_h = fields + if opts[:include_rest] and (rest_field = self.class.rest_field) + fields_for_to_h += [rest_field] + end + + fields_for_to_h.inject({}) do |h,f| + h[f.name.send(converter)] = send(f.name) + h + end + end + + # Returns an array of values of the fields of the BitStruct. By default, + # include the rest field. + def to_a(include_rest = true) + ary = + fields.map do |f| + send(f.name) + end + + if include_rest and (rest_field = self.class.rest_field) + ary << send(rest_field.name) + end + end + + class << self + # The unique "prototype" object from which new instances are copied. + # The fields of this instance can be modified in the class definition + # to set default values for the fields in that class. (Otherwise, defaults + # defined by the fields themselves are used.) A copy of this object is + # inherited in subclasses, which they may override using defaults and + # by writing to the initial_value object itself. + # + # If called with a block, yield the initial value object before returning + # it. Useful for customization within a class definition. + # + def initial_value # :yields: the initial value + unless @initial_value + iv = defined?(superclass.initial_value) ? + superclass.initial_value.dup : "" + if iv.length < round_byte_length + iv << "\0" * (round_byte_length - iv.length) + end + + @initial_value = "" # Serves as initval while the real initval is inited + @initial_value = new(iv) + @closed = false # only creating the first _real_ instance closes. + + fields.each do |field| + @initial_value.send("#{field.name}=", field.default) if field.default + end + end + yield @initial_value if block_given? + @initial_value + end + + # Take +data+ (a string or BitStruct) and parse it into instances of + # the +classes+, returning them in an array. The classes can be given + # as an array or a separate arguments. (For parsing a string into a _single_ + # BitStruct instance, just use the #new method with the string as an arg.) + def parse(data, *classes) + classes.flatten.map do |c| + c.new(data.slice!(0...c.round_byte_length)) + end + end + + # Join the given structs (array or multiple args) as a string. + # Actually, the inherited String#+ instance method is the same, as is using + # Array#join. + def join(*structs) + structs.flatten.map {|struct| struct.to_s}.join("") + end + end + + # ------------------------ + # :section: inspection methods + # + # ------------------------ + + DEFAULT_INSPECT_OPTS = { + :format => "#<%s %s>", + :field_format => "%s=%s", + :separator => ", ", + :field_name_meth => :name, + :include_rest => true + } + + DETAILED_INSPECT_OPTS = { + :format => "%s:\n%s", + :field_format => "%30s = %s", + :separator => "\n", + :field_name_meth => :display_name, + :include_rest => true + } + + # A standard inspect method which does not add newlines. + def inspect(opts = DEFAULT_INSPECT_OPTS) + field_format = opts[:field_format] + field_name_meth = opts[:field_name_meth] + + fields_for_inspect = fields.select {|field| field.inspectable?} + if opts[:include_rest] and (rest_field = self.class.rest_field) + fields_for_inspect << rest_field + end + + ary = fields_for_inspect.map do |field| + field_format % + [field.send(field_name_meth), + field.inspect_in_object(self, opts)] + end + + body = ary.join(opts[:separator]) + + opts[:format] % [self.class, body] + end + + # A more visually appealing inspect method that puts each field/value on + # a separate line. Very useful when output is scrolling by on a screen. + # + # (This is actually a convenience method to call #inspect with the + # DETAILED_INSPECT_OPTS opts.) + def inspect_detailed + inspect(DETAILED_INSPECT_OPTS) + end + + # ------------------------ + # :section: field declaration methods + # + # ------------------------ + + # Define accessors for a variable length substring from the end of + # the defined fields to the end of the BitStruct. The _rest_ may behave as + # a String or as some other String or BitStruct subclass. + # + # This does not add a field, which is useful because a superclass can have + # a rest method which accesses subclass data. In particular, #rest does + # not affect the #round_byte_length class method. Of course, any data + # in rest does add to the #length of the BitStruct, calculated as a string. + # Also, _rest_ is not inherited. + # + # The +ary+ argument(s) work as follows: + # + # If a class is provided, use it for the Field class (String by default). + # If a string is provided, use it for the display_name (+name+ by default). + # If a hash is provided, use it for options. + # + # *Warning*: the rest reader method returns a copy of the field, so + # accessors on that returned value do not affect the original rest field. + # + def self.rest(name, *ary) + if @rest_field + raise ArgumentError, "Duplicate rest field: #{name.inspect}." + end + + opts = parse_options(ary, name, String) + offset = round_byte_length + byte_range = offset..-1 + class_eval do + field_class = opts[:field_class] + define_method name do || + field_class.new(self[byte_range]) + end + + define_method "#{name}=" do |val| + self[byte_range] = val + end + + @rest_field = Field.new(offset, -1, name, { + :display_name => opts[:display_name], + :rest_class => field_class + }) + end + end + + # Not included with the other fields, but accessible separately. + def self.rest_field; @rest_field; end +end +#require 'bit-struct/bit-struct' + +class BitStruct + # Class for fixed length binary strings of characters. + # Declared with BitStruct.char. + class CharField < Field + #def self.default + # don't define this, since it must specify N nulls and we don't know N + #end + + # Used in describe. + def self.class_name + @class_name ||= "char" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + unless offset % 8 == 0 + raise ArgumentError, + "Bad offset, #{offset}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + unless length % 8 == 0 + raise ArgumentError, + "Bad length, #{length}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + offset_byte = offset / 8 + length_byte = length / 8 + last_byte = offset_byte + length_byte - 1 + byte_range = offset_byte..last_byte + val_byte_range = 0..length_byte-1 + + cl.class_eval do + define_method attr do || + self[byte_range].to_s + end + + define_method "#{attr}=" do |val| + val = val.to_s + if val.length < length_byte + val += "\0" * (length_byte - val.length) + end + self[byte_range] = val[val_byte_range] + end + end + end + end + + class << self + # Define a char string field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). Trailing nulls _are_ + # considered part of the string. + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # Note that the accessors have COPY semantics, not reference. + # + def char(name, length, *rest) + opts = parse_options(rest, name, CharField) + add_field(name, length, opts) + end + alias string char + end +end +#require 'bit-struct/bit-struct' + +class BitStruct + # Class for floats (single and double precision) in network order. + # Declared with BitStruct.float. + class FloatField < Field + # Used in describe. + def self.class_name + @class_name ||= "float" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + unless offset % 8 == 0 + raise ArgumentError, + "Bad offset, #{offset}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + unless length == 32 or length == 64 + raise ArgumentError, + "Bad length, #{length}, for #{self.class} #{name}." + + " Must be 32 or 64." + end + + offset_byte = offset / 8 + length_byte = length / 8 + last_byte = offset_byte + length_byte - 1 + byte_range = offset_byte..last_byte + + endian = (options[:endian] || options["endian"]).to_s + case endian + when "native" + ctl = case length + when 32; "f" + when 64; "d" + end + when "little" + ctl = case length + when 32; "e" + when 64; "E" + end + when "network", "big", "" + ctl = case length + when 32; "g" + when 64; "G" + end + else + raise ArgumentError, + "Unrecognized endian option: #{endian.inspect}" + end + + cl.class_eval do + define_method attr do || + self[byte_range].unpack(ctl).first + end + + define_method "#{attr}=" do |val| + self[byte_range] = [val].pack(ctl) + end + end + end + end + + class << self + # Define a floating point field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # The <tt>:endian => :native</tt> option overrides the default of + # <tt>:network</tt> byte ordering, in favor of native byte ordering. Also + # permitted are <tt>:big</tt> (same as <tt>:network</tt>) and + # <tt>:little</tt>. + # + def float name, length, *rest + opts = parse_options(rest, name, FloatField) + add_field(name, length, opts) + end + end +end +#require 'bit-struct/char-field' + +class BitStruct + # Class for char fields that can be accessed with values like + # "xxx.xxx.xxx.xxx", where each xxx is up to 3 decimal digits representing a + # single octet. The original string-based accessors are still available with + # the <tt>_chars</tt> suffix. + # + # Declared with BitStruct.octets. + class OctetField < BitStruct::CharField + # Used in describe. + def self.class_name + @class_name ||= "octets" + end + + SEPARATOR = "." + FORMAT = "%d" + BASE = 10 + + def add_accessors_to(cl, attr = name) # :nodoc: + attr_chars = "#{attr}_chars" + super(cl, attr_chars) + sep = self.class::SEPARATOR + base = self.class::BASE + fmt = self.class::FORMAT + + cl.class_eval do + define_method attr do || + ary = [] + send(attr_chars).each_byte do |c| + ary << fmt % c + end + ary.join(sep) + end + + old_writer = "#{attr_chars}=" + + define_method "#{attr}=" do |val| + data = val.split(sep).map{|s|s.to_i(base)}.pack("c*") + send(old_writer, data) + end + end + end + end + + class << self + # Define an octet string field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). Trailing nulls are + # not considered part of the string. The field is accessed using + # period-separated decimal digits. + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + def octets(name, length, *rest) + opts = parse_options(rest, name, OctetField) + add_field(name, length, opts) + end + end +end +#require 'bit-struct/char-field' + +class BitStruct + # Class for char fields that can be accessed with values like + # "xx:xx:xx:xx", where each xx is up to 2 hex digits representing a + # single octet. The original string-based accessors are still available with + # the <tt>_chars</tt> suffix. + # + # Declared with BitStruct.hex_octets. + class HexOctetField < BitStruct::OctetField + # Used in describe. + def self.class_name + @class_name ||= "hex_octets" + end + + SEPARATOR = ":" + FORMAT = "%02x" + BASE = 16 + end + + class << self + # Define an octet string field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). Trailing nulls are + # not considered part of the string. The field is accessed using + # period-separated hex digits. + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + def hex_octets(name, length, *rest) + opts = parse_options(rest, name, HexOctetField) + add_field(name, length, opts) + end + end +end +#require 'bit-struct/bit-struct' + +class BitStruct + # Class for nesting a BitStruct as a field within another BitStruct. + # Declared with BitStruct.nest. + class NestedField < Field + def initialize(*args) + super + end + + # Used in describe. + def self.class_name + @class_name ||= "nest" + end + + def class_name + @class_name ||= nested_class.name[/\w+$/] + end + + def nested_class + @nested_class ||= options[:nested_class] || options["nested_class"] + end + + def describe opts + if opts[:expand] + opts = opts.dup + opts[:byte_offset] = offset / 8 + opts[:omit_header] = opts[:omit_footer] = true + nested_class.describe(nil, opts) {|desc| yield desc} + else + super + end + end + + def add_accessors_to(cl, attr = name) # :nodoc: + unless offset % 8 == 0 + raise ArgumentError, + "Bad offset, #{offset}, for nested field #{name}." + + " Must be multiple of 8." + end + + unless length % 8 == 0 + raise ArgumentError, + "Bad length, #{length}, for nested field #{name}." + + " Must be multiple of 8." + end + + offset_byte = offset / 8 + length_byte = length / 8 + last_byte = offset_byte + length_byte - 1 + byte_range = offset_byte..last_byte + val_byte_range = 0..length_byte-1 + + nc = nested_class + + cl.class_eval do + define_method attr do || + nc.new(self[byte_range]) + end + + define_method "#{attr}=" do |val| + if val.length != length_byte + raise ArgumentError, "Size mismatch in nested struct assignment " + + "to #{attr} with value #{val.inspect}" + end + + if val.class != nc + warn "Type mismatch in nested struct assignment " + + "to #{attr} with value #{val.inspect}" + end + + self[byte_range] = val[val_byte_range] + end + end + end + end + + class << self + # Define a nested field in the current subclass of BitStruct, + # with the given _name_ and _nested_class_. Length is determined from + # _nested_class_. + # + # In _rest_: + # + # If a class is provided, use it for the Field class (i.e. <=NestedField). + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # WARNING: the accessors have COPY semantics, not reference. When you call a + # reader method to get the nested structure, you get a *copy* of that data. + # + # For example: + # + # class Sub < BitStruct + # unsigned :x, 8 + # end + # + # class A < BitStruct + # nest :n, Sub + # end + # + # a = A.new + # + # p a # ==> #<A n=#<Sub x=0>> + # + # # This fails to set x in a. + # a.n.x = 3 + # p a # ==> #<A n=#<Sub x=0>> + # + # # This works + # n = a.n + # n.x = 3 + # a.n = n + # p a # ==> #<A n=#<Sub x=3>> + # + def nest(name, nested_class, *rest) + opts = parse_options(rest, name, NestedField) + opts[:default] ||= nested_class.initial_value.dup + opts[:nested_class] = nested_class + field = add_field(name, nested_class.bit_length, opts) + field + end + alias struct nest + end +end +#require 'bit-struct/bit-struct' + +class BitStruct + # Class for fixed length padding. + class PadField < Field + # Used in describe. + def self.class_name + @class_name ||= "padding" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + # No accessors for padding. + end + + def inspectable?; false; end + end + + class << self + # Define a padding field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + def pad(name, length, *rest) + opts = parse_options(rest, name, PadField) + add_field(name, length, opts) + end + alias padding pad + end +end +#require 'bit-struct/bit-struct' + +class BitStruct + # Class for signed integers in network order, 1-16 bits, or 8n bits. + # Declared with BitStruct.signed. + class SignedField < Field + # Used in describe. + def self.class_name + @class_name ||= "signed" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + offset_byte = offset / 8 + offset_bit = offset % 8 + + length_bit = offset_bit + length + length_byte = (length_bit/8.0).ceil + last_byte = offset_byte + length_byte - 1 + max = 2**length-1 + mid = 2**(length-1) + max_unsigned = 2**length + to_signed = proc {|n| (n>=mid) ? n - max_unsigned : n} +# to_signed = proc {|n| (n>=mid) ? -((n ^ max) + 1) : n} + + divisor = options[:fixed] || options["fixed"] + divisor_f = divisor && divisor.to_f +# if divisor and not divisor.is_a? Fixnum +# raise ArgumentError, "fixed-point divisor must be a fixnum" +# end + + endian = (options[:endian] || options["endian"]).to_s + case endian + when "native" + ctl = length_byte <= 2 ? "s" : "l" + if length == 16 or length == 32 + to_signed = proc {|n| n} + # with pack support, to_signed can be replaced with no-op + end + when "little" + ctl = length_byte <= 2 ? "v" : "V" + when "network", "big", "" + ctl = length_byte <= 2 ? "n" : "N" + else + raise ArgumentError, + "Unrecognized endian option: #{endian.inspect}" + end + + data_is_big_endian = + ([1234].pack(ctl) == [1234].pack(length_byte <= 2 ? "n" : "N")) + + if length_byte == 1 + rest = 8 - length_bit + mask = ["0"*offset_bit + "1"*length + "0"*rest].pack("B8")[0] + mask2 = ["1"*offset_bit + "0"*length + "1"*rest].pack("B8")[0] + + cl.class_eval do + if divisor + define_method attr do || + to_signed[(self[offset_byte] & mask) >> rest] / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[offset_byte] = + (self[offset_byte] & mask2) | ((val<<rest) & mask) + end + + else + define_method attr do || + to_signed[(self[offset_byte] & mask) >> rest] + end + + define_method "#{attr}=" do |val| + self[offset_byte] = + (self[offset_byte] & mask2) | ((val<<rest) & mask) + end + end + end + + elsif offset_bit == 0 and length % 8 == 0 + field_length = length + byte_range = offset_byte..last_byte + + cl.class_eval do + case field_length + when 8 + if divisor + define_method attr do || + to_signed[self[offset_byte]] / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[offset_byte] = val + end + + else + define_method attr do || + to_signed[self[offset_byte]] + end + + define_method "#{attr}=" do |val| + self[offset_byte] = val + end + end + + when 16, 32 + if divisor + define_method attr do || + to_signed[self[byte_range].unpack(ctl).first] / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[byte_range] = [val].pack(ctl) + end + + else + define_method attr do || + to_signed[self[byte_range].unpack(ctl).first] + end + + define_method "#{attr}=" do |val| + self[byte_range] = [val].pack(ctl) + end + end + + else + reader_helper = proc do |substr| + bytes = substr.unpack("C*") + bytes.reverse! unless data_is_big_endian + bytes.inject do |sum, byte| + (sum << 8) + byte + end + end + + writer_helper = proc do |val| + bytes = [] + val += max_unsigned if val < 0 + while val > 0 + bytes.push val % 256 + val = val >> 8 + end + if bytes.length < length_byte + bytes.concat [0] * (length_byte - bytes.length) + end + + bytes.reverse! if data_is_big_endian + bytes.pack("C*") + end + + if divisor + define_method attr do || + to_signed[reader_helper[self[byte_range]] / divisor_f] + end + + define_method "#{attr}=" do |val| + self[byte_range] = writer_helper[(val * divisor).round] + end + + else + define_method attr do || + to_signed[reader_helper[self[byte_range]]] + end + + define_method "#{attr}=" do |val| + self[byte_range] = writer_helper[val] + end + end + end + end + + elsif length_byte == 2 # unaligned field that fits within two whole bytes + byte_range = offset_byte..last_byte + rest = 16 - length_bit + + mask = ["0"*offset_bit + "1"*length + "0"*rest] + mask = mask.pack("B16").unpack(ctl).first + + mask2 = ["1"*offset_bit + "0"*length + "1"*rest] + mask2 = mask2.pack("B16").unpack(ctl).first + + cl.class_eval do + if divisor + define_method attr do || + to_signed[(self[byte_range].unpack(ctl).first & mask) >> rest] / + divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + x = (self[byte_range].unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl) + end + + else + define_method attr do || + to_signed[(self[byte_range].unpack(ctl).first & mask) >> rest] + end + + define_method "#{attr}=" do |val| + x = (self[byte_range].unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl) + end + end + end + + elsif length_byte == 3 # unaligned field that fits within 3 whole bytes + byte_range = offset_byte..last_byte + rest = 32 - length_bit + + mask = ["0"*offset_bit + "1"*length + "0"*rest] + mask = mask.pack("B32").unpack(ctl).first + + mask2 = ["1"*offset_bit + "0"*length + "1"*rest] + mask2 = mask2.pack("B32").unpack(ctl).first + + cl.class_eval do + if divisor + define_method attr do || + bytes = self[byte_range] + bytes << 0 + to_signed[((bytes.unpack(ctl).first & mask) >> rest)] / + divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + bytes = self[byte_range] + bytes << 0 + x = (bytes.unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl)[0..2] + end + + else + define_method attr do || + bytes = self[byte_range] + bytes << 0 + to_signed[(bytes.unpack(ctl).first & mask) >> rest] + end + + define_method "#{attr}=" do |val| + bytes = self[byte_range] + bytes << 0 + x = (bytes.unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl)[0..2] + end + end + end + + else + raise "unsupported: #{inspect}" + end + end + end + + class << self + # Define a signed integer field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # SignedField adds the <tt>:fixed => divisor</tt> option, which specifies + # that the internally stored value is interpreted as a fixed point real + # number with the specified +divisor+. + # + # The <tt>:endian => :native</tt> option overrides the default of + # <tt>:network</tt> byte ordering, in favor of native byte ordering. Also + # permitted are <tt>:big</tt> (same as <tt>:network</tt>) and + # <tt>:little</tt>. + # + def signed name, length, *rest + opts = parse_options(rest, name, SignedField) + add_field(name, length, opts) + end + end +end +#require 'bit-struct/bit-struct' + +class BitStruct + # Class for null-terminated printable text strings. + # Declared with BitStruct.text. + class TextField < Field + # Used in describe. + def self.class_name + @class_name ||= "text" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + unless offset % 8 == 0 + raise ArgumentError, + "Bad offset, #{offset}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + unless length % 8 == 0 + raise ArgumentError, + "Bad length, #{length}, for #{self.class} #{name}." + + " Must be multiple of 8." + end + + offset_byte = offset / 8 + length_byte = length / 8 + last_byte = offset_byte + length_byte - 1 + byte_range = offset_byte..last_byte + val_byte_range = 0..length_byte-1 + + cl.class_eval do + define_method attr do || + self[byte_range].sub(/\0*$/, "").to_s + end + + define_method "#{attr}=" do |val| + val = val.to_s + if val.length < length_byte + val += "\0" * (length_byte - val.length) + end + self[byte_range] = val[val_byte_range] + end + end + end + end + + class << self + # Define a printable text string field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). Trailing nulls are + # _not_ considered part of the string. + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # Note that the accessors have COPY semantics, not reference. + # + def text(name, length, *rest) + opts = parse_options(rest, name, TextField) + add_field(name, length, opts) + end + end +end +#require 'bit-struct/bit-struct' + +class BitStruct + # Class for unsigned integers in network order, 1-16 bits, or 8n bits. + # Declared with BitStruct.unsigned. + class UnsignedField < Field + # Used in describe. + def self.class_name + @class_name ||= "unsigned" + end + + def add_accessors_to(cl, attr = name) # :nodoc: + offset_byte = offset / 8 + offset_bit = offset % 8 + + length_bit = offset_bit + length + length_byte = (length_bit/8.0).ceil + last_byte = offset_byte + length_byte - 1 + + divisor = options[:fixed] || options["fixed"] + divisor_f = divisor && divisor.to_f +# if divisor and not divisor.is_a? Fixnum +# raise ArgumentError, "fixed-point divisor must be a fixnum" +# end + + endian = (options[:endian] || options["endian"]).to_s + case endian + when "native" + ctl = length_byte <= 2 ? "S" : "L" + when "little" + ctl = length_byte <= 2 ? "v" : "V" + when "network", "big", "" + ctl = length_byte <= 2 ? "n" : "N" + else + raise ArgumentError, + "Unrecognized endian option: #{endian.inspect}" + end + + data_is_big_endian = + ([1234].pack(ctl) == [1234].pack(length_byte <= 2 ? "n" : "N")) + + if length_byte == 1 + rest = 8 - length_bit + mask = ["0"*offset_bit + "1"*length + "0"*rest].pack("B8")[0] + mask2 = ["1"*offset_bit + "0"*length + "1"*rest].pack("B8")[0] + + cl.class_eval do + if divisor + define_method attr do || + ((self[offset_byte] & mask) >> rest) / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[offset_byte] = + (self[offset_byte] & mask2) | ((val<<rest) & mask) + end + + else + define_method attr do || + (self[offset_byte] & mask) >> rest + end + + define_method "#{attr}=" do |val| + self[offset_byte] = + (self[offset_byte] & mask2) | ((val<<rest) & mask) + end + end + end + + elsif offset_bit == 0 and length % 8 == 0 + field_length = length + byte_range = offset_byte..last_byte + + cl.class_eval do + case field_length + when 8 + if divisor + define_method attr do || + self[offset_byte] / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[offset_byte] = val + end + + else + define_method attr do || + self[offset_byte] + end + + define_method "#{attr}=" do |val| + self[offset_byte] = val + end + end + + when 16, 32 + if divisor + define_method attr do || + self[byte_range].unpack(ctl).first / divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + self[byte_range] = [val].pack(ctl) + end + + else + define_method attr do || + self[byte_range].unpack(ctl).first + end + + define_method "#{attr}=" do |val| + self[byte_range] = [val].pack(ctl) + end + end + + else + reader_helper = proc do |substr| + bytes = substr.unpack("C*") + bytes.reverse! unless data_is_big_endian + bytes.inject do |sum, byte| + (sum << 8) + byte + end + end + + writer_helper = proc do |val| + bytes = [] + while val > 0 + bytes.push val % 256 + val = val >> 8 + end + if bytes.length < length_byte + bytes.concat [0] * (length_byte - bytes.length) + end + + bytes.reverse! if data_is_big_endian + bytes.pack("C*") + end + + if divisor + define_method attr do || + reader_helper[self[byte_range]] / divisor_f + end + + define_method "#{attr}=" do |val| + self[byte_range] = writer_helper[(val * divisor).round] + end + + else + define_method attr do || + reader_helper[self[byte_range]] + end + + define_method "#{attr}=" do |val| + self[byte_range] = writer_helper[val] + end + end + end + end + + elsif length_byte == 2 # unaligned field that fits within two whole bytes + byte_range = offset_byte..last_byte + rest = 16 - length_bit + + mask = ["0"*offset_bit + "1"*length + "0"*rest] + mask = mask.pack("B16").unpack(ctl).first + + mask2 = ["1"*offset_bit + "0"*length + "1"*rest] + mask2 = mask2.pack("B16").unpack(ctl).first + + cl.class_eval do + if divisor + define_method attr do || + ((self[byte_range].unpack(ctl).first & mask) >> rest) / + divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + x = (self[byte_range].unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl) + end + + else + define_method attr do || + (self[byte_range].unpack(ctl).first & mask) >> rest + end + + define_method "#{attr}=" do |val| + x = (self[byte_range].unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl) + end + end + end + + elsif length_byte == 3 # unaligned field that fits within 3 whole bytes + byte_range = offset_byte..last_byte + rest = 32 - length_bit + + mask = ["0"*offset_bit + "1"*length + "0"*rest] + mask = mask.pack("B32").unpack(ctl).first + + mask2 = ["1"*offset_bit + "0"*length + "1"*rest] + mask2 = mask2.pack("B32").unpack(ctl).first + + cl.class_eval do + if divisor + define_method attr do || + bytes = self[byte_range] + bytes << 0 + ((bytes.unpack(ctl).first & mask) >> rest) / + divisor_f + end + + define_method "#{attr}=" do |val| + val = (val * divisor).round + bytes = self[byte_range] + bytes << 0 + x = (bytes.unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl)[0..2] + end + + else + define_method attr do || + bytes = self[byte_range] + bytes << 0 + (bytes.unpack(ctl).first & mask) >> rest + end + + define_method "#{attr}=" do |val| + bytes = self[byte_range] + bytes << 0 + x = (bytes.unpack(ctl).first & mask2) | + ((val<<rest) & mask) + self[byte_range] = [x].pack(ctl)[0..2] + end + end + end + + else + raise "unsupported: #{inspect}" + end + end + end + + class << self + # Define a unsigned integer field in the current subclass of BitStruct, + # with the given _name_ and _length_ (in bits). + # + # If a class is provided, use it for the Field class. + # If a string is provided, use it for the display_name. + # If a hash is provided, use it for options. + # + # UnsignedField adds the <tt>:fixed => divisor</tt> option, which specifies + # that the internally stored value is interpreted as a fixed point real + # number with the specified +divisor+. + # + # The <tt>:endian => :native</tt> option overrides the default of + # <tt>:network</tt> byte ordering, in favor of native byte ordering. Also + # permitted are <tt>:big</tt> (same as <tt>:network</tt>) and + # <tt>:little</tt>. + # + def unsigned name, length, *rest + opts = parse_options(rest, name, UnsignedField) + add_field(name, length, opts) + end + end +end +#require 'bit-struct/bit-struct' +require 'yaml' + +class BitStruct + if RUBY_VERSION == "1.8.2" + def is_complex_yaml? # :nodoc: + true + end + + YAML.add_ruby_type(/^bitstruct/) do |type, val| + subtype, subclass = YAML.read_type_class(type, Object) + subclass.new(val) + end + + def to_yaml_type # :nodoc: + "!ruby/bitstruct:#{self.class}" + end + + def to_yaml( opts = {} ) # :nodoc: + opts[:DocType] = self.class if Hash === opts + YAML.quick_emit(self.object_id, opts) do |out| + out.map(to_yaml_type) do |map| + fields.each do |field| + fn = field.name + map.add(fn, send(fn)) + end + end + end + end + + else + yaml_as "tag:path.berkeley.edu,2006:bitstruct" + + def to_yaml_properties # :nodoc: + yaml_fields = fields.select {|field| field.inspectable?} + props = yaml_fields.map {|f| f.name.to_s} + if (rest_field = self.class.rest_field) + props << rest_field.name.to_s + end + props + end + + # Return YAML representation of the BitStruct. + def to_yaml( opts = {} ) + YAML::quick_emit( object_id, opts ) do |out| + out.map( taguri, to_yaml_style ) do |map| + to_yaml_properties.each do |m| + map.add( m, send( m ) ) + end + end + end + end + + def self.yaml_new( klass, tag, val ) # :nodoc: + unless Hash === val + raise YAML::TypeError, "Invalid BitStruct: " + val.inspect + end + + bitstruct_name, bitstruct_type = YAML.read_type_class( tag, BitStruct ) + + st = bitstruct_type.new + + val.each do |k,v| + st.send( "#{k}=", v ) + end + + st + end + end +end + +#!/usr/bin/env ruby +# +# Copyright (C) 2008 Elan Feingold (elan at bluemandrill dot com) +# +# 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, 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 GNU Make; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +# +# + +#require 'bit-struct' + +# For example, "_calloc" => "_wrap_calloc" +prefix = '___wrap_' +mappings = { +'calloc' => true, +'clearerr' => true, +'close' => true, +'fclose' => true, +'fdopen' => true, +'feof' => true, +'ferror' => true, +'fflush' => true, +'fgetc' => true, +'fgetpos' => true, +'fgets' => true, +'fileno' => true, +'flockfile' => true, +'fopen' => true, +'fopen64' => true, +'fprintf' => true, +'fputc' => true, +'fputs' => true, +'fread' => true, +'free' => true, +'freopen' => true, +'fseek' => true, +'fsetpos' => true, +'fstatvfs64' => true, +'ftell' => true, +'ftrylockfile' => true, +'funlockfile' => true, +'fwrite' => true, +'getc_unlocked' => true, +'ioctl' => true, +'lseek' => true, +'lseek64' => true, +'malloc' => true, +'open' => true, +'open64' => true, +'popen' => true, +'printf' => true, +'read' => true, +'realloc' => true, +'rewind' => true, +'stat' => true, +'fstat' => true, +'ungetc' => true, +'vfprintf' => true, +'write' => true, +'putc' => '___wrap__IO_putc', +'getc' => '___wrap__IO_getc', +'getc_unlocked' => '___wrap__IO_getc_unlocked' +} + +prefix_python = '___py_wrap_' +mappings_python = { + 'getcwd' => true, 'chdir' => true, 'access' => true, 'unlink' => true, 'chmod' => true, + 'rmdir' => true, 'utime' => true, 'rename' => true, 'mkdir' => true, + 'opendir' => true, 'dlopen' => true, 'dlclose' => true, 'dlsym' => true, + 'lstat' => true +} + +LC_SYMTAB = 0x02 +LC_SEGMENT = 0x01 + +class MachHeader < BitStruct + hex_octets :magic, 32, "Magic Number" + unsigned :cputype, 32, "CPU Type", :endian => :native + unsigned :cpusubtype, 32, "CPU Subtype", :endian => :native + unsigned :filetype, 32, "File Type", :endian => :native + unsigned :ncmds, 32, "Number of commands", :endian => :native + unsigned :sizeofcmds, 32, "Size of commands", :endian => :native + unsigned :flags, 32, "Flags", :endian => :native + rest :data, "Data" +end + +class LoadCommand < BitStruct + unsigned :cmd, 32, "Command", :endian => :native + unsigned :cmdsize, 32, "Command Size", :endian => :native +end + +class SymtabCommand < BitStruct + unsigned :cmd, 32, "Command", :endian => :native + unsigned :cmdsize, 32, "Command Size", :endian => :native + unsigned :symoff, 32, "Symbol Offset", :endian => :native + unsigned :nsyms, 32, "Number of Symbols", :endian => :native + unsigned :stroff, 32, "String table offset", :endian => :native + unsigned :strsize, 32, "Size of string table", :endian => :native +end + +class SegmentCommand < BitStruct + unsigned :cmd, 32, "Command", :endian => :native + unsigned :cmdsize, 32, "Command Size", :endian => :native + char :segname, 16*8, "Segment name", :endian => :native + unsigned :vmaddr, 32, "VM Adddress", :endian => :native + unsigned :vmsize, 32, "VM Size", :endian => :native + unsigned :fileoff, 32, "File Offset", :endian => :native + unsigned :filesize, 32, "File Size", :endian => :native +end + +class SymtabEntry < BitStruct + unsigned :strtableoffset, 32, "String table offset", :endian => :native + unsigned :debuggingEntry, 3, "Debugging entry", :endian => :native + unsigned :privateExternal, 1, "Is Private Enternal", :endian => :native + unsigned :type, 3, "Type bits", :endian => :native + unsigned :external, 1, "External symbol", :endian => :native + unsigned :sectionNumber, 8, "Section number", :endian => :native + unsigned :description, 16, "Description", :endian => :native + unsigned :value, 32, "Value", :endian => :native +end + +# Select which mapping to use. +if ARGV.size() > 1 and ARGV[1].index('libpython') == 0 + puts "Using Python mappings." + mappings = mappings_python + #prefix = prefix_python +end + +data = open(ARGV[0]).read +puts "Input file was #{data.length} bytes long." + +# Parse the header. +header = MachHeader.new(data) +sym_cmd = nil + +# String table. +string_table = nil +string_table_offset = nil +string_table_map = {} +offset_map = {} + +# Symbol table. +symbol_table = nil +symbol_table_offset = nil +symbols = [] + +# Link segment. +link_cmd = nil +link_cmd_offset = nil + +# Walk through all the commands. +offset = data.size - header.data.size +header.ncmds.times do |i| + load_cmd = LoadCommand.new(data[offset..-1]) + + if load_cmd.cmd == LC_SEGMENT + seg_cmd = SegmentCommand.new(data[offset..-1]) + if seg_cmd.segname.index('__LINKEDIT') == 0 + puts "Found LINKEDIT segment at offset #{offset}" + link_cmd = seg_cmd + link_cmd_offset = offset + end + end + + if load_cmd.cmd == LC_SYMTAB + # Parse the symbol table command. + sym_cmd = SymtabCommand.new(data[offset..-1]) + symbol_table_offset = offset + + # Parse the string table, store with offsets. + string_table_offset = sym_cmd.stroff + string_table = data[sym_cmd.stroff..sym_cmd.stroff+sym_cmd.strsize-1] + i = 0 + string_table.split("\x00", -1).each do |s| + string_table_map[i] = s + i += s.length + 1 + end + + # Parse the symbol table. + symbol_table = data[sym_cmd.symoff..-1] + i = 0 + puts "Symbol table has #{sym_cmd.nsyms} symbols." + sym_cmd.nsyms.times do |n| + symbols << SymtabEntry.new(symbol_table[i..i+11]) + i += 12 + end + + # Now go through and make renames to the symbols. + size_diff = 0 + + string_table_map.keys.sort.each do |i| + orig_sym = string_table_map[i] + + # Store the offset mapping. + offset_map[i] = (i + size_diff) + + if orig_sym.length > 1 + sym = orig_sym[1..-1].gsub('$UNIX2003','') + if mappings.has_key?(sym) + if mappings[sym] != true + string_table_map[i] = mappings[sym] + else + string_table_map[i] = "#{prefix}#{sym}" + end + puts " - Mapping: #{orig_sym} to #{string_table_map[i]} (offset #{i} -> #{i + size_diff})" + + # Accumulate the offset difference. + size_diff += string_table_map[i].length - orig_sym.length + end + end + end + end + + offset += load_cmd.cmdsize +end + +# OK, now lets rewrite the symbol table. Offsets may have changed, but the size doesn't. +new_symbol_table = '' +i = 0 +symbols.each do |symbol| + puts " - Mapped #{i} symbols..." if i % 10000 == 0 and i > 0 + symbol.strtableoffset = offset_map[symbol.strtableoffset] if symbol.strtableoffset > 1 + new_symbol_table << symbol + i += 1 +end + +# OK, now lets rewrite the string table. The size will be different if mappings have occurred. +new_string_table = string_table_map.keys.sort.collect { |i| string_table_map[i] }.join("\x00") + +# Next, modify the LC_SYMTAB header. +size_diff = new_string_table.length - sym_cmd.strsize +sym_cmd.strsize = new_string_table.length + +# Lastly, modify the LINKEDIT segment if it exists. +if link_cmd + puts "Size changed by #{size_diff} bytes, rewriting LINKEDIT segment." + link_cmd.filesize += size_diff + SegmentCommand.round_byte_length.times { |i| data[link_cmd_offset + i] = link_cmd[i] } +end + +# Create the new file in memory. First, copy the new symbol table header into place. +24.times { |i| data[symbol_table_offset + i] = sym_cmd[i] } + +# Now copy the new symbol table. +new_symbol_table.length.times { |i| data[sym_cmd.symoff + i] = new_symbol_table[i] } + +# Finally, add the new string table. +data = data[0..string_table_offset-1] + new_string_table + +puts "Output file is #{data.length} bytes long." +open("output.so", "wb").write(data) diff --git a/tools/MingwBuildEnvironment/Readme.txt b/tools/MingwBuildEnvironment/Readme.txt new file mode 100644 index 0000000000..cc1a7314f8 --- /dev/null +++ b/tools/MingwBuildEnvironment/Readme.txt @@ -0,0 +1,14 @@ +Mingw build environment to build ffmpeg and other libraries
+
+Installation:
+extract msys.7z to c:\
+
+Open a shell:
+run c:\msys\msys.bat
+
+Source:
+The environment was compiled like described here: http://ffmpeg.arrozcru.org/wiki/index.php?title=Main_Page
+
+Changes:
+I had to adapt the file c:\msys\mingw\include\vfw.h in order to build without errors. This change might need to be reverted for later builds.
+To do so open the file in an editor and remove the comments from line 673 to 708 (CAPTUREPARMS and VIDEOHDR are already defined in libavcodec).
\ No newline at end of file diff --git a/tools/MingwBuildEnvironment/msys.7z b/tools/MingwBuildEnvironment/msys.7z Binary files differnew file mode 100644 index 0000000000..094abff553 --- /dev/null +++ b/tools/MingwBuildEnvironment/msys.7z diff --git a/tools/PackageMaker/VolumeDSStore b/tools/PackageMaker/VolumeDSStore Binary files differnew file mode 100644 index 0000000000..387b6e21eb --- /dev/null +++ b/tools/PackageMaker/VolumeDSStore diff --git a/tools/PackageMaker/VolumeDSStoreApp b/tools/PackageMaker/VolumeDSStoreApp Binary files differnew file mode 100644 index 0000000000..f1a82a4bbb --- /dev/null +++ b/tools/PackageMaker/VolumeDSStoreApp diff --git a/tools/PackageMaker/VolumeIcon.icns b/tools/PackageMaker/VolumeIcon.icns Binary files differnew file mode 100644 index 0000000000..75215701b6 --- /dev/null +++ b/tools/PackageMaker/VolumeIcon.icns diff --git a/tools/PackageMaker/XBMC Package.pmdoc/01xbmc-contents.xml b/tools/PackageMaker/XBMC Package.pmdoc/01xbmc-contents.xml new file mode 100644 index 0000000000..6eb39c4b8c --- /dev/null +++ b/tools/PackageMaker/XBMC Package.pmdoc/01xbmc-contents.xml @@ -0,0 +1 @@ +<pkg-contents spec="1.12"><f n="XBMC.app" o="root" g="admin" p="16893" pt="/Users/d4rk/Code/XBMC/XBMC/build/Release/XBMC.app" m="true" t="file"><f n="Contents" o="root" g="admin" p="16893"><f n="Frameworks" o="root" g="admin" p="16893"><f n="libbz2.1.0.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libcrypto.0.9.8.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libexpat.1.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libfontconfig.1.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libfreetype.6.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libfribidi.0.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libGLEW.1.5.0.dylib" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="libiconv.2.dylib" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="liblzo.1.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libmad.0.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libmysqlclient.15.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libogg.0.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libpcre.0.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libpng12.0.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libsmbclient.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libssl.0.9.8.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libvorbis.0.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libz.1.dylib" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="Info.plist" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MacOS" o="root" g="admin" p="16893"><f n="XBMC" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="Resources" o="root" g="admin" p="16893"><f n="XBMC" o="root" g="admin" p="16893"><f n="language" o="root" g="admin" p="16893"><f n="Catalan" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Chinese (Simple)" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Chinese (Traditional)" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Croatian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Czech" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Danish" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Dutch" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="English" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="English (US)" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Esperanto" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Finnish" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="French" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="German" o="root" g="admin" p="16893"><f n="keyboardmap.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="German (Austria)" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Greek" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Hebrew" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Hungarian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Icelandic" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Indonesian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Italian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Japanese" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Korean" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Maltese" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Norwegian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Polish" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Portuguese" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Portuguese (Brazil)" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Romanian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Russian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Serbian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Slovak" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Slovenian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Spanish" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Swedish" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Turkish" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Ukrainian" o="root" g="admin" p="16893"><f n="langinfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="media" o="root" g="admin" p="16893"><f n="Fonts" o="root" g="admin" p="16893"><f n="arial.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="icon.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Splash.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Splash_Xmas.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="weather.rar" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="xbmc.icns" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="xbmc.old.icns" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="org.xbmc.helper.plist" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="plugins" o="root" g="admin" p="16893"><f n="music" o="root" g="admin" p="16893"><mod>mode</mod></f><f n="pictures" o="root" g="admin" p="16893"><mod>mode</mod></f><f n="video" o="root" g="admin" p="16893"><mod>mode</mod></f><mod>mode</mod></f><f n="screensavers" o="root" g="admin" p="16893"><mod>mode</mod></f><f n="scripts" o="root" g="admin" p="16893"><mod>mode</mod></f><f n="skin" o="root" g="admin" p="16893"><f n="MediaStream" o="root" g="admin" p="16893"><f n="720p" o="root" g="admin" p="16893"><f n="Custom1001_SkinSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Custom1002_OptionsMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CustomSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Defaults.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogAlbumInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogBusy.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogButtonMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogContentSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogContextMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFavourites.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFileStacking.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogGamepad.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogHost.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogInvite.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogKaiToast.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogKeyboard.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMediaSource.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMusicScan.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMuteBug.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogNetworkSetup.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogNumeric.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogOk.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogPictureInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogPluginSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogProgress.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogScriptInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSeekBar.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSelect.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSongInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVideoInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVideoScan.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVolumeBar.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogYesNo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="FileBrowser.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="FileManager.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Includes.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="IncludesDims.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="LockSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="LoginScreen.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOSD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOSDVisSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOverlay.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicVisualisation.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyBuddies.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyGameSaves.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicNav.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicPlaylist.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicPlaylistEditor.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicSongs.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyPics.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyPrograms.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyScripts.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideoNav.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideoPlaylist.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyWeather.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OptionsMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Pointer.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ProfileSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-chooser.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-context.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-main.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-search.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-settings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-showtimes.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Settings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsCategory.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsProfile.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsScreenCalibration.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsSystemInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SlideShow.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SmartPlaylistEditor.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SmartPlaylistRule.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Startup.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="TrainerSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoFullScreen.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSDBookmarks.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSDSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOverlay.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ViewsCommon.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ViewsCoverflow.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ViewsMusic.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ViewsPics.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ViewsVideo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VisualisationPresetList.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="colors" o="root" g="admin" p="16893"><f n="Defaults.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="extras" o="root" g="admin" p="16893"><f n="XBMC Lyrics" o="root" g="admin" p="16893"><f n="default.py" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default.tbn" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="resources" o="root" g="admin" p="16893"><f n="__init__.py" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="__init__.pyo" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="language" o="root" g="admin" p="16893"><f n="dutch" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="english" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="finnish" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="french" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="german" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="polish" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="spanish" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="swedish" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="lib" o="root" g="admin" p="16893"><f n="__init__.py" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="__init__.pyo" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="credits.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="gui.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="gui.pyo" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="language.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="language.pyo" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="playlist.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="settings.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="update.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="utilities.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="utilities.pyo" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="scrapers" o="root" g="admin" p="16893"><f n="__init__.py" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="__init__.pyo" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="embedded" o="root" g="admin" p="16893"><f n="__init__.py" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="lyricsScraper.py" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="lyrc.com.ar" o="root" g="admin" p="16893"><f n="__init__.py" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="lyricsScraper.py" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="lyricwiki" o="root" g="admin" p="16893"><f n="__init__.py" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="__init__.pyo" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="lyricsScraper.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="lyricsScraper.pyo" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="skins" o="root" g="admin" p="16893"><f n="Default" o="root" g="admin" p="16893"><f n="media" o="root" g="admin" p="16893"><f n="default-black.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-dialog-panel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-homeinfo-bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-input-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-input-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-keyboard-btn-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-keyboard-btn.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-list-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-list-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-panel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-progress_back.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-progress_left.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-progress_mid.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-progress_right.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-scroll-down-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-scroll-down.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-scroll-up-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-scroll-up.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-separatorOSD.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-settings-check-box.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default-settings-check-boxNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="PAL" o="root" g="admin" p="16893"><f n="script-XBMC_Lyrics-credits.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-XBMC_Lyrics-main.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-XBMC_Lyrics-settings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="PAL16x9" o="root" g="admin" p="16893"><f n="script-XBMC_Lyrics-main.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="fonts" o="root" g="admin" p="16893"><f n="Default.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultCaps.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Title.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="TitleCaps.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="language" o="root" g="admin" p="16893"><f n="Chinese (Traditional)" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Dutch" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="English" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="French" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="German" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Greek" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Hebrew" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Polish" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Portuguese" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Spanish" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Swedish" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="media" o="root" g="admin" p="16893"><f n="textures.xpr" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="PAL" o="root" g="admin" p="16893"><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="IncludesDims.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="skin.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sounds" o="root" g="admin" p="16893"><f n="Back.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Click.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Cursor.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Notify.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Out.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Shutter.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sounds.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Start.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="PM3.HD" o="root" g="admin" p="16893"><f n="720p" o="root" g="admin" p="16893"><f n="custom_SkinSetting_1111.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaults.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogAlbumInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogBusy.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogButtonMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogContentSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogContextMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFavourites.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFileStacking.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFullScreenInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogGamepad.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogKaiToast.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogKeyboard.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMediaSource.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMusicScan.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMuteBug.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogNetworkSetup.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogNumeric.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogOK.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogPictureInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogPluginSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogProgress.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogScriptInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSeekBar.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSelect.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSongInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVideoInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVideoScan.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVolumeBar.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogYesNo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="FileBrowser.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="FileManager.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="includes.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="LockSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="LoginScreen.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOSD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOSDVisSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOverlay.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicVisualisation.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyGameSaves.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicNav.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicPlaylist.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicPlaylistEditor.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicSongs.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyPics.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyPrograms.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyScripts.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideoNav.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideoPlaylist.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyWeather.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Pointer.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ProfileSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-chooser.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-context.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-main.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-search.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-settings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-Apple_Movie_Trailers-showtimes.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-XBMC_Lyrics-main.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="script-XBMC_Lyrics-settings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Settings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsCategory.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsProfile.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsScreenCalibration.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsSystemInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SlideShow.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SmartPlaylistEditor.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SmartPlaylistRule.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Startup.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="TrainerSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoFullScreen.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSDBookmarks.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSDSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOverlay.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ViewsFileMode.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ViewsVideoLibrary.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VisualisationPresetList.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="build.bat" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="colors" o="root" g="admin" p="16893"><f n="defaults.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="fonts" o="root" g="admin" p="16893"><f n="humanist_521_bt.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="humanist_521_condensed_bt.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Liberation-Font-License.txt" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="LiberationSans-Regular.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="HomeSytemIcon Licence.txt" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Icons.txt" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="language" o="root" g="admin" p="16893"><f n="English" o="root" g="admin" p="16893"><f n="strings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="media" o="root" g="admin" p="16893"><f n="amt-blank-poster.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-generic-actor.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-generic-genre-i.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-generic-genre.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-generic-noactor.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-generic-studio.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-generic-trailer-w.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-generic-trailer.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-overlay-favorite.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-overlay-saved.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="amt-overlay-watched.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Apple Movie Trailers" o="root" g="admin" p="16893"><f n="G.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="NC-17.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="NR.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PG-13.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PG.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="R.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Background-Home-2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Background-Home.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-music.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-pictures.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-scripts.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-settings.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-videos.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-weather.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Background.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Barground2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="black-back.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="black-back2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy" o="root" g="admin" p="16893"><f n="busy1.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy4.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy5.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy6.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy7.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy8.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="button-focus-keyboard.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-focus-toggle-off.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-focus-toggle-on.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-focus2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-nofocus-toggle-off.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-nofocus-toggle-on.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Button_Side_Focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Button_Side_NoFocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-bottomright-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-bottomright.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-pixelratio-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-pixelratio.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-subtitles-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-subtitles.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-topleft-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-topleft.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="close-window.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="close-windowFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ContextMenu_Bottom.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ContextMenu_Middle.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ContextMenu_Top.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultActorBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultAddSource.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultAlbumCover.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultArtistBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultaudiobig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultcddabig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultDVDEmptyBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultdvdrombig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultFile.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultFileBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultfolderbackbig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultfolderbig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultharddiskbig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultLockedBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultnetworkbig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultpicturebig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultplaylistbig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultprogrambig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultScriptBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultshortcutbig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultvideobig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultVideoCover.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultxboxdvdbig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogBack.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFront.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogLeft.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMiddle.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogRight.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="diffuse_mirror.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="diffuse_mirror2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fanart_Diffuse.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filemanager-select.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="folder-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Footer.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="gradient.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Header.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-button-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-button.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-favourites-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-favourites.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home-Menu-Back.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-playmedia-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-playmedia.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-power-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-power.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="homeinfo-blank.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="homeinfo-system.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_appearence.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_apps.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_files.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_music.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_network.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_pics.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_scripts.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_settings.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_system.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_video.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="icon_weather.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="lastfm-hate-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="lastfm-hate-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="lastfm-love-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="lastfm-love-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="list-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="NoCover_1.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="NoCover_2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd-panel-top.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_audioFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_audioSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_bookmarkFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_bookmarkSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_dvdmenu.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_dvdmenu2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_dvdmenuNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_ffFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_ffSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_info_1.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_info_1_nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_info_2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_info_2_nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_lyrics.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_lyricsFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_pauseFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_pauseNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_playFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_playlistFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_playNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_presetsFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_presetsSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rec.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rec2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_recNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rewFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rewSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_skip_minusFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_skip_plusFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_stopFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_videoFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_videoSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_visFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_vizsettingsFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_vizsettingsSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_panel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_panel_audio.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_slider_bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_slider_nib.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_slider_nibNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayHasTrainer.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayHD.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayLocked.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayRAR.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayTrained.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayWatched.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Panel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Panel2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-ForwardFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-ForwardNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-FullScreenFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-FullScreenNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-NextFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-NextNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-PauseFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-PauseNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-PlayFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-PlayNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-PrevFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-PrevNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RandomFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RandomNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RandomOnFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RandomOnNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RepeatAllFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RepeatAllNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RepeatFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RepeatNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RepeatOneFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RepeatOneNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RewindFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-RewindNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-StopFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls-StopNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="pointer-focus-click.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="pointer-focus-drag.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="pointer-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="pointer-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="poster-shadow.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ProgressBack.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ProgressFront.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ProgressFront2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="radiobutton-focus-2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="radiobutton-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="radiobutton-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating0.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating1.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating4.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating5.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-down-2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-down-focus-2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-down-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-down.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-left-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-left.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-right-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-right.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-up-2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-up-focus-2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-up-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-up.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_bar-vertical.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_bar.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_bar_back.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_bar_back2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_bar_focus-vertical.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_bar_focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_nib-vertical.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_nib.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SeekbarMarker.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="seekslider.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="separator.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="slider_nibFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-background-label.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-background.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-eject-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-eject-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-favs-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-favs-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-info-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-info-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-logoff-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-logoff-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-master-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-master-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-nomaster-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-nomaster-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-reboot-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-reboot-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-shutdown-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-shutdown-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="thumb-back.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="unknown-user.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VeticalLight.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VolumeIcon-Mute.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VolumeIcon.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Wide_Icon_Diffuse.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="xbmc-logo.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="skin.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sounds" o="root" g="admin" p="16893"><f n="back.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="click.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="cursor.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="notify.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="out.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="shutter.wav" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sounds.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="Project Mayhem III" o="root" g="admin" p="16893"><f n="1080i" o="root" g="admin" p="16893"><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="720p" o="root" g="admin" p="16893"><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="build.bat" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="colors" o="root" g="admin" p="16893"><f n="defaults.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="fonts" o="root" g="admin" p="16893"><f n="FrancophilSans.ttf" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="FrancophilSans_readme.txt" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="media" o="root" g="admin" p="16893"><f n="ap-lock.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ap-signal1.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ap-signal2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ap-signal3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ap-signal4.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ap-signal5.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-apps.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-bottom.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-Login-Overlay.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-music.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-pics.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-plain.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-settings.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-videos.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background-weather.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="background.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ban-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ban.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="black.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="blue-rectangle.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="blue-rectangleNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="blue_rectangle_music.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="blue_rectangle_slideshow.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="blue_rectangle_video.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="blue_rectangle_weather.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="bluebar.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="bookmark-resume.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy" o="root" g="admin" p="16893"><f n="busy1.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy4.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy5.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy6.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy7.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="busy8.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="button-cd-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-cd-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="button-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-bottomright-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-bottomright.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-pixelratio-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-pixelratio.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-subtitles-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-subtitles.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-topleft-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="calibrate-topleft.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="check-box.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="check-boxNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Content_Panel_Diffuse.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="contentpanel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="contentpanel_left.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="default_icon_back.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultActorBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultAddSource.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultAlbumCover.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultArtistBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultAudio.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultAudioBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultCdda.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultCddaBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultDVDEmpty.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultDVDEmptyBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultDVDRom.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultDVDRomBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultFile.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultFileBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultFolder.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultFolderBack.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultFolderBackBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultFolderBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultHardDisk.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultHardDiskBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultLocked.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultLockedBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultNetwork.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultNetworkBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultPicture.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultPictureBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultPlaylist.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultPlaylistBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultProgram.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultProgramBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultScript.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultScriptBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultShortcut.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DefaultShortcutBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultVCD.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultVCDBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultVideo.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultVideoBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultVideoCover.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultXBOXDVD.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaultXBOXDVDBig.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="dialog-context-bottom.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="dialog-context-middle.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="dialog-context-top.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="dialog-panel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="dialog-panel2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="dialog-panellock.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="dialog-panelprofile.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="diffuse_mirror.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="dvdview_bottom.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filemanager.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filemanager_Panel_Sel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="folder-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="folder-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="gradient.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-dvd.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-dvd.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myfiles" o="root" g="admin" p="16893"><f n="home-myfiles.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myfiles2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myfiles3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="home-mymusic" o="root" g="admin" p="16893"><f n="home-mymusic.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-mymusic2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-mymusic3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-mymusic4.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="home-mypictures" o="root" g="admin" p="16893"><f n="home-mypictures.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-mypictures2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-mypictures3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="home-myprograms" o="root" g="admin" p="16893"><f n="home-myprograms.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myprograms2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myprograms3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="home-myvideos" o="root" g="admin" p="16893"><f n="home-myvideos.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myvideos2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myvideos3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="home-myweather" o="root" g="admin" p="16893"><f n="home-myweather.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myweather2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myweather3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-myweather4.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="home-power.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-power.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-scripts" o="root" g="admin" p="16893"><f n="home-scripts.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-scripts2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-scripts3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="home-settings" o="root" g="admin" p="16893"><f n="home-settings.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-settings2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-settings3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="home-sub.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home-sub.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home_Bottom.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="home_buttons.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home_Middle.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home_Top.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home_Top_16x9.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="homebutton-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="homebutton-small.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="homeinfo-bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="homeinfo-bgdrive.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="homeinfo-overlay.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="homeinfo-system.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="infoicon.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="input-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="input-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Kai_connected.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Kai_disconnected.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-backspace-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-backspace.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-done-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-done.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-dummyright.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-ip-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-ip.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-mid-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-mid-sel-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-mid-sel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-mid.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-next-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-next.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-num1-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-Num1.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-numclear-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-numclear.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-numenter-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-numenter.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-numnext-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-numnext.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-numprev-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-numprev.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-prev-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-prev.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-space-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-space-focus2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-space.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-topright-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn-topright.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-btn.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-numeric-bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-numeric-overlay.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-numeric-overlay2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-panel-overlay.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="keyboard-panel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="list-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="list-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="logo.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="love-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="love.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-ff-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-ff-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-pause-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-pause-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-play-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-play-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-random-off-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-random-off-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-random-on-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-random-on-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-repeat-all-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-repeat-all-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-repeat-off-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-repeat-off-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-repeat-one-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-repeat-one-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-rw-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-rw-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-skipminus-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-skipminus-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-skipplus-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-skipplus-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-stop-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="music-stop-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="mute.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_audioFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_audioSELFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_audioSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_bookmarkFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_bookmarkSELFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_bookmarkSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_dvdmenu.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_dvdmenu2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_dvdmenuNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_ffFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_ffSELFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_ffSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_pauseFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_pauseNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_playFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_playlistFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_playNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_presetsFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rec.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rec2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_recNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rewFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rewSELFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_rewSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_skip_minusFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_skip_minusSELFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_skip_minusSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_skip_plusFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_skip_plusSELFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_skip_plusSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_videoFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_videoSELFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_videoSELNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_visFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_button_vizsettingsFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_menu_bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_panel.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_panel_audio.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_settings_header.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_slider_bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_slider_nibFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_slider_nibNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_slider_volume_bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="osd_volumeslider.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OSDtime-panel-bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayHasTrainer.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayHD.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayLocked.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayRAR.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayTrained.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayUnwatched.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayWatched.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="OverlayZIP.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="panel2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="pointer-focus-click.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="pointer-focus-drag.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="pointer-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="pointer-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="progress_back.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="progress_back2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="progress_left.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="progress_mid.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="progress_over.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="progress_right.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="radiobutton-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="radiobutton-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating0.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating1.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating2.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating3.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating4.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="rating5.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Scan-panel-bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-down-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-down-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-down.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-left-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-left.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-right-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-right.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-up-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-up-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scroll-up.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_arrow_down.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_arrow_down_focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_arrow_up.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_arrow_up_focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_background.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_bar.PNG" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="scrollbar_bar_focus.PNG" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="seekslider.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="select-left-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="select-left.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="select-right-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="select-right.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="separator.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="separatorOSD.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-appearance-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-appearance-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-check-box.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-check-boxNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-divider.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-music-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-music-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-network-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-network-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-pictures-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-pictures-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-programs-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-programs-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-system-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-system-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-videos-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-videos-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-weather-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="settings-weather-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="slider_nibFO.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-background-label.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-background.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-eject-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-eject-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-exit-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-exit-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-favs-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-favs-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-info-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-info-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-logoff-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-logoff-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-master-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-master-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-nomaster-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-nomaster-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-reboot-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-reboot-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-shutdown-focus.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sub-shutdown-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="toggle-down.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="toggle-up.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="totalblack.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Trainer.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="TWClogo_64px.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="unknown-user.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-16x.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-16xr.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-2x.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-2xr.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-32x.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-32xr.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-4x.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-4xr.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-8x.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-8xr.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-info-button-focus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-info-button-nofocus.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="video-pause.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="voulume-panel-bg.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Wide_Icon_Diffuse.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="WideIcon.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="WideIconNF.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="NTSC" o="root" g="admin" p="16893"><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="NTSC16x9" o="root" g="admin" p="16893"><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="PAL" o="root" g="admin" p="16893"><f n="3D_CoverView.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CommonViewTypes.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CommonViewTypes_Dialogs.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CommonViewTypes_Library.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="custom2_SkinSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="defaults.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogAccessPoints.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogAlbumInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogBusy.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogButtonMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogContentSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogContextMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFavourites.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFileStacking.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogFullScreenInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogGamepad.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogKaiToast.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogKeyboard.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMediaSource.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMusicScan.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogMuteBug.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogNetworkSetup.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogNumeric.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogOK.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogPictureInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogPluginSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogProgress.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogScriptInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSeekBar.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSelect.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogSongInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVideoInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVideoScan.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogVolumeBar.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogYesNo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="FileBrowser.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="FileManager.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="includes.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="LockSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="LoginScreen.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOSD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOSDVisSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOverlay.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicVisualisation.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyGameSaves.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicNav.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicPlaylist.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicPlaylistEditor.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyMusicSongs.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyPics.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyPrograms.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyScripts.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideoNav.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyVideoPlaylist.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MyWeather.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PlayerControls.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Pointer.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ProfileSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Settings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsCategory.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsProfile.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsScreenCalibration.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SettingsSystemInfo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SlideShow.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SmartPlaylistEditor.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SmartPlaylistRule.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Startup.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="TrainerSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoFullScreen.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSDBookmarks.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSDSettings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOverlay.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VisualisationPresetList.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="PAL16x9" o="root" g="admin" p="16893"><f n="3D_CoverView.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CommonViewTypes.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CommonViewTypes_Dialogs.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CommonViewTypes_Library.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogBusy.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DialogButtonMenu.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Font.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Home.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="LoginScreen.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicOSD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MusicVisualisation.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Pointer.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Settings.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="SlideShow.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Startup.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="VideoOSD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="skin.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="sounds" o="root" g="admin" p="16893"><f n="back.wav" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="click.wav" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="cursor.wav" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="notify.wav" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="out.wav" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="shutter.wav" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="sounds.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="start.wav" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="sounds" o="root" g="admin" p="16893"><mod>mode</mod></f><f n="system" o="root" g="admin" p="16893"><f n="asound.conf" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="cdrip" o="root" g="admin" p="16893"><mod>mode</mod></f><f n="ImageLib-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="IRSSmap.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Keymap.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="libcurl-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libexif-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libid3tag-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="Lircmap.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="players" o="root" g="admin" p="16893"><f n="dvdplayer" o="root" g="admin" p="16893"><f n="avcodec-51-osx.a" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="avformat-51-osx.a" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="avutil-51-osx.a" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="liba52-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libao-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libass-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libdts-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libdvdcss-2-osx.so" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="libdvdnav-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libfaad-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libmad-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libmpeg2-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="postproc-51-osx.a" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="swscale-51-osx.a" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="paplayer" o="root" g="admin" p="16893"><f n="AACCodec-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="libFLAC-osx.so" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="libmpcdec-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="MACDll-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="MADCodec-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="vorbisfile-osx.so" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="python" o="root" g="admin" p="16893"><f n="DLLs" o="root" g="admin" p="16893"><f n="_socket.pyd" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_ssl.pyd" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="bz2.pyd" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="pyexpat.pyd" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="select.pyd" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="unicodedata.pyd" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="zlib.pyd" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="lib-osx" o="root" g="admin" p="16893"><f n="_AE.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_AH.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_App.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_bisect.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_CarbonEvt.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_CF.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_CG.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Cm.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_codecs_cn.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_codecs_hk.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_codecs_iso2022.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_codecs_jp.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_codecs_kr.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_codecs_tw.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_csv.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Ctl.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_curses.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_curses_panel.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Dlg.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Drag.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Evt.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_File.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Fm.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Folder.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_heapq.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Help.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_hotshot.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_IBCarbon.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Icn.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Launch.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_List.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_locale.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Menu.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Mlte.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_multibytecodec.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_OSA.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Qd.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Qdoffs.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Qt.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_random.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Res.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Scrap.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Snd.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_socket.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_ssl.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_TE.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_testcapi.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_tkinter.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_weakref.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="_Win.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="array.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="audioop.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="autoGIL.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="binascii.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="bsddb185.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="bz2.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="cmath.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="collections.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="ColorPicker.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="cPickle.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="crypt.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="cStringIO.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="datetime.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="dbm.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="fcntl.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="gestalt.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="grp.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="icglue.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="imageop.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="itertools.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="MacOS.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="math.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="md5.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="mmap.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="Nav.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="nis.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="operator.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="OSATerminology.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="parser.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="pyexpat.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="readline.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="regex.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="resource.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="rgbimg.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="select.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="sha.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="strop.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="struct.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="syslog.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="termios.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="time.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="timing.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="unicodedata.so" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="zlib.so" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="python24-osx.so" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="python24.zip" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="python24.zlib" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="readme.txt" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="spyce" o="root" g="admin" p="16893"><f n="CHANGES" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Cookie.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="fcgi.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="installHelper.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="LICENCE" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="makefile" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="modules" o="root" g="admin" p="16893"><f n="automaton.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="compress.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="cookie.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="error.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="include.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="pool.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="redirect.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="request.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="response.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="session.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spylambda.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="stdout.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="taglib.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="template.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="toc.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="transform.py" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="README" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="RELEASE" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="run_spyceCGI.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="run_spyceCmd.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="run_spyceModpy.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyce.conf" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyce.mime" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyce.nsi" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyce.nsi.in" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyce.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyce.spec.in" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceApache.conf" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceCache.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceCGI.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceCmd.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceCompile.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceConfig.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceException.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceLock.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceModpy.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceModule.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceTag.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceUtil.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceWWW.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="spyceXbmc.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="THANKS" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="tree.py" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="verchk.py" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="scrapers" o="root" g="admin" p="16893"><f n="music" o="root" g="admin" p="16893"><f n="allmusic.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="allmusic.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="video" o="root" g="admin" p="16893"><f n="adultcdmovies.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="adultcdmovies.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="AdultFilmdatabase.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="adultfilmdatabase.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="allocine.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="allocine.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="asiandb.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="asiandb.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="culturalia.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="culturalia.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filmaffinity.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filmaffinity.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filmstarts.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filmstarts.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filmup.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filmup.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filmweb.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="filmweb.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="imdb tv.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="imdb.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="imdb.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="jaded.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="jadedVideo.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="KinoPoisk.gif" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="KinoPoisk.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="movie-xml.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="movie-xml.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="moviemaze.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="moviemaze.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="mtv.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="mtv.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="musicvideos.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ofdb.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ofdb.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="tvcom.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="tvcom.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="tvdb.png" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="tvdb.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="tvrage.jpg" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="tvrage.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="X10-Lola-IRSSmap.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="userdata" o="root" g="admin" p="16893"><f n="LCD.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="ModeLines.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PictureIcon" o="root" g="admin" p="16893"><f n="Picon" o="root" g="admin" p="16893"><f n="tuxbox.png" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="picon.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Readme.txt" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="RssFeeds.xml" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="visualisations" o="root" g="admin" p="16893"><mod>mode</mod></f><mod>mode</mod></f><f n="visualisations" o="root" g="admin" p="16893"><f n="GLspectrum.vis" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="Goom.vis" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="projectM" o="root" g="admin" p="16893"><f n="[Ishan] - Life in the drains.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Agitator.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Aimless (Gravity Directive Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Aimless (Spirogravity Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Airhandler (Menagerie Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Airs (Windy Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Airs.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Anchorpulse (Pulse Of A Ghast II Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Anchorpulse (Verified Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Anomalous Material Science (Pure Splinter Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Antidote (Aqualung Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Antidote (Side Effects Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Antidote.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Antique Abyss.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Arise! (Padded Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Ashes Of Air (Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Bitterfeld (Crystal Border Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Blender.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Bow To Gravity.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Brakefreak.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Candy Avian.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Causeway Of Dreams (Nightmare Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Causeway Of Dreams (REMix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Causeway Of Dreams.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Chromatic Abyss (The Other Side).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Circlefacade.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Contortion (Xenomorph Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Contortion.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Crystal Storm.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Dark Matter (Converse Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Elastoid.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Floater Society.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Flowing Form.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Making Time (Swamp Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Multiviola.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Negative Sun III.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Potion of Spirits.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Songflower (Moss Posy).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - Spillswirl.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - What Cannot Be Undone.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Aderrasi - What cannot be.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="baked - mushroom rainbows[2].milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Bmelgren & Krash - Rainbow Orb Peacock (Centred Journey Mix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Bmelgren & Krash - Rainbow Orb Peacock (Lonely Signal Gone .milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Bmelgren - Godhead.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Bmelgren - Pentultimate Nerual Slipstream (Tweak 2).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Bmelgren - Take This Highway.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CatalystTheElder - Electric Rosebud_Phat_texture_edit.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="che - adela the flower.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="che - burning hus (oil mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Che - Burning Hus.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Che - Escape.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Che - Terracarbon Stream.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Che - Watch & Fly.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="CrystalHigh - mad ravetriping.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="DaNOnE - Highway to Heaven (rotating).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="EMPR - Random - Changing Polyevolution.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="EMPR - Random - Look mama I'm on TV! 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="EMPR - Random - They're so cute Dad can I keep one!.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="EMPR - Random - Turbulence Sandwich.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.s and PieturP - Starfield.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. + Phat - chasers 18 hallway.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - glowsticks v2 03 music.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - glowsticks v2 04 music minimal.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix02b.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix07 recursive demons.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - heater core C_Phat's_class + sparks_mix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - heater core C_Phat's_on route_mix+beam.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - repeater 05 - rave on acid.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - repeater 15 - kaleidoscope b.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S. - skylight a3 [trip colors flux2]_phat_Multi_shaped2_zoe_colours5.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S.+Phat - Arm_upgrades - transformer.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S.+Phat Cool Bug v2 + (Krash's beat detection).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S.+Phat Cool Bug_arm.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S.+Phat Cool Bug_arm_textured.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S.+Phat Fractical_dancer - pulsate B.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S.+Phat Fractical_dancer - pulsate box_mix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Eo.S.+Phat Fractical_dancer_Peacock.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="EvilJim - Follow the ball.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="EvilJim - Ice Drops.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="fiShbRaiN - blueprint.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="fiShbRaiN - brainstem activation.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="fiShbRaiN - crazy diamond.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="fiShbRaiN - cthulhus asshole (bad breakfast remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="fiShbRaiN - cthulhus asshole.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="fiShbRaiN - plasma temptation.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="fiShbRaiN - quark matrix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese & Idiot24-7 - Rearview Mirror.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - 0 To 60.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - A Blur.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - Lifesavor Anyone.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - New meetings.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - Quicksand.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - Round and Round (geiss gamma mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - simple.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - Stand Still!.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - The Tunnel (Final Stage Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - Window Reflection 6.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - Zoom Effects (Remix 2).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - Zoom Effects With A Twist 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Fvese - Zoom Effects With A Twist 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss & Rovastar - Julia Fractal (Vectrip Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss & Rovastar - Notions Of Tonality 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss & Rovastar - The Chaos Of Colours (sprouting dimentia mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss & Rovastar - Tokamak (Naked Intrusion Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss & Sperl - Cruzin' (Moody).prjm" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="Geiss & Sperl - Feedback (projectM idle HDR mix).prjm" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Aieeeeee!!!.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Anomaly 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Anomaly 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Approach.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Asymptote.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bass Kaleidosphere.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bass Zoom.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bipolar 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bipolar 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bipolar 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bipolar 4.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bipolar 5.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Blasto.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bonfire.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bright Fiber Matrix 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Bright Fiber Matrix 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Calligraphy.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Casino.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Cepiasound.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Churn.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Constant Velocity.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Coral.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Corpus Callosum.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Cosmic Dust 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Cosmic Dust 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Cruzin'.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Cycloid 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Cycloid 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Davod The Pod.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - De La Moutard 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - De La Moutard 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Demonic Distortion.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Descent.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Destruction.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Diffraction.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Digital Smoke.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Downward Spiral.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Drift.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Dynamic Swirls 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Dynamic Swirls 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Eddies 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Eddies 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Eggs.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - El Cubismo.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Feedback 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Feedback.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Festive.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Fiberglass.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Flotsam.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Flower Blossom.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Flower.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Four Kinds of Amphetamines.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Galaxy 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Galaxy 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Greenland.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Heavenly 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Heavenly 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Heavenly 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - High Dynamic Range.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Hovering.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Hyperion.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Inkblot.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Iris.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Journey.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Julia Fractal 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Julia Fractal 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Luz.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Mega Swirl 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Mega Swirl 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Mega Swirl 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Microcosm.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Monotone Ripples.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Music Box.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Nautilus.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Octopus Blue.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Octopus Ever Changing.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Octopus Fat and Ever Changing.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Octopus Gold with Dots.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Octopus Gold.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Octopus.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Oldskool Mellowstyle.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Pelota De Fuego.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Pinch.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Pistons.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Planet 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Planet 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Quasilinear Submanifolds.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Reducto Absurdum.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Reducto Ad Nauseum.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Rocket.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Runoff.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Scary.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Script.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Serpent.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Shake.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Shift.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Sinews 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Sinews 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Smoke.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Solar Flare (Blue).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Solar Flare (Reptile).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Solar Flare.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Sound And The Fury.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Space Voyage (High-Warp).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Space Voyage Bright.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Space Voyage.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Spacedust.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Starfish 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Starfish 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Sunsets.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Supernova 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Supernova 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Surface.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Swirl 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Swirl 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Swirlie 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Swirlie 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Swirlie 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Swirlie 4.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Swirlie 5.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Symmetry.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - The Fatty Lumpkin Sunkle Tweaker.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Three And A Half Kinds Of Amphetamines.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Three Kinds Of Amphetamines.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Tokamak.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Tornado.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Toy.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Trampoline.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Tube.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Two-Pointed Pulsagon.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Ultrafast.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Volume Zoom.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Vortex 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Vortex 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Warp Of Dali 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Warp Of Dali 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Warp Of Dali Bright.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss - Waterfall.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss and Rovastar - The Chaos Of Colours (sprouting diment.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Geiss and Rovastar - The Chaos Of Colours (sprouting dimentia mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="headphones.tga" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot & Che - Various Abstract Effects.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot & Rovastar - Altars Of Madness 2 (X.42 Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot & Zylot - Unhealthy Love (Idiot's STDs Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - 9-7-02 (Remix) (sustain fixed).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - Cortex (Spiritual Visions Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - Madness Within The Void (Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - MOTIVATION!.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="idiot - Nothing Yet - 03 - The worst of the pack.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="idiot - Nucleus.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="idiot - Sinful Code (unchained style).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="idiot - Some big word I learned.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="idiot - Spectrum.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - Tentacle Dreams (Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - Texture Boxes (Remix 2).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - Texture Boxes (Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - Typomatic (Remix 2).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - What Is.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot - What Shall Come.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot24-7 - Ascending to heaven 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Idiot24-7 - Meeting place.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion & Che - Return Of The King.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion & Che - The Piper.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion & Rovastar - Clouded Bottle.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion & Rovastar - Snowflake Delight.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion & Rovastar - Snowflake Return.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="illusion & studio music - charged bliss.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion & Unchained - Frozen Eye 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion & Unchained - Invade My Mind.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion & Unchained - Re-Enter Homeworld.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion - Figure Eight.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Illusion - Heavenly Eye.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Jess - Trying To Trap A Twister.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Idiot - Memories Of The Castle.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Illusion - Indecisive Mosaic.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Illusion - Spiral Movement.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Rovastar - A Million Miles from Earth (Ripple Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Rovastar - Altars of Madness (Mad Ocean Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Rovastar - Cerebral Demons (Distant Memory Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Rovastar - Cerebral Demons - Phat + Eo.S. hall of ghouls Remix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Rovastar - Cerebral Demons - Phat + Eo.S. Killer Death Bunny Remix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Rovastar - Switching Polygons.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Rovastar - The Devil Is In The Details.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & TEcHNO - Rhythmic Mantas.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash & Zylot - Inside The Planar Portal (Indecision Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - 3D Shapes Demo 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - 3D Shapes Demo.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - Digital Flame.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - Dynamic Borders 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - Framed Geometry.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - Interwoven (Nightmare Weft Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - Pulse.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - Season's Greetings 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - Twisting Indecision.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - War Machine (Shifting Complexity Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash - Windowframe To Mega Swirl 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash and Fvese - Molten Indecision (Fvese Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash and Rovastar - Rainbow Orb 2 Peacock (Bmelgren's Comp.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Krash and Rovastar - Rainbow Orb.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="M.tga" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Mstress & Darius - Pursuing The Sunset.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Mstress & Juppy - Dancer.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Mstress & Juppy - Dancers In The Dark.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Mstress - Acoustic Nerve Impulses (Under Drug Effetcs (Hypn.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Mstress - Snowing Fiber City.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="nil - Can't Stop the Blithering.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="nil - Can't Stop the Cramming.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="nil - Cid and Lucy.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="nil - Disco Comet.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="nil - Singularity in My Oscilloscope.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="nil - Vortex of Vortices.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Phat+fiShbRaiN+Eo.S_Mandala_Chasers_remix - www.eos4life.com.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Phat+fiShbRaiN+Eo.S_Mandala_Chasers_remix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="phat_CloseIncouneters.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="phat_CloseIncounetersV2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Phat_Eo.S. - our own personal demon.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Phat_Eo.S._Algorithm.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Phat_Eo.S_shoot_em_up.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Phat_Rovastar - What_does_your_soul_look_like.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Phat_Rovastar_Eo.S. spiral_faces.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Phat_Zylot_Eo.S._Krash I_hope_someone_will_see_this_triping_v2b.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PieturP - triptrap_(getting_concrete_visions_through_a_diafragma_version).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="PieturP - triptrap_(ultimate-trip-mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Pithlit & Illusion - Symetric pattern.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="project.tga" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Redi Jedi - acid in your brain.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Redi Jedi - multiple points of origin, one destination.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Reenen - phoenix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Reenen Geiss - Triple Feedback.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Reenen Geiss - Triple Feedback_phat+eos_edit.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rocke - Cold Love (Tei Zwaa).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rocke - Personal Comet.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Aderrasi - Clockwork Organism.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Aderrasi - Oceanic Bassograph (Underwater Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Che - Adela The Flower (Altars Of Madness Mix 2).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Che - Asylum Animations.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Fvese - Dark Subconscious.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Fvese - Deadly Flower.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Fvese - Mosaic Waves.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Fvese - Paranormal Static.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Fvese - Stranger Minds (Astral Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Fvese - Stranger Minds.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Approach (Vectrip Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Bipolar 2 (Vectrip Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Dynamic Swirls 3 (Broken Destiny Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Dynamic Swirls 3 (Mysticial Awakening Mi.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Dynamic Swirls 3 (Poltergiest Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Dynamic Swirls 3 (Smoke Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Dynamic Swirls 3 (Smoking Delusion Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Dynamic Swirls 3 (Twisted Truth Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Dynamic Swirls 3 (Voyage Of Twisted Soul.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Dynamic Swirls 3 (Voyage Of Twisted Souls Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Hurricane Nightmare.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Ice Planet.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Notions Of Tonality.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Octoplasm.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Octotrip (MultiTrip Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Octotrip.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Geiss - Surface (Vectrip Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Idiot24-7 - Balk Acid.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Idiot24-7 - Mixed Emotions (Harlequin's Shame Mi.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Idiot24-7 - Mixed Emotions (Harlequin's Shame Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Illusion - Shifting Sphere.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Krash - Cerebral Demons.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Krash - Flowing Synergy.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Krash - Interwoven (Contra Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Rocke - Answer.42 (Trippy S. Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Rocke - Headspin.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Rocke - Sugar Spun Sister.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Sperl - Tuxflower.prjm" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="Rovastar & StudioMusic - More Cherished Desires.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & StudioMusic - Twisted Spider Web.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Telek - Altars of Madness (Rolling Oceans Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Telek - Cosmic Fireworks.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Unchained - Ambrosia Mystic (Dark Heart Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Unchained - Centre Of Gravity.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Unchained - Demonology (Vampire Soul Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Unchained - Oddball World.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Unchained - Voodoo Chess Magnet (Everglow Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Unchained - Xen Traffic.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Zylot - Azirphaeli's Plan (Multiplan Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Zylot - Crystal Ball (Cerimonial Decor).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Zylot - Narell's Fever.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Zylot - Passion Flower.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar & Zylot - Sea Of Zigrot.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - A Million Miles from Earth (Pathfinder Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - A Million Miles From Earth (Wormhole Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - A Million Miles from Earth.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Harlequin's Maddess.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Harlequin's Madness (Dark Disorder Mix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Madness (A Million Miles From Earth Mi.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Madness (Boxfresh Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Madness (Duel Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Madness (Surealist Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Madness 2 (Frozen Time Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Madness 4 (Spirit Of Twisted Madness M.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Madness 4 (Spirit Of Twisted Madness Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Altars Of Madness.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Attacking Freedom.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Bellanova (New Wave Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Biohazard Warning.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Chapel Of Ghouls.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Chemical Spirituality.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Clouded Judgement 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Cosmic Echoes 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Cosmic Echoes 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Cosmic Havoc.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Cosmic Mosaic (Active Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Dark Ritual (Star Of Destiny Denied Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Dark Ritual (Star Of Destiny Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Decreasing Dreams (Extended Movement Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Decreasing Dreams (Increasing Memory Mix) .milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Dreamcatcher.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Explosive Minds.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Eye On Reality (Mega 3 Mix)_phat_edit.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Forgotten Moon.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Fractopia (Fantic Dancing Lights Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Fractopia (Focused Childhood Mix ).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Fractopia (Fractal Havok Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Fractopia (Galaxy Swirl Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Fractopia (Upspoken Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Fractopia (Upspoken Mix)_Phat_Speak_When_Spoken_2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Frozen Rapture .milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Future Speakers.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Halcyon Dreams 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Hallucinogenic Pyramids (Beat Time Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Delight (Endless Tunnel Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Dynamic Fractal (Crazed Spiral Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Dynamic Fractal (Dual Spiral Mix ).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Dynamic Fractal 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Dynamic Fractal 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Dynamic Fractal 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Fractal Encounter 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Fractal Encounter.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Spirit (Twisted Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Harlequin's Spirit.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Hyperspace (Frozen Rapture Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Hyperspace (Hyper Speed Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Hyperspace.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Inner Thoughts (Clouded Judgement Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Inner Thoughts (Dark Secret Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Inner Thoughts (Distant Memories Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Inner Thoughts (Frantic Thoughts Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Inner Thoughts (Strange Cargo Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Kalideostars (Altars Of Madness MIx).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Kalideostars (Round Round Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Kalideostars.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - LabFunk.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Lost Souls of the Bermuda Triangle (Darkest Soul.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Magic Carpet.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Mosaics Of Ages.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Multiverse Starfield 1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Multiverse Starfield 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Omnipresence Resurrection (Raw Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Omnipresence Resurrection.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Oozing Resistance.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Pandora's Volcano.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Parallel Universe.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Sea Shells.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Snapshot Of Space.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Solarized Space (Space DNA Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Solarized Space.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Space (Twisted Dimension Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Space.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Starquake (Sunquake Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Sunflower Passion (Enlightment Mix)_Phat_edit.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Sunflower Passion (Simple Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Sunflower Passion.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - The Awakening.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - The Chaos Of Colours (Drifting Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - The Chaos Of Colours.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - The Shroomery.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Timeless Voyage.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Torrid Tales.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Touchdown on Mars (Detailed Pictures Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Tripmaker.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - Twilight Tunnel.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - twisted bytes.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - VooV's Movement (After Dark Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar - VooV's Movement.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar and Krash - Hallucinogenic Pyramids (Extra Beat Ti.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar and Unchained - Braindance Visions.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rovastar and Unchained - Life After Pie (Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzer & Neuro - Starover (Semicolon Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzer & Zylot - Force Field Generator (Slowtime Tweak).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor & Aderrasi - Canon.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor & Che - Inside The House Of Nil.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor & Rovastar - Oozing Resistance (Waveform Mod).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor & Shreyas - Deeper Aesthetics.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor & Zylot - Rainbow River.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor - Learning Curve (Invert tweak).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor and che - Inside the House of nil.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor and Idiot - Any Other Deep Rising.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor and Rovastar - Altars Of Madness 3 (ooze tweak with .milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor and Rovastar - Altars Of Madness 3 (ooze tweak).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor and StudioMusic - Vertigyny (Geiss shape mod).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Rozzor and Zylot - Associative Order.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="shifter - escape the worm - Eo.S. + Phat - Before_It_Eats_Your_Brain_Mix_v2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="shifter - escape the worm - Eo.S. + Phat 5362.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="shifter - feathers (angel wings)_phat_remix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="shifter - flashburn.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="shifter - pinwheel.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="shifter - pulsar.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="shifter - snow.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Studio Music - Cherished Desires.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Studio Music and Unchained - Rapid Alteration.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic & Unchained - Entity.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic & Unchained - Minor Alteration.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic & Unchained - Remembering How You Were (Perceived Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic & Unchained - So Much Love.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic & Unchained - State Of Discretion.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic & Unchained - Wrenched Fate.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic - Harmonic Bliss (elated mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic - It's Only Make Believe.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic - Numerosity.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic - Twisted Galaxy.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="StudioMusic Aderrasi & nil - LA movement (Intellectual Sens.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="TEcHNO and SandStorm - Psychodelic Highway.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - City Helix Lattice.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Directive Swagger (Spectral Inferno) (fix...) maybe.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Flicker (@xis).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Flicker.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Lost Star (Flash).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Recirculate (Cool).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Sine Wave.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Slow Shift Matrix (bb4.5).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Slow Shift Matrix (Ethereal Drift).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Slow Shift Matrix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Slow Thing (Spiderman Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Spiral Tabletop (New and Improved!).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Spokes (More Dynamic).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek - Target Practice (tracking retreat slide).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Telek EMPR - Scanner - Trust me I've got a Melways.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="TobiasWolfBoi - Cataract.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="TobiasWolfBoi - The Pit.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Tschoey - Music Flower.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Tux.tga" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Che - Oddnezz 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Che - Oddnezz 4 (Done it again).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & CTho - Bad Vibes.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Illusion - Dual Wave 3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Illusion - Logic Morph.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Illusion - Spirit Morph.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Rovastar - For The Seagull.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Rovastar - Luckless.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Rovastar - Rainbow Obscura.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Rovastar - Slow Solstice.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Rovastar - Triptionary.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Rovastar - Wormhole Pillars (Hall of Shadows mi.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Rovastar - Wormhole Pillars.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained & Rovastar - Xen Traffic.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - A Matter Of Taste (Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - All You Can Eat.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Bad Karma Oddnezz Style.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Beat Demo (Demonology Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Beat Demo 1.0.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Beat Demo 10.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Beat Demo 2.0.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Beat Demo 2.1.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Beat Demo 2.2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Beat Demo 2.3.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Cartoon Factory.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Cranked On Failure.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Custom Gramatix (Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Deeper Logic.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Free to Feel (Valium Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - French Clothing.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Games With Light & Sound.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Ghostlight Whisper.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - God Of The Game (Remix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Goo Kung Fu.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Goofy Beat Detection.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Housed In A Childish Mind.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - In Memory Of Peg.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Invariant Under Rigorous Motions.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Jaded Emotion.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Jaundice.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Making a Science of It 4.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Morat's Final Voyage.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Non-Professional Music Analyzer.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Painful Plasma (Multi-Wave Mirrored Rage) -- Ro.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Painful Plasma (Multi-Wave Mirrored Rage) -- Rozzor triangle tweak.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Perverted Dialect.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Picture Of Exile.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Picture Of Nectar.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Picture Of Poison.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - ReAwoke.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Resistance.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Ribald Ballad.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Shaping The Grid.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Subjective Experience Of The Manifold.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Unclaimed Wreckage 2 (Shamanic).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Unclaimed Wreckage.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Unified Drag 2.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - ventilation.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Unchained - Working the Grid.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot & Aderrasi - Oceanic Bassograph (New Jersey Shore Mix.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot & Idiot - ATan2 Demo (Spiraling Mad Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot & Krash - Extremophile.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot & Mstress - Celebrate.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot & Mstress - Toxic Storm On Acid Sea (The End Of The W.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot & Rovastar - Crystal Ball (Cerimonial Decor Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Azirphaeli's Mirror.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Block Of Sound (Abstract Architecture Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Block Of Sound (Fractal Construction Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Color Of Music.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Crystal Ball (Magical Reaction Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Dark Wisps.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - De(-a)range(d)(ment) complex.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - De(-a)range(d)(ment) strain.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Digiscape Advanced Processor.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Ether Storm.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Global Earthquake.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Inside The Planar Portal.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - light of the path.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Mixing Pot.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Present For Saddam.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Puddle Of Music.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Rainbow Planet Under Attack.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Rush.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - S Pulse Virus.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - String.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Tangent Universe (Collapsed With Artifact Mix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - The Deeper.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - The Inner Workings of my New Computer.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Visionarie (geiss aspect ratio fix).milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Visionarie.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Waves Of Blood.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot - Wisps.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="Zylot and Rovastar - Iouo Stone Morphic Fusion.milk" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="ProjectM.vis" o="root" g="admin" p="33277"><mod>mode</mod></f><f n="Waveform.vis" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="web" o="root" g="admin" p="16893"><mod>mode</mod></f><f n="XBMCHelper" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="xbmc.icns" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f></pkg-contents>
\ No newline at end of file diff --git a/tools/PackageMaker/XBMC Package.pmdoc/01xbmc.xml b/tools/PackageMaker/XBMC Package.pmdoc/01xbmc.xml new file mode 100644 index 0000000000..ac78e281d0 --- /dev/null +++ b/tools/PackageMaker/XBMC Package.pmdoc/01xbmc.xml @@ -0,0 +1 @@ +<pkgref spec="1.12" uuid="DCD4E33E-F7D6-4426-962B-8B6B9C047673"><config><identifier>org.xbmc.xbmcForMac.pkg</identifier><version>2</version><description></description><post-install type="none"/><requireAuthorization/><installFrom relative="true" mod="true" includeRoot="true">../../build/Release/XBMC.app</installFrom><installTo mod="true" relocatable="true">/Applications</installTo><flags><followSymbolicLinks/><allowRevert/><mod>allowRevert</mod></flags><packageStore type="internal"></packageStore><mod>parent</mod><mod>installTo</mod><mod>installTo.path</mod><mod>installTo.isAbsoluteType</mod><mod>installTo.isRelativeType</mod><mod>relocatable</mod><mod>version</mod><mod>includeRoot</mod><mod>installFrom.path</mod><mod>identifier</mod><mod>installFrom.isRelativeType</mod></config><contents><file-list>01xbmc-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
\ No newline at end of file diff --git a/tools/PackageMaker/XBMC Package.pmdoc/02plugins-contents.xml b/tools/PackageMaker/XBMC Package.pmdoc/02plugins-contents.xml new file mode 100644 index 0000000000..f57c1f9cc7 --- /dev/null +++ b/tools/PackageMaker/XBMC Package.pmdoc/02plugins-contents.xml @@ -0,0 +1 @@ +<pkg-contents spec="1.12"><f n="plugins" o="d4rk" g="staff" p="16877" pt="/Users/d4rk/Code/XBMC/XBMC/extras/user/plugins" m="true" t="file"><f n="music" o="d4rk" g="staff" p="16877"><f n="iTunes" o="d4rk" g="staff" p="16877"><f n="default.py" o="d4rk" g="staff" p="33261"/><f n="default.tbn" o="d4rk" g="staff" p="33188"/><f n="itunes_parser.py" o="d4rk" g="staff" p="33261"/><f n="itunes_parser.pyo" o="d4rk" g="staff" p="33188"/><f n="LICENSE" o="d4rk" g="staff" p="33188"/><f n="README" o="d4rk" g="staff" p="33188"/><f n="resources" o="d4rk" g="staff" p="16877"><f n=".DS_Store" o="d4rk" g="staff" p="33188"/><f n="icons" o="d4rk" g="staff" p="16877"><f n=".DS_Store" o="d4rk" g="staff" p="33188"/><f n="albums.png" o="d4rk" g="staff" p="33261"/><f n="artist.png" o="d4rk" g="staff" p="33188"/><f n="genres.png" o="d4rk" g="staff" p="33188"/><f n="import.png" o="d4rk" g="staff" p="33188"/><f n="playlist.png" o="d4rk" g="staff" p="33261"/><f n="star.png" o="d4rk" g="staff" p="33188"/><f n="star1.png" o="d4rk" g="staff" p="33188"/><f n="star2.png" o="d4rk" g="staff" p="33188"/><f n="star3.png" o="d4rk" g="staff" p="33188"/><f n="star4.png" o="d4rk" g="staff" p="33188"/><f n="star5.png" o="d4rk" g="staff" p="33188"/></f><f n="platform_libraries" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="dir-prop-base" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="Linux" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="_imaging.so" o="d4rk" g="staff" p="33188"/><f n="pysqlite2" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33060"/><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="_sqlite.so" o="d4rk" g="staff" p="33188"/><f n="dbapi2.py" o="d4rk" g="staff" p="33188"/></f></f><f n="OS X" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="_imaging.so" o="d4rk" g="staff" p="33188"/><f n="pysqlite2" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33060"/><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="__init__.pyc" o="d4rk" g="staff" p="33188"/><f n="__init__.pyo" o="d4rk" g="staff" p="33188"/><f n="_sqlite.so" o="d4rk" g="staff" p="33188"/><f n="dbapi2.py" o="d4rk" g="staff" p="33188"/><f n="dbapi2.pyc" o="d4rk" g="staff" p="33188"/><f n="dbapi2.pyo" o="d4rk" g="staff" p="33188"/></f></f><f n="win32" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_imaging.pyd.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="_imaging.pyd.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="_imaging.pyd" o="d4rk" g="staff" p="33188"/><f n="pysqlite2" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_sqlite.pyd.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="_sqlite.pyd.svn-base" o="d4rk" g="staff" p="33060"/><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="_sqlite.pyd" o="d4rk" g="staff" p="33188"/><f n="dbapi2.py" o="d4rk" g="staff" p="33188"/></f></f></f></f></f></f><f n="pictures" o="d4rk" g="staff" p="16877"><f n="iPhoto" o="d4rk" g="staff" p="16877"><f n="default.py" o="d4rk" g="staff" p="33261"/><f n="default.tbn" o="d4rk" g="staff" p="33188"/><f n="default_64.png" o="d4rk" g="staff" p="33188"/><f n="iphoto_parser.py" o="d4rk" g="staff" p="33261"/><f n="iphoto_parser.pyo" o="d4rk" g="staff" p="33188"/><f n="LICENSE" o="d4rk" g="staff" p="33188"/><f n="README" o="d4rk" g="staff" p="33188"/><f n="resources" o="d4rk" g="staff" p="16877"><f n=".DS_Store" o="d4rk" g="staff" p="33188"/><f n="icons" o="d4rk" g="staff" p="16877"><f n="albums.png" o="d4rk" g="staff" p="33261"/><f n="star.png" o="d4rk" g="staff" p="33188"/><f n="star1.png" o="d4rk" g="staff" p="33188"/><f n="star2.png" o="d4rk" g="staff" p="33188"/><f n="star3.png" o="d4rk" g="staff" p="33188"/><f n="star4.png" o="d4rk" g="staff" p="33188"/><f n="star5.png" o="d4rk" g="staff" p="33188"/></f><f n="platform_libraries" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="dir-prop-base" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="Linux" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="_imaging.so" o="d4rk" g="staff" p="33188"/><f n="pysqlite2" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33060"/><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="_sqlite.so" o="d4rk" g="staff" p="33188"/><f n="dbapi2.py" o="d4rk" g="staff" p="33188"/></f></f><f n="OS X" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="_imaging.so" o="d4rk" g="staff" p="33188"/><f n="pysqlite2" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33060"/><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="__init__.pyc" o="d4rk" g="staff" p="33188"/><f n="__init__.pyo" o="d4rk" g="staff" p="33188"/><f n="_sqlite.so" o="d4rk" g="staff" p="33188"/><f n="dbapi2.py" o="d4rk" g="staff" p="33188"/><f n="dbapi2.pyc" o="d4rk" g="staff" p="33188"/><f n="dbapi2.pyo" o="d4rk" g="staff" p="33188"/></f></f><f n="win32" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_imaging.pyd.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="_imaging.pyd.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="_imaging.pyd" o="d4rk" g="staff" p="33188"/><f n="pysqlite2" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="_sqlite.pyd.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="_sqlite.pyd.svn-base" o="d4rk" g="staff" p="33060"/><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="_sqlite.pyd" o="d4rk" g="staff" p="33188"/><f n="dbapi2.py" o="d4rk" g="staff" p="33188"/></f></f></f></f></f></f><f n="video" o="d4rk" g="staff" p="16877"><f n="Apple Movie Trailers II" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="default.tbn.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="BUILD.BAT.svn-base" o="d4rk" g="staff" p="33060"/><f n="default.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="default.tbn.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="BUILD.BAT" o="d4rk" g="staff" p="33188"/><f n="default.py" o="d4rk" g="staff" p="33188"/><f n="default.tbn" o="d4rk" g="staff" p="33188"/><f n="resources" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="settings.xml.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="language" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="English" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="strings.xml.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="strings.xml" o="d4rk" g="staff" p="33188"/></f><f n="Finnish" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="strings.xml.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="strings.xml" o="d4rk" g="staff" p="33188"/></f><f n="Swedish" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="strings.xml.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="strings.xml" o="d4rk" g="staff" p="33188"/></f></f><f n="lib" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="xbmcplugin_download.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="xbmcplugin_showtimes.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="xbmcplugin_trailers.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="xbmcplugin_download.py" o="d4rk" g="staff" p="33188"/><f n="xbmcplugin_showtimes.py" o="d4rk" g="staff" p="33188"/><f n="xbmcplugin_trailers.py" o="d4rk" g="staff" p="33188"/></f><f n="scrapers" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="Google" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33060"/><f n="showtimesScraper.py.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="__init__.py" o="d4rk" g="staff" p="33188"/><f n="showtimesScraper.py" o="d4rk" g="staff" p="33188"/></f></f><f n="settings.xml" o="d4rk" g="staff" p="33188"/><f n="skins" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="default" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="media" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"><f n="showtimes-dialog-panel.png.svn-base" o="d4rk" g="staff" p="33060"/><f n="showtimes-input-focus.png.svn-base" o="d4rk" g="staff" p="33060"/><f n="showtimes-input-nofocus.png.svn-base" o="d4rk" g="staff" p="33060"/><f n="showtimes-ticket.png.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="showtimes-dialog-panel.png.svn-base" o="d4rk" g="staff" p="33060"/><f n="showtimes-input-focus.png.svn-base" o="d4rk" g="staff" p="33060"/><f n="showtimes-input-nofocus.png.svn-base" o="d4rk" g="staff" p="33060"/><f n="showtimes-ticket.png.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="showtimes-dialog-panel.png" o="d4rk" g="staff" p="33188"/><f n="showtimes-input-focus.png" o="d4rk" g="staff" p="33188"/><f n="showtimes-input-nofocus.png" o="d4rk" g="staff" p="33188"/><f n="showtimes-ticket.png" o="d4rk" g="staff" p="33188"/></f><f n="PAL" o="d4rk" g="staff" p="16877"><f n=".svn" o="d4rk" g="staff" p="16877"><f n="all-wcprops" o="d4rk" g="staff" p="33060"/><f n="entries" o="d4rk" g="staff" p="33060"/><f n="format" o="d4rk" g="staff" p="33060"/><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"><f n="plugin-AMTII-showtimes.xml.svn-base" o="d4rk" g="staff" p="33060"/></f><f n="tmp" o="d4rk" g="staff" p="16877"><f n="prop-base" o="d4rk" g="staff" p="16877"/><f n="props" o="d4rk" g="staff" p="16877"/><f n="text-base" o="d4rk" g="staff" p="16877"/></f></f><f n="plugin-AMTII-showtimes.xml" o="d4rk" g="staff" p="33188"/></f></f></f></f></f></f></f></pkg-contents>
\ No newline at end of file diff --git a/tools/PackageMaker/XBMC Package.pmdoc/02plugins.xml b/tools/PackageMaker/XBMC Package.pmdoc/02plugins.xml new file mode 100644 index 0000000000..8c659e5783 --- /dev/null +++ b/tools/PackageMaker/XBMC Package.pmdoc/02plugins.xml @@ -0,0 +1 @@ +<pkgref spec="1.12" uuid="362DF32A-AB79-4CD6-99A0-0E9699FCDF22"><config><identifier>org.xbmc.xbmcForMac.plugins.pkg</identifier><version>1</version><description/><post-install type="none"/><installFrom relative="true">../../extras/user/plugins</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>scripts.postinstall.path</mod><mod>requireAuthorization</mod><mod>scripts.postinstall.isRelativeType</mod><mod>scripts.postflight.path</mod><mod>installFrom.isRelativeType</mod><mod>installTo.path</mod><mod>scripts.postflight.isRelativeType</mod><mod>installTo</mod></config><scripts><postflight relative="true" mod="true">post_install_user.pl</postflight></scripts><contents><file-list>02plugins-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
\ No newline at end of file diff --git a/tools/PackageMaker/XBMC Package.pmdoc/02user-contents.xml b/tools/PackageMaker/XBMC Package.pmdoc/02user-contents.xml new file mode 100644 index 0000000000..fa5e01b5f5 --- /dev/null +++ b/tools/PackageMaker/XBMC Package.pmdoc/02user-contents.xml @@ -0,0 +1 @@ +<pkg-contents spec="1.12"><f n="user" o="d4rk" g="staff" p="16877" pt="/Users/d4rk/Code/XBMC/XBMC/extras/user" m="false" t="file"><f n="plugins" o="d4rk" g="staff" p="16893"><f n="music" o="d4rk" g="staff" p="16893"><f n="iTunes" o="d4rk" g="staff" p="16893"><f n="default.py" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="default.tbn" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="itunes_parser.pyo" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="LICENSE" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="README" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="resources" o="d4rk" g="staff" p="16893"><f n=".DS_Store" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="icons" o="d4rk" g="staff" p="16893"><f n=".DS_Store" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="albums.png" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="artist.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="genres.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="import.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="playlist.png" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="star.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star1.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star2.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star3.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star4.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star5.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="platform_libraries" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dir-prop-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="Linux" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="_imaging.so" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="pysqlite2" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.so" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="OS X" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="_imaging.so" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="pysqlite2" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="__init__.pyc" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="__init__.pyo" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.so" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.pyc" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.pyo" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="win32" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_imaging.pyd.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="_imaging.pyd.svn-base" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="_imaging.pyd" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="pysqlite2" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_sqlite.pyd.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.pyd.svn-base" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.pyd" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="dbapi2.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="pictures" o="d4rk" g="staff" p="16893"><f n="iPhoto" o="d4rk" g="staff" p="16893"><f n="default.py" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="default.tbn" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="iphoto_parser.pyo" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="LICENSE" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="README" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="resources" o="d4rk" g="staff" p="16893"><f n=".DS_Store" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="icons" o="d4rk" g="staff" p="16893"><f n="albums.png" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="star.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star1.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star2.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star3.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star4.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="star5.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="platform_libraries" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dir-prop-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="Linux" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="_imaging.so" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="pysqlite2" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.so" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="OS X" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="_imaging.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="_imaging.so" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="pysqlite2" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.so.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="__init__.pyc" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="__init__.pyo" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.so" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.pyc" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="dbapi2.pyo" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="win32" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_imaging.pyd.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="_imaging.pyd.svn-base" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="_imaging.pyd" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="pysqlite2" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="_sqlite.pyd.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.pyd.svn-base" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="dbapi2.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="_sqlite.pyd" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="dbapi2.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="video" o="d4rk" g="staff" p="16893"><f n="Apple Movie Trailers II" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="default.tbn.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="BUILD.BAT.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="default.py.svn-base" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="default.tbn.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="BUILD.BAT" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="default.py" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="default.tbn" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="resources" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="settings.xml.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="language" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="English" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="strings.xml.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="strings.xml" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Finnish" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="strings.xml.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="strings.xml" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="Swedish" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="strings.xml.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="strings.xml" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="lib" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="xbmcplugin_download.py.svn-base" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="xbmcplugin_showtimes.py.svn-base" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="xbmcplugin_trailers.py.svn-base" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="xbmcplugin_download.py" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="xbmcplugin_showtimes.py" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><f n="xbmcplugin_trailers.py" o="d4rk" g="staff" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="scrapers" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="Google" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="__init__.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimesScraper.py.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="__init__.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimesScraper.py" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="settings.xml" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="skins" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="default" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="media" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><f n="showtimes-dialog-panel.png.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-input-focus.png.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-input-nofocus.png.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-ticket.png.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="showtimes-dialog-panel.png.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-input-focus.png.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-input-nofocus.png.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-ticket.png.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="showtimes-dialog-panel.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-input-focus.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-input-nofocus.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="showtimes-ticket.png" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="PAL" o="d4rk" g="staff" p="16893"><f n=".svn" o="d4rk" g="staff" p="16893"><f n="all-wcprops" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="entries" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="format" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><f n="plugin-AMTII-showtimes.xml.svn-base" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="tmp" o="d4rk" g="staff" p="16893"><f n="prop-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="props" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><f n="text-base" o="d4rk" g="staff" p="16893"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="plugin-AMTII-showtimes.xml" o="d4rk" g="staff" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f></f></pkg-contents>
\ No newline at end of file diff --git a/tools/PackageMaker/XBMC Package.pmdoc/02user.xml b/tools/PackageMaker/XBMC Package.pmdoc/02user.xml new file mode 100644 index 0000000000..2107283967 --- /dev/null +++ b/tools/PackageMaker/XBMC Package.pmdoc/02user.xml @@ -0,0 +1 @@ +<pkgref spec="1.12" uuid="362DF32A-AB79-4CD6-99A0-0E9699FCDF22"><config><identifier>org.xbmc.xbmcForMac.user.pkg</identifier><version>1</version><description></description><post-install type="none"/><installFrom relative="true" mod="true">../../extras/user/</installFrom><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>scripts.postinstall.isRelativeType</mod><mod>installTo.isAbsoluteType</mod><mod>installTo.isRelativeType</mod><mod>parent</mod><mod>scripts.postinstall.path</mod><mod>requireAuthorization</mod><mod>scripts.postflight.path</mod><mod>installFrom.isRelativeType</mod><mod>installTo.path</mod><mod>scripts.postflight.isRelativeType</mod><mod>installTo</mod><mod>installFrom.path</mod></config><scripts><postflight relative="true" mod="true">post_install_user.pl</postflight></scripts><contents><file-list>02user-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
\ No newline at end of file diff --git a/tools/PackageMaker/XBMC Package.pmdoc/index.xml b/tools/PackageMaker/XBMC Package.pmdoc/index.xml new file mode 100644 index 0000000000..1104d5fb33 --- /dev/null +++ b/tools/PackageMaker/XBMC Package.pmdoc/index.xml @@ -0,0 +1,659 @@ +<pkmkdoc spec="1.12"><properties><title>XBMC for Mac</title><build>/Users/d4rk/Desktop/XBMC_for_Mac_b1_1.mpkg</build><organization>org.xbmc</organization><userSees ui="easy"/><min-target os="2"/><domain anywhere="true" system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>Atlantis rev 15066 Beta 1</description><contents><choice title="XBMC Media Center" id="choice0" description="Atlantis rev 15066 Alpha 4" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="org.xbmc.xbmcForMac.pkg"/><pkgref id="org.xbmc.xbmcForMac.user.pkg"/></choice></contents><resources bg-scale="proportional" bg-align="left"><locale lang="en"><resource relative="true" mod="true" type="background">setup window.png</resource><resource mime-type="text/rtf" kind="embedded" type="license"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\f0\fs26 \cf0 XBMC Media Center as a whole is distributed under the GNU General Public License 2.0 (with a few libraries used by XBMC licensed under the LGPL).\ +\ + +\fs20 \ + GNU GENERAL PUBLIC LICENSE\ + Version 2, June 1991\ +\ + Copyright (C) 1989, 1991 Free Software Foundation, Inc.\ + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\ + Everyone is permitted to copy and distribute verbatim copies\ + of this license document, but changing it is not allowed.\ +\ + Preamble\ +\ + The licenses for most software are designed to take away your\ +freedom to share and change it. By contrast, the GNU General Public\ +License is intended to guarantee your freedom to share and change free\ +software--to make sure the software is free for all its users. This\ +General Public License applies to most of the Free Software\ +Foundation's software and to any other program whose authors commit to\ +using it. (Some other Free Software Foundation software is covered by\ +the GNU Library General Public License instead.) You can apply it to\ +your programs, too.\ +\ + When we speak of free software, we are referring to freedom, not\ +price. Our General Public Licenses are designed to make sure that you\ +have the freedom to distribute copies of free software (and charge for\ +this service if you wish), that you receive source code or can get it\ +if you want it, that you can change the software or use pieces of it\ +in new free programs; and that you know you can do these things.\ +\ + To protect your rights, we need to make restrictions that forbid\ +anyone to deny you these rights or to ask you to surrender the rights.\ +These restrictions translate to certain responsibilities for you if you\ +distribute copies of the software, or if you modify it.\ +\ + For example, if you distribute copies of such a program, whether\ +gratis or for a fee, you must give the recipients all the rights that\ +you have. You must make sure that they, too, receive or can get the\ +source code. And you must show them these terms so they know their\ +rights.\ +\ + We protect your rights with two steps: (1) copyright the software, and\ +(2) offer you this license which gives you legal permission to copy,\ +distribute and/or modify the software.\ +\ + Also, for each author's protection and ours, we want to make certain\ +that everyone understands that there is no warranty for this free\ +software. If the software is modified by someone else and passed on, we\ +want its recipients to know that what they have is not the original, so\ +that any problems introduced by others will not reflect on the original\ +authors' reputations.\ +\ + Finally, any free program is threatened constantly by software\ +patents. We wish to avoid the danger that redistributors of a free\ +program will individually obtain patent licenses, in effect making the\ +program proprietary. To prevent this, we have made it clear that any\ +patent must be licensed for everyone's free use or not licensed at all.\ +\ + The precise terms and conditions for copying, distribution and\ +modification follow.\ +\ + GNU GENERAL PUBLIC LICENSE\ + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\ +\ + 0. This License applies to any program or other work which contains\ +a notice placed by the copyright holder saying it may be distributed\ +under the terms of this General Public License. The "Program", below,\ +refers to any such program or work, and a "work based on the Program"\ +means either the Program or any derivative work under copyright law:\ +that is to say, a work containing the Program or a portion of it,\ +either verbatim or with modifications and/or translated into another\ +language. (Hereinafter, translation is included without limitation in\ +the term "modification".) Each licensee is addressed as "you".\ +\ +Activities other than copying, distribution and modification are not\ +covered by this License; they are outside its scope. The act of\ +running the Program is not restricted, and the output from the Program\ +is covered only if its contents constitute a work based on the\ +Program (independent of having been made by running the Program).\ +Whether that is true depends on what the Program does.\ +\ + 1. You may copy and distribute verbatim copies of the Program's\ +source code as you receive it, in any medium, provided that you\ +conspicuously and appropriately publish on each copy an appropriate\ +copyright notice and disclaimer of warranty; keep intact all the\ +notices that refer to this License and to the absence of any warranty;\ +and give any other recipients of the Program a copy of this License\ +along with the Program.\ +\ +You may charge a fee for the physical act of transferring a copy, and\ +you may at your option offer warranty protection in exchange for a fee.\ +\ + 2. You may modify your copy or copies of the Program or any portion\ +of it, thus forming a work based on the Program, and copy and\ +distribute such modifications or work under the terms of Section 1\ +above, provided that you also meet all of these conditions:\ +\ + a) You must cause the modified files to carry prominent notices\ + stating that you changed the files and the date of any change.\ +\ + b) You must cause any work that you distribute or publish, that in\ + whole or in part contains or is derived from the Program or any\ + part thereof, to be licensed as a whole at no charge to all third\ + parties under the terms of this License.\ +\ + c) If the modified program normally reads commands interactively\ + when run, you must cause it, when started running for such\ + interactive use in the most ordinary way, to print or display an\ + announcement including an appropriate copyright notice and a\ + notice that there is no warranty (or else, saying that you provide\ + a warranty) and that users may redistribute the program under\ + these conditions, and telling the user how to view a copy of this\ + License. (Exception: if the Program itself is interactive but\ + does not normally print such an announcement, your work based on\ + the Program is not required to print an announcement.)\ +\ +These requirements apply to the modified work as a whole. If\ +identifiable sections of that work are not derived from the Program,\ +and can be reasonably considered independent and separate works in\ +themselves, then this License, and its terms, do not apply to those\ +sections when you distribute them as separate works. But when you\ +distribute the same sections as part of a whole which is a work based\ +on the Program, the distribution of the whole must be on the terms of\ +this License, whose permissions for other licensees extend to the\ +entire whole, and thus to each and every part regardless of who wrote it.\ +\ +Thus, it is not the intent of this section to claim rights or contest\ +your rights to work written entirely by you; rather, the intent is to\ +exercise the right to control the distribution of derivative or\ +collective works based on the Program.\ +\ +In addition, mere aggregation of another work not based on the Program\ +with the Program (or with a work based on the Program) on a volume of\ +a storage or distribution medium does not bring the other work under\ +the scope of this License.\ +\ + 3. You may copy and distribute the Program (or a work based on it,\ +under Section 2) in object code or executable form under the terms of\ +Sections 1 and 2 above provided that you also do one of the following:\ +\ + a) Accompany it with the complete corresponding machine-readable\ + source code, which must be distributed under the terms of Sections\ + 1 and 2 above on a medium customarily used for software\ + interchange; or,\ +\ + b) Accompany it with a written offer, valid for at least three\ + years, to give any third party, for a charge no more than your\ + cost of physically performing source distribution, a complete\ + machine-readable copy of the corresponding source code, to be\ + distributed under the terms of Sections 1 and 2 above on a medium\ + customarily used for software interchange; or,\ +\ + c) Accompany it with the information you received as to the offer\ + to distribute corresponding source code. (This alternative is\ + allowed only for noncommercial distribution and only if you\ + received the program in object code or executable form with such\ + an offer, in accord with Subsection b above.)\ +\ +The source code for a work means the preferred form of the work for\ +making modifications to it. For an executable work, complete source\ +code means all the source code for all modules it contains, plus any\ +associated interface definition files, plus the scripts used to\ +control compilation and installation of the executable. However, as a\ +special exception, the source code distributed need not include\ +anything that is normally distributed (in either source or binary\ +form) with the major components (compiler, kernel, and so on) of the\ +operating system on which the executable runs, unless that component\ +itself accompanies the executable.\ +\ +If distribution of executable or object code is made by offering\ +access to copy from a designated place, then offering equivalent\ +access to copy the source code from the same place counts as\ +distribution of the source code, even though third parties are not\ +compelled to copy the source along with the object code.\ +\ + 4. You may not copy, modify, sublicense, or distribute the Program\ +except as expressly provided under this License. Any attempt\ +otherwise to copy, modify, sublicense or distribute the Program is\ +void, and will automatically terminate your rights under this License.\ +However, parties who have received copies, or rights, from you under\ +this License will not have their licenses terminated so long as such\ +parties remain in full compliance.\ +\ + 5. You are not required to accept this License, since you have not\ +signed it. However, nothing else grants you permission to modify or\ +distribute the Program or its derivative works. These actions are\ +prohibited by law if you do not accept this License. Therefore, by\ +modifying or distributing the Program (or any work based on the\ +Program), you indicate your acceptance of this License to do so, and\ +all its terms and conditions for copying, distributing or modifying\ +the Program or works based on it.\ +\ + 6. Each time you redistribute the Program (or any work based on the\ +Program), the recipient automatically receives a license from the\ +original licensor to copy, distribute or modify the Program subject to\ +these terms and conditions. You may not impose any further\ +restrictions on the recipients' exercise of the rights granted herein.\ +You are not responsible for enforcing compliance by third parties to\ +this License.\ +\ + 7. If, as a consequence of a court judgment or allegation of patent\ +infringement or for any other reason (not limited to patent issues),\ +conditions are imposed on you (whether by court order, agreement or\ +otherwise) that contradict the conditions of this License, they do not\ +excuse you from the conditions of this License. If you cannot\ +distribute so as to satisfy simultaneously your obligations under this\ +License and any other pertinent obligations, then as a consequence you\ +may not distribute the Program at all. For example, if a patent\ +license would not permit royalty-free redistribution of the Program by\ +all those who receive copies directly or indirectly through you, then\ +the only way you could satisfy both it and this License would be to\ +refrain entirely from distribution of the Program.\ +\ +If any portion of this section is held invalid or unenforceable under\ +any particular circumstance, the balance of the section is intended to\ +apply and the section as a whole is intended to apply in other\ +circumstances.\ +\ +It is not the purpose of this section to induce you to infringe any\ +patents or other property right claims or to contest validity of any\ +such claims; this section has the sole purpose of protecting the\ +integrity of the free software distribution system, which is\ +implemented by public license practices. Many people have made\ +generous contributions to the wide range of software distributed\ +through that system in reliance on consistent application of that\ +system; it is up to the author/donor to decide if he or she is willing\ +to distribute software through any other system and a licensee cannot\ +impose that choice.\ +\ +This section is intended to make thoroughly clear what is believed to\ +be a consequence of the rest of this License.\ +\ + 8. If the distribution and/or use of the Program is restricted in\ +certain countries either by patents or by copyrighted interfaces, the\ +original copyright holder who places the Program under this License\ +may add an explicit geographical distribution limitation excluding\ +those countries, so that distribution is permitted only in or among\ +countries not thus excluded. In such case, this License incorporates\ +the limitation as if written in the body of this License.\ +\ + 9. The Free Software Foundation may publish revised and/or new versions\ +of the General Public License from time to time. Such new versions will\ +be similar in spirit to the present version, but may differ in detail to\ +address new problems or concerns.\ +\ +Each version is given a distinguishing version number. If the Program\ +specifies a version number of this License which applies to it and\ +"any later version", you have the option of following the terms and\ +conditions either of that version or of any later version published by\ +the Free Software Foundation. If the Program does not specify a\ +version number of this License, you may choose any version ever\ +published by the Free Software Foundation.\ +\ + 10. If you wish to incorporate parts of the Program into other free\ +programs whose distribution conditions are different, write to the author\ +to ask for permission. For software which is copyrighted by the Free\ +Software Foundation, write to the Free Software Foundation; we sometimes\ +make exceptions for this. Our decision will be guided by the two goals\ +of preserving the free status of all derivatives of our free software and\ +of promoting the sharing and reuse of software generally.\ +\ + NO WARRANTY\ +\ + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO\ +WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\ +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\ +OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY\ +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\ +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\ +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\ +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME\ +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\ +\ + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\ +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\ +AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU\ +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\ +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\ +PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\ +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\ +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF\ +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\ +DAMAGES.\ +\ + END OF TERMS AND CONDITIONS\ +\ + How to Apply These Terms to Your New Programs\ +\ + If you develop a new program, and you want it to be of the greatest\ +possible use to the public, the best way to achieve this is to make it\ +free software which everyone can redistribute and change under these\ +terms.\ +\ + To do so, attach the following notices to the program. It is safest\ +to attach them to the start of each source file to most effectively\ +convey the exclusion of warranty; and each file should have at least\ +the "copyright" line and a pointer to where the full notice is found.\ +\ + <one line to give the program's name and a brief idea of what it does.>\ + Copyright (C) <year> <name of author>\ +\ + 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\ +\ +\ +Also add information on how to contact you by electronic and paper mail.\ +\ +If the program is interactive, make it output a short notice like this\ +when it starts in an interactive mode:\ +\ + Gnomovision version 69, Copyright (C) year name of author\ + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\ + This is free software, and you are welcome to redistribute it\ + under certain conditions; type `show c' for details.\ +\ +The hypothetical commands `show w' and `show c' should show the appropriate\ +parts of the General Public License. Of course, the commands you use may\ +be called something other than `show w' and `show c'; they could even be\ +mouse-clicks or menu items--whatever suits your program.\ +\ +You should also get your employer (if you work as a programmer) or your\ +school, if any, to sign a "copyright disclaimer" for the program, if\ +necessary. Here is a sample; alter the names:\ +\ + Yoyodyne, Inc., hereby disclaims all copyright interest in the program\ + `Gnomovision' (which makes passes at compilers) written by James Hacker.\ +\ + <signature of Ty Coon>, 1 April 1989\ + Ty Coon, President of Vice\ +\ +This General Public License does not permit incorporating your program into\ +proprietary programs. If your program is a subroutine library, you may\ +consider it more useful to permit linking proprietary applications with the\ +library. If this is what you want to do, use the GNU Library General\ +Public License instead of this License.\ + +\fs26 \ +By proceeding to install XBMC you are agreeing to the above license. The XBMC code is copyrighted to Team XBMC. Team XBMC reserves the right to modify this license at any time without notice.}]]></resource><resource mime-type="text/rtf" kind="embedded" type="readme"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red227\green0\blue0;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\f0\fs26 \cf0 You are about to install a +\b \cf2 development release, Atlantis Beta 1, +\b0 \cf0 of XBMC. Note that being a development release, the application might crash occasionally or display unexpected behavior.\ +}]]></resource><resource mime-type="text/rtf" kind="embedded" type="welcome"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\f0\b\fs26 \cf0 XBMC Media Center +\b0 is a free and open source cross-platform media-player and entertainment hub.\ +\ +XBMC supports a wide range of multimedia formats and includes features such as playlists, audio visualizations, slideshows, metadata retrieval, weather reporting, etc. In addition, it also supports an expanding array of third-party Python plugins.\ +\ +Please visit our official website located at {\field{\*\fldinst{HYPERLINK "http://xbmc.org"}}{\fldrslt http://xbmc.org}} for more information. You will also find {\field{\*\fldinst{HYPERLINK "http://xbmc.org/wiki/?title=XBMC_Online_Manual"}}{\fldrslt documentation}} and user support {\field{\*\fldinst{HYPERLINK "http://xbmc.org/forum"}}{\fldrslt forums}} located there.}]]></resource><resource mime-type="text/rtf" kind="embedded" type="conclusion"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\f0\fs26 \cf0 XBMC Media Center was successfully installed!\ +\ +Please visit our forums at {\field{\*\fldinst{HYPERLINK "http://xbmc.org/forum"}}{\fldrslt http://xbmc.org/forum}} if you have any questions or comments. You can also browse our online Documentation at http://xbmc.org/. \ +\ +You can talk to other XBMC users at {\field{\*\fldinst{HYPERLINK "irc://irc.freenode.net"}}{\fldrslt irc://irc.freenode.net}} in the channels #xbmc, #xbmc-osx and #xbmc-linux.\ +\ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b \cf0 Thank you for choosing XBMC Media Center.}]]></resource></locale><locale lang="fr"><resource relative="true" mod="true" type="background">setup window.png</resource><resource mime-type="text/rtf" kind="embedded" type="license"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\f0\fs26 \cf0 XBMC Media Center dans son ensemble est distribu\'e9 sous la licence GNU General Public License 2.0 (avec quelques librairies utilis\'e9es par XBMC sous licence LGPL).\ +\ + +\fs20 GNU GENERAL PUBLIC LICENSE\ +\ +Version 3, du 29 Juin 2007\ +\ +Copyright \'a9 2007 Free Software Foundation, Inc. <http://fsf.org/>\ +\ +Chacun est autoris\'e9 \'e0 copier et distribuer des copies conformes de ce document de licence, mais toute modification en est proscrite.\ +\ +Pr\'e9ambule\ +\ +La Licence Publique G\'e9n\'e9rale GNU (\'93GNU General Public License\'94) est une licence libre, en \'93copyleft\'94, destin\'e9e aux \'9cuvres logicielles et d\'92autres types de travaux.\ +\ +Les licences de la plupart des \'9cuvres logicielles et autres travaux de pratique sont con\'e7ues pour \'f4ter votre libert\'e9 de partager et modifier ces travaux. En contraste, la Licence Publique G\'e9n\'e9rale GNU a pour but de garantir votre libert\'e9 de partager et changer toutes les versions d\'92un programme \'97 afin d\'92assurer qu\'92il restera libre pour tous les utilisateurs. Nous, la Free Software Foundation, utilisons la Licence Publique G\'e9n\'e9rale GNU pour la plupart de nos logiciels ; cela s\'92applique aussi \'e0 tout autre travail \'e9dit\'e9 de cette fa\'e7on par ses auteurs. Vous pouvez, vous aussi, l\'92appliquer \'e0 vos propres programmes.\ +\ +Quand nous parlons de logiciel libre (\'93free\'94), nous nous r\'e9f\'e9rons \'e0 la libert\'e9 (\'93freedom\'94), pas au prix. Nos Licences Publiques G\'e9n\'e9rales sont con\'e7ues pour assurer que vous ayez la libert\'e9 de distribuer des copies de logiciel libre (et le facturer si vous le souhaitez), que vous receviez le code source ou pouviez l\'92obtenir si vous le voulez, que vous pouviez modifier le logiciel ou en utiliser toute partie dans de nouveaux logiciels libres, et que vous sachiez que vous avez le droit de faire tout ceci.\ +\ +Pour prot\'e9ger vos droits, nous avons besoin d\'92emp\'eacher que d\'92autres vous restreignent ces droits ou vous demande de leur abandonner ces droits. En cons\'e9quence, vous avez certaines responsabilit\'e9s si vous distribuez des copies d\'92un tel programme ou si vous le modifiez : les responsabilit\'e9s de respecter la libert\'e9 des autres.\ +\ +Par exemple, si vous distribuez des copies d\'92un tel programme, que ce soit gratuit ou contre un paiement, vous devez accorder aux Destinataires les m\'eames libert\'e9s que vous avez re\'e7ues. Vous devez aussi vous assurer qu\'92eux aussi re\'e7oivent ou peuvent recevoir son code source. Et vous devez leur montrer les termes de cette licence afin qu\'92ils connaissent leurs droits.\ +\ +Les d\'e9veloppeurs qui utilisent la GPL GNU prot\'e8gent vos droits en deux \'e9tapes : (1) ils affirment leur droits d\'92auteur (\'93copyright\'94) sur le logiciel, et (2) vous accordent cette Licence qui vous donne la permission l\'e9gale de le copier, le distribuer et/ou le modifier.\ +\ +Pour la protection des d\'e9veloppeurs et auteurs, la GPL stipule clairement qu\'92il n\'92y a pas de garantie pour ce logiciel libre. Aux fins \'e0 la fois des utilisateurs et auteurs, la GPL requi\'e8re que les versions modifi\'e9es soient marqu\'e9es comme chang\'e9es, afin que leurs probl\'e8mes ne soient pas attribu\'e9s de fa\'e7on erron\'e9e aux auteurs des versions pr\'e9c\'e9dentes.\ +\ +Certains dispositifs sont con\'e7us pour emp\'eacher l\'92acc\'e8s des utilisateurs \'e0 l\'92installation ou l\'92ex\'e9cution de versions modifi\'e9es du logiciel \'e0 l\'92int\'e9rieur de ces dispositifs, alors que les fabricants le peuvent. Ceci est fondamentalement incompatible avec le but de prot\'e9ger la libert\'e9 des utilisateurs de modifier le logiciel. L\'92aspect syst\'e9matique de tels abus se produit dans le secteur des produits destin\'e9s aux utilisateurs individuels, ce qui est pr\'e9cid\'e9ment ce qui est le plus inacceptable. Aussi, nous avons con\'e7u cette version de la GPL pour prohiber cette pratique pour ces produits. Si de tels probl\'e8mes surviennent dans d\'92autres domaines, nous nous tenons pr\'eat \'e0 \'e9tendre cette restriction \'e0 ces domaines dans de futures versions de la GPL, autant qu\'92il sera n\'e9cessaire pour prot\'e9ger la libert\'e9 des utilisateurs.\ +\ +Finalement, chaque programme est constamment menac\'e9 par les brevets logiciels. Les \'c9tats ne devraient pas autoriser de tels brevets \'e0 restreindre le d\'e9veloppement et l\'92utilisation de logiciels libres sur des ordinateurs d\'92usage g\'e9n\'e9ral ; mais dans ceux qui le font, nous voulons sp\'e9cialement \'e9viter le danger que les brevets appliqu\'e9s \'e0 un programme libre puisse le rendre effectivement propri\'e9taire. Pour emp\'eacher ceci, la GPL assure que les brevets ne peuvent \'eatre utilis\'e9s pour rendre le programme non-libre.\ +\ +Les termes pr\'e9cis et conditions concernant la copie, la distribution et la modification suivent.\ +\ +\ +TERMES ET CONDITIONS\ +Article 0. D\'e9finitions.\ +\ +\'ab Cette Licence \'bb se r\'e9f\'e8re \'e0 la version 3 de la \'93GNU General Public License\'94 (le texte original en anglais).\ +\ +\'ab Droit d\'92Auteur \'bb signifie aussi les droits du \'93copyright\'94 ou voisins qui s\'92appliquent \'e0 d\'92autres types de travaux, tels que ceux sur les masques de semi-conducteurs.\ +\ +\'ab Le Programme \'bb se r\'e9f\'e8re \'e0 tout travail qui peut \'eatre sujet au Droit d\'92Auteur (\'93copyright\'94) et dont les droits d\'92utilisation sont conc\'e9d\'e9s en vertu de cette Licence. Chacun des Licenci\'e9s, \'e0 qui cette Licence est conc\'e9d\'e9e, est d\'e9sign\'e9 par \'ab vous. \'bb Les \'ab Licenci\'e9s \'bb et les \'ab Destinataires \'bb peuvent \'eatre des personnes physiques ou morales (individus ou organisations).\ +\ +\'ab Modifier \'bb un travail signifie en obtenir une copie et adapter tout ou partie du travail d\'92une fa\'e7on n\'e9cessitant une autorisation d\'92un titulaire de Droit d\'92Auteur, autre que celle permettant d\'92en produire une copie conforme. Le travail r\'e9sultant est appel\'e9 une \'ab version modifi\'e9e \'bb du pr\'e9c\'e9dent travail, ou un travail \'ab bas\'e9 sur \'bb le pr\'e9c\'e9dent travail.\ +\ +Un \'ab Travail Couvert \'bb signifie soit le Programme non modifi\'e9 soit un travail bas\'e9 sur le Programme.\ +\ +\'ab Propager \'bb un travail signifie faire quoi que ce soit avec lui qui, sans permission, vous rendrait directement ou indirectement responsable d\'92un d\'e9lit de contrefa\'e7on suivant les lois relatives au Droit d\'92Auteur, \'e0 l\'92exception de son ex\'e9cution sur un ordinateur ou de la modification d\'92une copie priv\'e9e. La propagation inclue la copie, la distribution (avec ou sans modification), la mise \'e0 disposition envers le public, et aussi d'autres activit\'e9s dans certains pays.\ +\ +\'ab Acheminer \'bb un travail signifie tout moyen de propagation de celui-ci qui permet \'e0 d\'92autres parties de r\'e9aliser ou recevoir des copies. La simple interaction d\'92un utilisateur \'e0 travers un r\'e9seau informatique, sans transfert effectif d\'92une copie, ne constitue pas un acheminement.\ +\ +Une interface utilisateur interactive affiche des \'ab Notices L\'e9gales Appropri\'e9es \'bb quand elle comprend un dispositif convenable, bien visible et \'e9vident qui (1) affiche une notice appropri\'e9e sur les droits d\'92auteur et (2) informe l\'92utilisateur qu\'92il n\'92y a pas de garantie pour le travail (sauf si des garanties ont \'e9t\'e9 fournies hors du cadre de cette Licence), que les licenci\'e9s peuvent acheminer le travail sous cette Licence, et comment voir une copie de cette Licence. Si l\'92interface pr\'e9sente une liste de commandes utilisateur ou d\'92options, tel qu\'92un menu, un \'e9l\'e9ment \'e9vident dans la liste pr\'e9sent\'e9e remplit ce crit\'e8re.\ +Article 1. Code source.\ +\ +Le \'ab code source \'bb d\'92un travail signifie la forme pr\'e9f\'e9r\'e9e du travail permettant ou facilitant les modifications de celui-ci. Le \'ab code objet \'bb d\'92un travail signifie toute forme du travail qui n\'92en est pas le code source.\ +\ +Une \'ab Interface Standard \'bb signifie une interface qui est soit celle d\'92une norme officielle d\'e9finie par un organisme de normalisation reconnu ou, dans le cas des interfaces sp\'e9cifi\'e9es pour un langage de programmation particulier, une interface largement utilis\'e9e parmi les d\'e9veloppeurs travaillant dans ce langage.\ +\ +Les \'ab Biblioth\'e8ques Syst\'e8me \'bb d\'92un travail ex\'e9cutable incluent tout ce qui, en dehors du travail dans son ensemble, (a) est inclus dans la forme usuelle de paquetage d\'92un Composant Majeur mais ne fait pas partie de ce Composant Majeur et (b) sert seulement \'e0 permettre l\'92utilisation du travail avec ce Composant Majeur ou \'e0 impl\'e9menter une Interface Standard pour laquelle une impl\'e9mentation est disponible au public sous forme de code source ; un \'ab Composant Majeur \'bb signifie, dans ce contexte, un composant majeur essentiel (noyau, syst\'e8me de fen\'eatrage, etc.) du syst\'e8me d\'92exploitation (le cas \'e9ch\'e9ant) d\'92un syst\'e8me sur lequel le travail ex\'e9cutable fonctionne, ou bien un compilateur utilis\'e9 pour produire le code objet du travail, ou un interpr\'e8te de code objet utilis\'e9 pour ex\'e9cuter celui-ci.\ +\ +Le \'ab Source Correspondant \'bb d\'92un travail sous forme de code objet signifie l\'92ensemble des codes sources n\'e9cessaires pour g\'e9n\'e9rer, installer et (dans le cas d\'92un travail ex\'e9cutable) ex\'e9cuter le code objet et modifier le travail, y compris les scripts pour contr\'f4ler ces activit\'e9s. Cependant, cela n\'92inclue pas les Biblioth\'e8ques Syst\'e8me du travail, ni les outils d\'92usage g\'e9n\'e9ral ou les programmes libres g\'e9n\'e9ralement disponibles qui peuvent \'eatre utilis\'e9s sans modification pour achever ces activit\'e9s mais ne sont pas partie de ce travail. Par exemple le Source Correspondant inclut les fichiers de d\'e9finition d\'92interfaces associ\'e9s aux fichiers sources du travail, et le code source des biblioth\'e8ques partag\'e9es et des sous-routines li\'e9es dynamiquement, pour lesquelles le travail est sp\'e9cifiquement con\'e7u pour les requ\'e9rir via, par exemple, des communications de donn\'e9es ou contr\'f4les de flux internes entre ces sous-programmes et d\'92autres parties du travail.\ +\ +Le Source Correspondant n\'92a pas besoin d\'92inclure tout ce que les utilisateurs peuvent reg\'e9n\'e9rer automatiquement \'e0 partir d\'92autres parties du Source Correspondant.\ +\ +Le Source Correspondant pour un travail sous forme de code source est ce m\'eame travail.\ +Article 2. Permissions de base.\ +\ +Tous les droits accord\'e9s suivant cette Licence le sont jusqu\'92au terme des Droits d\'92Auteur (\'93copyright\'94) sur le Programme, et sont irr\'e9vocables pourvu que les conditions \'e9tablies soient remplies. Cette Licence affirme explicitement votre permission illimit\'e9e d\'92ex\'e9cuter le Programme non modifi\'e9. La sortie produite par l\'92ex\'e9cution d\'92un Travail Couvert n\'92est couverte par cette Licence que si cette sortie, \'e9tant donn\'e9 leur contenu, constitue un Travail Couvert. Cette Licence reconnait vos propres droits d\'92usage raisonnable (\'93fair use\'94 en l\'e9gislation des \'c9tats-Unis d\'92Am\'e9rique) ou autres \'e9quivalents, tels qu\'92ils sont pourvus par la loi applicable sur le Droit d\'92Auteur (\'93copyright\'94).\ +\ +Vous pouvez cr\'e9er, ex\'e9cuter et propager sans condition des Travaux Couverts que vous n\'92acheminez pas, aussi longtemps que votre licence demeure en vigueur. Vous pouvez acheminer des Travaux Couverts \'e0 d\'92autres personnes dans le seul but de leur faire r\'e9aliser des modifications \'e0 votre usage exclusif, ou pour qu\'92ils vous fournissent des facilit\'e9s vous permettant d\'92ex\'e9cuter ces travaux, pourvu que vous vous conformiez aux termes de cette Licence lors de l\'92acheminement de tout mat\'e9riel dont vous ne contr\'f4lez pas le Droit d\'92Auteur (\'93copyright\'94). Ceux qui, d\'e8s lors, r\'e9alisent ou ex\'e9cutent pour vous les Travaux Couverts ne doivent alors le faire qu\'92exclusivement pour votre propre compte, sous votre direction et votre contr\'f4le, suivant des termes qui leur interdisent de r\'e9aliser, en dehors de leurs relations avec vous, toute copie de votre mat\'e9riel soumis au Droit d\'92Auteur.\ +\ +L\'92acheminement dans toutes les autres circonstances n\'92est permis que selon les conditions \'e9tablies ci-dessous. La concession de sous-licences n\'92est pas autoris\'e9 ; l\'92article 10 rend cet usage non n\'e9cessaire.\ +Article 3. Protection des droits l\'e9gaux des utilisateurs envers les lois anti-contournement.\ +\ +Aucun Travail Couvert ne doit \'eatre vu comme faisant partie d\'92une mesure technologique effective selon toute loi applicable remplissant les obligations pr\'e9vues \'e0 l\'92article 11 du trait\'e9 international sur le droit d\'92auteur adopt\'e9 \'e0 l\'92OMPI le 20 d\'e9cembre 1996, ou toutes lois similaires qui prohibent ou restreignent le contournement de telles mesures.\ +\ +Si vous acheminez un Travail Couvert, vous renoncez \'e0 tout pouvoir l\'e9gal d\'92interdire le contournement des mesures technologiques dans tous les cas o\'f9 un tel contournement serait effectu\'e9 en exer\'e7ant les droits pr\'e9vus dans cette Licence pour ce Travail Couvert, et vous d\'e9clarez rejeter toute intention de limiter l\'92op\'e9ration ou la modification du Travail, en tant que moyens de renforcer, \'e0 l\'92encontre des utilisateurs de ce Travail, vos droits l\'e9gaux ou ceux de tierces parties d\'92interdire le contournement des mesures technologiques.\ +Article 4. Acheminement des copies conformes.\ +\ +Vous pouvez acheminer des copies conformes du code source du Programme tel que vous l\'92avez re\'e7u, sur n\'92importe quel support, pourvu que vous publiiez scrupuleusement et de fa\'e7on appropri\'e9e sur chaque copie une notice de Droit d\'92Auteur appropri\'e9e ; gardez intactes toutes les notices \'e9tablissant que cette Licence et tous les termes additionnels non permissifs ajout\'e9s en accord avec l\'92article 7 s\'92appliquent \'e0 ce code ; et donnez \'e0 chacun des Destinataires une copie de cette Licence en m\'eame temps que le Programme.\ +\ +Vous pouvez facturer un prix quelconque, y compris gratuit, pour chacune des copies que vous acheminez, et vous pouvez offrir une protection additionnelle de support ou de garantie en \'e9change d\'92un paiement.\ +Article 5. Acheminement des versions sources modifi\'e9es.\ +\ +Vous pouvez acheminer un travail bas\'e9 sur le Programme, ou bien les modifications pour le produire \'e0 partir du Programme, sous la forme de code source suivant les termes de l\'92article 4, pourvu que vous satisfassiez aussi \'e0 chacune des conditions requises suivantes :\ +\ + * a) Le travail doit comporter des notices \'e9videntes \'e9tablissant que vous l\'92avez modifi\'e9 et donnant la date correspondante.\ + * b) Le travail doit comporter des notices \'e9videntes \'e9tablissant qu\'92il est \'e9dit\'e9 selon cette Licence et les conditions ajout\'e9es d\'92apr\'e8s l\'92article 7. Cette obligation vient modifier l\'92obligation de l\'92article 4 de \'ab garder intactes toutes les notices. \'bb\ + * c) Vous devez licencier le travail entier, comme un tout, suivant cette Licence \'e0 quiconque entre en possession d\'92une copie. Cette Licence s\'92appliquera en cons\'e9quence, avec les termes additionnels applicables pr\'e9vus par l\'92article 7, \'e0 la totalit\'e9 du travail et chacune de ses parties, ind\'e9pendamment de la fa\'e7on dont ils sont empaquet\'e9s. Cette licence ne donne aucune permission de licencier le travail d\'92une autre fa\'e7on, mais elle n\'92invalide pas une telle permission si vous l\'92avez re\'e7ue s\'e9par\'e9ment.\ + * d) Si le travail a des interfaces utilisateurs interactives, chacune doit afficher les Notices L\'e9gales Appropri\'e9es ; cependant si le Programme a des interfaces qui n\'92affichent pas les Notices L\'e9gales Appropri\'e9es, votre travail n\'92a pas \'e0 les modifier pour qu\'92elles les affichent.\ +\ +Une compilation d\'92un Travail Couvert avec d\'92autres travaux s\'e9par\'e9s et ind\'e9pendants, qui ne sont pas par leur nature des extensions du Travail Couvert, et qui ne sont pas combin\'e9s avec lui de fa\'e7on \'e0 former un programme plus large, dans ou sur un volume de stockage ou un support de distribution, est appel\'e9 un \'ab aggr\'e9gat \'bb si la compilation et son Droit d\'92Auteur r\'e9sultant ne sont pas utilis\'e9s pour limiter l\'92acc\'e8s ou les droits l\'e9gaux des utilisateurs de la compilation en de\'e7a de ce que permettent les travaux individuels. L\'92inclusion d\'92un Travail Couvert dans un aggr\'e9gat ne cause pas l\'92application de cette Licence aux autres parties de l\'92aggr\'e9gat.\ +Article 6. Acheminement des formes non sources.\ +\ +Vous pouvez acheminer sous forme de code objet un Travail Couvert suivant les termes des articles 4 et 5, pourvu que vous acheminiez \'e9galement suivant les termes de cette Licence le Source Correspondant lisible par une machine, d\'92une des fa\'e7ons suivantes :\ +\ + * a) Acheminer le code objet sur, ou inclus dans, un produit physique (y compris un support de distribution physique), accompagn\'e9 par le Source Correspondant fix\'e9 sur un support physique durable habituellement utilis\'e9 pour les \'e9changes de logiciels.\ + * b) Acheminer le code objet sur, ou inclus dans, un produit physique (y compris un support de distribution physique), accompagn\'e9 d\'92une offre \'e9crite, valide pour au moins trois ann\'e9es et valide pour aussi longtemps que vous fournissez des pi\'e8ces de rechange ou un support client pour ce mod\'e8le de produit, afin de donner \'e0 quiconque poss\'e8de le code objet soit (1) une copie du Source Correspondant \'e0 tout logiciel dans ce produit qui est couvert par cette Licence, sur un support physique durable habituellement utilis\'e9 pour les \'e9changes de logiciels, pour un prix non sup\'e9rieur au co\'fbt raisonnable de la r\'e9alisation physique de l\'92acheminement de la source, ou soit (2) un acc\'e8s permettant de copier le Source Correspondant depuis un serveur r\'e9seau sans frais.\ + * c) Acheminer des copies individuelles du code objet avec une copie de l\'92offre \'e9crite de fournir le Source Correspondant. Cette alternative est permise seulement occasionellement et non-commercialement, et seulement si vous avez re\'e7u le code objet avec une telle offre, en accord avec l\'92article 6 alin\'e9a b.\ + * d) Acheminer le code objet en offrant un acc\'e8s depuis un emplacement d\'e9sign\'e9 (gratuit ou contre facturation) et offrir un acc\'e8s \'e9quivalent au Source Correspondant de la m\'eame fa\'e7on via le m\'eame emplacement et sans facturation suppl\'e9mentaire. Vous n\'92avez pas besoin d\'92obliger les Destinataires \'e0 copier le Source Correspondant en m\'eame temps que le code objet. Si l\'92emplacement pour copier le code objet est un serveur r\'e9seau, le Source Correspondant peut \'eatre sur un serveur diff\'e9rent (op\'e9r\'e9 par vous ou par un tiers) qui supporte des facilit\'e9s \'e9quivalentes de copie, pourvu que vous mainteniez des directions claires \'e0 proximit\'e9 du code objet indiquant o\'f9 trouver le Source Correspondant. Ind\'e9pendamment de quel serveur h\'e9berge le Source Correspondant, vous restez oblig\'e9 de vous assurer qu\'92il reste disponible aussi longtemps que n\'e9cessaire pour satisfaire \'e0 ces obligations.\ + * e) Acheminer le code objet en utilisant une transmission d\'92\'e9gal-\'e0-\'e9gal, pourvu que vous informiez les autres participants sur o\'f9 le code objet et le Source Correspondant du travail sont offerts sans frais au public g\'e9n\'e9ral suivant l\'92article 6 alin\'e9a d.\ +\ +Une portion s\'e9parable du code objet, dont le code source est exclu du Source Correspondant en tant que Biblioth\'e8que Syst\'e8me, n\'92a pas besoin d\'92\'eatre inclu dans l\'92acheminement du travail sous forme de code objet.\ +\ +Un \'ab Produit Utilisateur \'bb est soit (1) un \'ab Produit de Consommation, \'bb ce qui signifie toute propri\'e9t\'e9 personnelle tangible normalement utilis\'e9e \'e0 des fins personnelles, familiales ou relatives au foyer, soit (2) toute chose con\'e7ue ou vendue pour l\'92incorporation dans un lieu d\'92habitation. Pour d\'e9terminer si un produit constitue un Produit de Consommation, les cas ambigus sont r\'e9solus en fonction de la couverture. Pour un produit particulier re\'e7u par un utilisateur particulier, l\'92expression \'ab normalement utilis\'e9e \'bb ci-avant se r\'e9f\'e8re \'e0 une utilisation typique ou l\'92usage commun de produits de m\'eame cat\'e9gorie, ind\'e9pendamment du statut de cet utilisateur particulier ou de la fa\'e7on sp\'e9cifique dont cet utilisateur particulier utilise effectivement ou s\'92attend lui-m\'eame ou est attendu \'e0 utiliser ce produit. Un produit est un Produit de Consommation ind\'e9pendamment du fait que ce produit a ou n\'92a pas d\'92utilisations substantielles commerciales, industrielles ou hors Consommation, \'e0 moins que de telles utilisations repr\'e9sentent le seul mode significatif d\'92utilisation du produit.\ +\ +Les \'ab Informations d\'92Installation \'bb d\'92un Produit Utilisateur signifient toutes les m\'e9thodes, proc\'e9dures, cl\'e9s d\'92autorisation ou autres informations requises pour installer et ex\'e9cuter des versions modifi\'e9es d\'92un Travail Couvert dans ce Produit Utilisateur \'e0 partir d\'92une version modifi\'e9e de son Source Correspondant. Les informations qui suffisent \'e0 assurer la continuit\'e9 de fonctionnement du code objet modifi\'e9 ne doivent en aucun cas \'eatre emp\'each\'e9es ou interf\'e9r\'e9es du seul fait qu\'92une modification a \'e9t\'e9 effectu\'e9e.\ +\ +Si vous acheminez le code objet d\'92un Travail Couvert dans, ou avec, ou sp\'e9cifiquement pour l\'92utilisation dans, un Produit Utilisateur et l\'92acheminement se produit en tant qu\'92\'e9l\'e9ment d\'92une transaction dans laquelle le droit de possession et d\'92utilisation du Produit Utilisateur est transf\'e9r\'e9 au Destinataire d\'e9finitivement ou pour un terme fix\'e9 (ind\'e9pendamment de la fa\'e7on dont la transaction est caract\'e9ris\'e9e), le Source Correspondant achemin\'e9 selon cet article-ci doit \'eatre accompagn\'e9 des Informations d\'92Installation. Mais cette obligation ne s\'92applique pas si ni vous ni aucune tierce partie ne d\'e9tient la possibilit\'e9 d\'92intaller un code objet modifi\'e9 sur le Produit Utilisateur (par exemple, le travail a \'e9t\'e9 install\'e9 en m\'e9moire morte).\ +\ +L\'92obligation de fournir les Informations d\'92Installation n\'92inclue pas celle de continuer \'e0 fournir un service de support, une garantie ou des mises \'e0 jour pour un travail qui a \'e9t\'e9 modifi\'e9 ou install\'e9 par le Destinataire, ou pour le Produit Utilisateur dans lequel il a \'e9t\'e9 modifi\'e9 ou install\'e9. L\'92acc\'e8s \'e0 un r\'e9seau peut \'eatre rejet\'e9 quand la modification elle-m\'eame affecte mat\'e9riellement et d\'e9favorablement les op\'e9rations du r\'e9seau ou viole les r\'e8gles et protocoles de communication au travers du r\'e9seau.\ +\ +Le Source Correspondant achemin\'e9 et les Informations d\'92Installation fournies, en accord avec cet article, doivent \'eatre dans un format publiquement document\'e9 (et dont une impl\'e9mentation est disponible aupr\'e8s du public sous forme de code source) et ne doit n\'e9cessiter aucune cl\'e9 ou mot de passe sp\'e9cial pour le d\'e9paquetage, la lecture ou la copie.\ +Article 7. Termes additionnels.\ +\ +Les \'ab permissions additionelles \'bb d\'e9signent les termes qui suppl\'e9mentent ceux de cette Licence en \'e9mettant des exceptions \'e0 l\'92une ou plusieurs de ses conditions. Les permissions additionnelles qui sont applicables au Programme entier doivent \'eatre trait\'e9es comme si elles \'e9taient incluent dans cette Licence, dans les limites de leur validit\'e9 suivant la loi applicable. Si des permissions additionnelles s\'92appliquent seulement \'e0 une partie du Programme, cette partie peut \'eatre utilis\'e9e s\'e9par\'e9ment suivant ces permissions, mais le Programme tout entier reste gouvern\'e9 par cette Licence sans regard aux permissions additionelles.\ +\ +Quand vous acheminez une copie d\'92un Travail Couvert, vous pouvez \'e0 votre convenance \'f4ter toute permission additionelle de cette copie, ou de n\'92importe quelle partie de celui-ci. (Des permissions additionnelles peuvent \'eatre r\'e9dig\'e9es de fa\'e7on \'e0 requ\'e9rir leur propre suppression dans certains cas o\'f9 vous modifiez le travail.) Vous pouvez placer les permissions additionnelles sur le mat\'e9riel achemin\'e9, ajout\'e9es par vous \'e0 un Travail Couvert pour lequel vous avez ou pouvez donner les permissions de Droit d\'92Auteur (\'93copyright\'94) appropri\'e9es.\ +\ +Nonobstant toute autre clause de cette Licence, pour tout constituant que vous ajoutez \'e0 un Travail Couvert, vous pouvez (si autoris\'e9 par les titulaires de Droit d\'92Auteur pour ce constituant) suppl\'e9menter les termes de cette Licence avec des termes :\ +\ + * a) qui rejettent la garantie ou limitent la responsabilit\'e9 de fa\'e7on diff\'e9rente des termes des articles 15 et 16 de cette Licence ; ou\ + * b) qui requi\'e8rent la pr\'e9servation de notices l\'e9gales raisonnables sp\'e9cifi\'e9es ou les attributions d\'92auteur dans ce constituant ou dans les Notices L\'e9gales Appropri\'e9es affich\'e9es par les travaux qui le contiennent ; ou\ + * c) qui prohibent la repr\'e9sentation incorrecte de l\'92origine de ce constituant, ou qui requi\'e8rent que les versions modifi\'e9es d\'92un tel constituant soit marqu\'e9es par des moyens raisonnables comme diff\'e9rentes de la version originale ; ou\ + * d) qui limitent l\'92usage \'e0 but publicitaire des noms des conc\'e9dants de licence et des auteurs du constituant ; ou\ + * e) qui refusent \'e0 accorder des droits selon la l\'e9gislation relative aux marques commerciales, pour l\'92utilisation dans des noms commerciaux, marques commerciales ou marques de services ; ou\ + * f) qui requi\'e8rent l\'92indemnisation des conc\'e9dants de licences et auteurs du constituant par quiconque achemine ce constituant (ou des versions modifi\'e9es de celui-ci) en assumant contractuellement la responsabilit\'e9 envers le Destinataire, pour toute responsabilit\'e9 que ces engagements contractuels imposent directement \'e0 ces octroyants de licences et auteurs.\ +\ +Tous les autres termes additionnels non permissifs sont consid\'e9r\'e9s comme des \'ab restrictions avanc\'e9es \'bb dans le sens de l\'92article 10. Si le Programme tel que vous l\'92avez re\'e7u, ou toute partie de celui-ci, contient une notice \'e9tablissant qu\'92il est gouvern\'e9 par cette Licence en m\'eame temps qu\'92un terme qui est une restriction avanc\'e9e, vous pouvez \'f4ter ce terme. Si un document de licence contient une restriction avanc\'e9e mais permet la reconcession de licence ou l\'92acheminement suivant cette Licence, vous pouvez ajouter un Travail Couvert constituant gouvern\'e9 par les termes de ce document de licence, pourvu que la restriction avanc\'e9e ne survit pas \'e0 un telle cession de licence ou acheminement.\ +\ +Si vous ajoutez des termes \'e0 un Travail Couvert en accord avec cet article, vous devez placer, dans les fichiers sources appropri\'e9s, une d\'e9claration des termes additionnels qui s\'92appliquent \'e0 ces fichiers, ou une notice indiquant o\'f9 trouver les termes applicables.\ +\ +Les termes additionnels, qu\'92ils soient permissifs ou non permissifs, peuvent \'eatre \'e9tablis sous la forme d\'92une licence \'e9crite s\'e9par\'e9ment, ou \'e9tablis comme des exceptions ; les obligations ci-dessus s\'92appliquent dans chacun de ces cas.\ +Article 8. Terminaison.\ +\ +Vous ne pouvez ni propager ni modifier un Travail Couvert autrement que suivant les termes de cette Licence. Toute autre tentative de le propager ou le modifier est nulle et terminera automatiquement vos droits selon cette Licence (y compris toute licence de brevet accord\'e9e selon le troisi\'e8me paragraphe de l\'92article 11).\ +\ +Cependant, si vous cessez toute violation de cette Licence, alors votre licence depuis un titulaire de Droit d\'92Auteur (\'93copyright\'94) est r\'e9instaur\'e9e (a) \'e0 titre provisoire \'e0 moins que et jusqu\'92\'e0 ce que le titulaire de Droit d\'92Auteur termine finalement et explicitement votre licence, et (b) de fa\'e7on permanente si le titulaire de Droit d\'92Auteur ne parvient pas \'e0 vous notifier de la violation par quelque moyen raisonnable dans les soixante (60) jours apr\'e8s la cessation.\ +\ +De plus, votre licence depuis un titulaire particulier de Droit d\'92Auteur est r\'e9instaur\'e9e de fa\'e7on permanente si ce titulaire vous notifie de la violation par quelque moyen raisonnable, c\'92est la premi\'e8re fois que vous avez re\'e7u une notification deviolation de cette Licence (pour un travail quelconque) depuis ce titulaire de Droit d\'92Auteur, et vous r\'e9solvez la violation dans les trente (30) jours qui suivent votre r\'e9ception de la notification.\ +\ +La terminaison de vos droits suivant cette section ne terminera pas les licences des parties qui ont re\'e7u des copies ou droits de votre part suivant cette Licence. Si vos droits ont \'e9t\'e9 termin\'e9s et non r\'e9instaur\'e9s de fa\'e7on permanente, vous n\'92\'eates plus qualifi\'e9 \'e0 recevoir de nouvelles licences pour les m\'eames constituants selon l\'92article 10.\ +Article 9. Acceptation non requise pour obtenir des copies.\ +\ +Vous n\'92\'eates pas oblig\'e9 d\'92accepter cette licence afin de recevoir ou ex\'e9cuter une copie du Programme. La propagation asservie d\'92un Travail Couvert qui se produit simplement en cons\'e9quence d\'92une transmission d\'92\'e9gal-\'e0-\'e9gal pour recevoir une copie ne n\'e9cessite pas l\'92acceptation. Cependant, rien d\'92autre que cette Licence ne vous accorde la permission de propager ou modifier un quelconque Travail Couvert. Ces actions enfreignent le Droit d\'92Auteur si vous n\'92acceptez pas cette Licence. Par cons\'e9quent, en modifiant ou propageant un Travail Couvert, vous indiquez votre acceptation de cette Licence pour agir ainsi.\ +Article 10. Cession automatique de Licence aux Destinataires et interm\'e9diaires.\ +\ +Chaque fois que vous acheminez un Travail Couvert, le Destinataire re\'e7oit automatiquement une licence depuis les conc\'e9dants originaux, pour ex\'e9cuter, modifier et propager ce travail, suivant les termes de cette Licence. Vous n\'92\'eates pas responsable du renforcement de la conformation des tierces parties avec cette Licence.\ +\ +Une \'ab transaction d\'92entit\'e9 \'bb d\'e9signe une transaction qui transf\'e8re le contr\'f4le d\'92une organisation, ou de substantiellement tous ses actifs, ou la subdivision d\'92une organisation, ou la fusion de plusieurs organisations. Si la propagation d\'92un Travail Couvert r\'e9sulte d\'92une transaction d\'92entit\'e9, chaque partie \'e0 cette transaction qui re\'e7oit une copie du travail re\'e7oit aussi les licences pour le travail que le pr\'e9d\'e9cesseur int\'e9ress\'e9 \'e0 cette partie avait ou pourrait donner selon le paragraphe pr\'e9c\'e9dent, plus un droit de possession du Source Correspondant de ce travail depuis le pr\'e9d\'e9cesseur int\'e9ress\'e9 si ce pr\'e9d\'e9cesseur en dispose ou peut l\'92obtenir par des efforts raisonnables.\ +\ +Vous ne pouvez imposer aucune restriction avanc\'e9e dans l\'92exercice des droits accord\'e9s ou affirm\'e9s selon cette Licence. Par exemple, vous ne pouvez imposer aucun paiement pour la licence, aucune royaltie, ni aucune autre charge pour l\'92exercice des droits accord\'e9s selon cette Licence ; et vous ne pouvez amorcer aucun litige judiciaire (y compris une r\'e9clamation crois\'e9e ou contre-r\'e9clamation dans un proc\'e8s) sur l\'92all\'e9gation qu\'92une revendication de brevet est enfreinte par la r\'e9alisation, l\'92utilisation, la vente, l\'92offre de vente, ou l\'92importation du Programme ou d\'92une quelconque portion de celui-ci.\ +Article 11. Brevets.\ +\ +Un \'ab contributeur \'bb est un titulaire de Droit d\'92Auteur (\'93copyright\'94) qui autorise l\'92utilisation selon cette Licence du Programme ou du travail sur lequel le Programme est bas\'e9. Le travail ainsi soumis \'e0 licence est appel\'e9 la \'ab version contributive \'bb de ce contributeur.\ +\ +Les \'ab revendications de brevet essentielles \'bb sont toutes les revendications de brevets d\'e9tenues ou contr\'f4l\'e9es par le contributeur, qu\'92elles soient d\'e9j\'e0 acquises par lui ou acquises subs\'e9quemment, qui pourraient \'eatre enfreintes de quelque mani\'e8re, permises par cette Licence, sur la r\'e9alisation, l\'92utilisation ou la vente de la version contributive de celui-ci. Aux fins de cette d\'e9finition, le \'ab contr\'f4le \'bb inclue le droit de conc\'e9der des sous-licences de brevets d\'92une mani\'e8re consistante, n\'e9cessaire et suffisante, avec les obligations de cette Licence.\ +\ +Chaque contributeur vous accorde une licence de brevet non exclusive, mondiale et libre de toute royaltie, selon les revendications de brevet essentielles, pour r\'e9aliser, utiliser, vendre, offrir \'e0 la vente, importer et autrement ex\'e9cuter, modifier et propager les contenus de sa version contributive.\ +\ +Dans les trois paragraphes suivants, une \'ab licence de brevet \'bb d\'e9signe tous les accords ou engagements exprim\'e9s, quel que soit le nom que vous lui donnez, de ne pas mettre en vigueur un brevet (telle qu\'92une permission explicite pour mettre en pratique un brevet, ou un accord pour ne pas poursuivre un Destinataire pour cause de violation de brevet). \'ab Accorder \'bb une telle licence de brevet \'e0 une partie signifie conclure un tel accord ou engagement \'e0 ne pas faire appliquer le brevet \'e0 cette partie.\ +\ +Si vous acheminez un Travail Couvert, d\'e9pendant en connaissance d\'92une licence de brevet, et si le Source Correspondant du travail n\'92est pas disponible \'e0 quiconque copie, sans frais et suivant les termes de cette Licence, \'e0 travers un serveur r\'e9seau publiquement acessible ou tout autre moyen imm\'e9diatement accessible, alors vous devez soit (1) rendre la Source Correspondante ainsi disponible, soit (2) vous engager \'e0 vous priver pour vous-m\'eame du b\'e9n\'e9fice de la licence de brevet pour ce travail particulier, soit (3) vous engager, d\'92une fa\'e7on consistante avec les obligations de cette Licence, \'e0 \'e9tendre la licence de brevet aux Destinataires de ce travail. \'ab D\'e9pendant en connaissance \'bb signifie que vous avez effectivement connaissance que, selon la licence de brevet, votre acheminement du Travail Couvert dans un pays, ou l\'92utilisation du Travail Couvert par votre Destinataire dans un pays, infreindrait un ou plusieurs brevets identifiables dans ce pays o\'f9 vous avez des raisons de penser qu\'92ils sont valides.\ +\ +Si, conform\'e9ment \'e0 ou en liaison avec une m\'eame transaction ou un m\'eame arrangement, vous acheminez, ou propagez en procurant un acheminement de, un Travail Couvert et accordez une licence de brevet \'e0 l\'92une des parties recevant le Travail Couvert pour lui permettre d\'92utiliser, propager, modifier ou acheminer une copie sp\'e9cifique du Travail Couvert, alors votre accord est automatiquement \'e9tendu \'e0 tous les Destinataires du Travail Couvert et des travaux bas\'e9s sur celui-ci.\ +\ +Une licence de brevet est \'ab discriminatoire \'bb si, dans le champ de sa couverture, elle n\'92inclut pas un ou plusieurs des droits qui sont sp\'e9cifiquement accord\'e9s selon cette Licence, ou en prohibe l\'92exercice, ou est conditionn\'e9e par le non-exercice d\'92un ou plusieurs de ces droits. Vous ne pouvez pas acheminer un Travail Couvert si vous \'eates partie \'e0 un arrangement selon lequel une partie tierce exer\'e7ant son activit\'e9 dans la distribution de logiciels et \'e0 laquelle vous effectuez un paiement fond\'e9 sur l\'92\'e9tendue de votre activit\'e9 d\'92acheminement du travail, et selon lequel la partie tierce accorde, \'e0 une quelconque partie qui recevrait depuis vous le Travail Couvert, une licence de brevet discriminatoire (a) en relation avec les copies du Travail Couvert achemin\'e9es par vous (ou les copies r\'e9alis\'e9es \'e0 partir de ces copies), ou (b) avant tout destin\'e9e et en relation avec des produits sp\'e9cifiques ou compilations contenant le Travail Couvert, \'e0 moins que vous ayez conclu cet arrangement ou que la licence de brevet ait \'e9t\'e9 accord\'e9e avant le 28 mars 2007.\ +\ +Rien dans cette Licence ne devrait \'eatre interpr\'e9t\'e9 comme devant exclure ou limiter toute licence implicite ou d\'92autres moyens de d\'e9fense \'e0 une infraction qui vous seraient autrement disponible selon la loi applicable relative aux brevets.\ +Article 12. Non abandon de la libert\'e9 des autres.\ +\ +Si des conditions vous sont impos\'e9es (que ce soit par d\'e9cision judiciaire, par un accord ou autrement) qui contredisent les conditions de cette Licence, elles ne vous excusent pas des conditions de cette Licence. Si vous ne pouvez pas acheminer un Travail Couvert de fa\'e7on \'e0 satisfaire simult\'e9n\'e9ment vos obligations suivant cette Licence et toutes autres obligations pertinentes, alors en cons\'e9quence vous ne pouvez pas du tout l\'92acheminer. Par exemple, si vous avez un accord sur des termes qui vous obligent \'e0 collecter pour le r\'e9acheminement des royalties depuis ceux \'e0 qui vous acheminez le Programme, la seule fa\'e7on qui puisse vous permettre de satisfaire \'e0 la fois \'e0 ces termes et ceux de cette Licence sera de vous abstenir enti\'e8rement d\'92acheminer le Programme.\ +Article 13. Utilisation avec la Licence G\'e9n\'e9rale Publique Affero GNU.\ +\ +Nonobstant toute autre clause de cette Licence, vous avez la permission de lier ou combiner tout Travail Couvert avec un travail plac\'e9 sous la version 3 de la Licence G\'e9n\'e9rale Publique GNU Affero (\'93GNU Affero General Public License\'94) en un seul travail combin\'e9, et d\'92acheminer le travail r\'e9sultant. Les termes de cette Licence continueront \'e0 s\'92appliquer \'e0 la partie formant un Travail Couvert, mais les obligations sp\'e9ciales de la Licence G\'e9n\'e9rale Publique GNU Affero, article 13, concernant l\'92interaction \'e0 travers un r\'e9seau s\'92appliqueront \'e0 la combinaison en tant que telle.\ +Article 14. Versions r\'e9vis\'e9es de cette License.\ +\ +La Free Software Foundation peut publier des versions r\'e9vis\'e9es et/ou nouvelles de la Licence Publique G\'e9n\'e9rale GNU (\'93GNU General Public License\'94) de temps en temps. De telles version nouvelles resteront similaires dans l\'92esprit avec la pr\'e9sente version, mais peuvent diff\'e9rer dans le d\'e9tail afin de traiter de nouveaux probl\'e8mes ou pr\'e9occupations.\ +\ +Chaque version re\'e7oit un num\'e9ro de version distinctif. Si le Programme indique qu\'92une version sp\'e9cifique de la Licence Publique G\'e9n\'e9rale GNU \'ab ou toute version ult\'e9rieure \'bb (\'93or any later version\'94) s\'92applique \'e0 celui-ci, vous avez le choix de suivre soit les termes et conditions de cette version num\'e9rot\'e9e, soit ceux de n\'92importe quelle version publi\'e9e ult\'e9rieurement par la Free Software Foundation. Si le Programme n\'92indique pas une version sp\'e9cifique de la Licence Publique G\'e9n\'e9rale GNU, vous pouvez choisir l\'92une quelconque des versions qui ont \'e9t\'e9 publi\'e9es par la Free Software Foundation.\ +\ +Si le Programme sp\'e9cifie qu\'92un interm\'e9diaire peut d\'e9cider quelles versions futures de la Licence G\'e9n\'e9rale Publique GNU peut \'eatre utilis\'e9e, la d\'e9claration publique d\'92acceptation d\'92une version par cet interm\'e9diaire vous autorise \'e0 choisir cette version pour le Programme.\ +\ +Des versions ult\'e9rieures de la licence peuvent vous donner des permissions additionelles ou diff\'e9rentes. Cependant aucune obligation additionelle n\'92est impos\'e9e \'e0 l\'92un des auteurs ou titulaires de Droit d\'92Auteur du fait de votre choix de suivre une version ult\'e9rieure.\ +Article 15. D\'e9claration d\'92absence de garantie.\ +\ +IL N\'92Y A AUCUNE GARANTIE POUR LE PROGRAMME, DANS LES LIMITES PERMISES PAR LA LOI APPLICABLE. \'c0 MOINS QUE CELA NE SOIT \'c9TABLI DIFF\'c9REMMENT PAR \'c9CRIT, LES PROPRI\'c9TAIRES DE DROITS ET/OU LES AUTRES PARTIES FOURNISSENT LE PROGRAMME \'ab EN L\'92\'c9TAT \'bb SANS GARANTIE D\'92AUCUNE SORTE, QU\'92ELLE SOIT EXPRIM\'c9E OU IMPLICITE, CECI COMPRENANT, SANS SE LIMITER \'c0 CELLES-CI, LES GARANTIES IMPLICITES DE COMMERCIALISABILIT\'c9 ET D\'92AD\'c9QUATION \'c0 UN OBJECTIF PARTICULIER. VOUS ASSUMEZ LE RISQUE ENTIER CONCERNANT LA QUALIT\'c9 ET LES PERFORMANCES DU PROGRAMME. DANS L\'92\'c9VENTUALIT\'c9 O\'d9 LE PROGRAMME S\'92AV\'c9RERAIT D\'c9FECTUEUX, VOUS ASSUMEZ LES CO\'dbTS DE TOUS LES SERVICES, R\'c9PARATIONS OU CORRECTIONS N\'c9CESSAIRES.\ +Article 16. Limitation de responsabilit\'e9.\ +\ +EN AUCUNE AUTRE CIRCONSTANCE QUE CELLES REQUISES PAR LA LOI APPLICABLE OU ACCORD\'c9ES PAR \'c9CRIT, UN TITULAIRE DE DROITS SUR LE PROGRAMME, OU TOUT AUTRE PARTIE QUI MODIFIE OU ACHEMINE LE PROGRAMME COMME PERMIS CI-DESSUS, NE PEUT \'caTRE TENU POUR RESPONSABLE ENVERS VOUS POUR LES DOMMAGES, INCLUANT TOUT DOMMAGE G\'c9N\'c9RAL, SP\'c9CIAL, ACCIDENTEL OU INDUIT SURVENANT PAR SUITE DE L\'92UTILISATION OU DE L\'92INCAPACIT\'c9 D\'92UTILISER LE PROGRAMME (Y COMPRIS, SANS SE LIMITER \'c0 CELLES-CI, LA PERTE DE DONN\'c9ES OU L\'92INEXACTITUDE DES DONN\'c9ES RETOURN\'c9ES OU LES PERTES SUBIES PAR VOUS OU DES PARTIES TIERCES OU L\'92INCAPACIT\'c9 DU PROGRAMME \'c0 FONCTIONNER AVEC TOUT AUTRE PROGRAMME), M\'caME SI UN TEL TITULAIRE OU TOUTE AUTRE PARTIE A \'c9T\'c9 AVIS\'c9 DE LA POSSIBILIT\'c9 DE TELS DOMMAGES.\ +Article 17. Interpr\'e9tation des sections 15 et 16.\ +\ +Si la d\'e9claration d\'92absence de garantie et la limitation de responsabilit\'e9 fournies ci-dessus ne peuvent prendre effet localement selon leurs termes, les cours de justice qui les examinent doivent appliquer la l\'e9gislation locale qui approche au plus pr\'e8s possible une lev\'e9e absolue de toute responsabilit\'e9 civile li\'e9e au Programme, \'e0 moins qu\'92une garantie ou assumation de responsabilit\'e9 accompagne une copie du Programme en \'e9change d\'92un paiement.\ +\ +FIN DES TERMES ET CONDITIONS.\ +Comment appliquer ces termes \'e0 vos nouveaux programmes\ +\ +Si vous d\'e9veloppez un nouveau programme et voulez qu\'92il soit le plus possible utilisable par le public, la meilleure fa\'e7on d\'92y parvenir et d\'92en faire un logiciel libre que chacun peut redistribuer et changer suivant ces termes-ci.\ +\ +Pour appliquer ces termes, attachez les notices suivantes au programme. Il est plus s\'fbr de les attacher au d\'e9but de chacun des fichiers sources afin de transporter de fa\'e7on la plus effective possible l\'92exclusion de garantie ; et chaque fichier devrait comporter au moins la ligne de r\'e9servation de droit (\'93copyright\'94) et une indication permettant de savoir o\'f9 la notice compl\'e8te peut \'eatre trouv\'e9e :\ +\ + <une ligne donnant le nom du programme et une br\'e8ve id\'e9e de ce qu\'92il fait.>\ + Copyright (C) <ann\'e9e> <nom de l\'92auteur> \'97 Tous droits r\'e9serv\'e9s.\ + \ + Ce programme est un logiciel libre ; vous pouvez le redistribuer ou le\ + modifier suivant les termes de la \'93GNU General Public License\'94 telle que\ + publi\'e9e par la Free Software Foundation : soit la version 3 de cette\ + licence, soit (\'e0 votre gr\'e9) toute version ult\'e9rieure.\ + \ + Ce programme est distribu\'e9 dans l\'92espoir qu\'92il vous sera utile, mais SANS\ + AUCUNE GARANTIE : sans m\'eame la garantie implicite de COMMERCIALISABILIT\'c9\ + ni d\'92AD\'c9QUATION \'c0 UN OBJECTIF PARTICULIER. Consultez la Licence G\'e9n\'e9rale\ + Publique GNU pour plus de d\'e9tails.\ + \ + Vous devriez avoir re\'e7u une copie de la Licence G\'e9n\'e9rale Publique GNU avec\ + ce programme ; si ce n\'92est pas le cas, consultez :\ + <http://www.gnu.org/licenses/>.\ +\ +Ajoutez \'e9galement les informations permettant de vous contacter par courrier \'e9lectronique ou postal.\ +\ +Si le programme produit une interaction sur un terminal, faites lui afficher une courte notice comme celle-ci lors de son d\'e9marrage en mode interactif :\ +\ + <programme> Copyright (C) <ann\'e9e> <nom de l\'92auteur>\ + Ce programme vient SANS ABSOLUMENT AUCUNE GARANTIE ; taper \'93affiche g\'94 pour\ + les d\'e9tails. Ceci est un logiciel libre et vous \'eates invit\'e9 \'e0 le redistribuer\ + suivant certaines conditions ; taper \'93affiche c\'94 pour les d\'e9tails.\ +\ +Les commandes hypoth\'e9tiques \'93affiche g\'94 and \'93affiche c\'94 devrait afficher les parties appropri\'e9es de la Licence G\'e9n\'e9rale Publique. Bien s\'fbr, les commandes de votre programme peuvent \'eatre diff\'e9rentes ; pour une interface graphique, vous pourriez utiliser une \'ab bo\'eete \'c0 propos. \'bb\ +\ +Vous devriez \'e9galement obtenir de votre employeur (si vous travaillez en tant que programmeur) ou de votre \'e9cole un \'ab renoncement aux droits de propri\'e9t\'e9 \'bb pour ce programme, si n\'e9cessaire. Pour plus d\'92informations \'e0 ce sujet, et comment appliquer la GPL GNU, consultez <http://www.gnu.org/licenses/>.\ +\ +La Licence G\'e9n\'e9rale Publique GNU ne permet pas d\'92incorporer votre programme dans des programmes propri\'e9taires. Si votre programme est une biblioth\'e8que de sous-routines, vous pourriez consid\'e9rer qu\'92il serait plus utile de permettre de lier des applications propri\'e9taires avec la biblioth\'e8que. Si c\'92est ce que vous voulez faire, utilisez la Licence G\'e9n\'e9rale Publique Limit\'e9e GNU au lieu de cette Licence ; mais d\'92abord, veuillez lire <http://www.gnu.org/philosophy/why-not-lgpl.html>.\ + +\fs26 \ +En proc\'e9dant \'e0 l'installation de XBMC, vous acceptez la licence ci-dessus. Les droits d'auteur reviennent \'e0 l'\'e9quipe XBMC. L'\'e9quipe XBMC se r\'e9serve le droit de modifier cette licence \'e0 tout moment sans pr\'e9avis.\ +}]]></resource><resource mime-type="text/rtf" kind="embedded" type="readme"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red227\green0\blue0;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\f0\fs26 \cf0 Vous \'eates sur le point d'installer une +\b \cf2 distribution au stade de d\'e9veloppement, Atlantis Beta 1, +\b0 \cf0 de XBMC. Notez que lors des versions en phase de d\'e9veloppement, l'application peut s'arr\'eater occasionnellement ou afficher une erreur inattendue.\ +}]]></resource><resource mime-type="text/rtf" kind="embedded" type="welcome"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\f0\b\fs26 \cf0 XBMC Media Center +\b0 est un centre de media multi-plateforme gratuit et open source.\ +\ +XBMC supporte un vaste panel de formats multim\'e9dia incluant des fonctionnalit\'e9s telles que les listes de lecture, les visualisations audios, les diaporamas, la r\'e9cup\'e9ration de donn\'e9es, les pr\'e9visions m\'e9t\'e9o, etc. En extension, il supporte aussi un large choix de scripts Python.\ +\ +Pour plus d'information, merci de visiter notre site officiel disponible \'e0 cette adresse {\field{\*\fldinst{HYPERLINK "http://xbmc.org"}}{\fldrslt http://xbmc.org}} . Vous trouverez aussi une {\field{\*\fldinst{HYPERLINK "http://xbmc.org/wiki/?title=XBMC_Online_Manual"}}{\fldrslt documentation}} en ligne et un support utilisateurs sur notre {\field{\*\fldinst{HYPERLINK "http://xbmc.org/forum"}}{\fldrslt forum}}.\ +}]]></resource><resource mime-type="text/rtf" kind="embedded" type="conclusion"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\f0\fs26 \cf0 XBMC Media Center a \'e9t\'e9 install\'e9 avec succ\'e8s !\ +\ +Merci de visitez notre forum disponible sur {\field{\*\fldinst{HYPERLINK "http://xbmc.org/forum"}}{\fldrslt http://xbmc.org/forum}} pour toutes questions ou commentaires.\ +\ +Vous pouvez aussi partager votre exp\'e9rience avec les autres utilisateurs de XBMC sur {\field{\*\fldinst{HYPERLINK "irc://irc.freenode.net"}}{\fldrslt irc://irc.freenode.net}} dans les chanels #xbmc, #xbmc-osx et #xbmc-linux.\ +\ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural + +\b \cf0 Merci d'avoir choisis XBMC Media Center.\ +}]]></resource></locale></resources><flags/><item type="file">01xbmc.xml</item><item type="file">02user.xml</item><mod>properties.userDomain</mod><mod>properties.systemDomain</mod><mod>properties.anywhereDomain</mod><mod>properties.customizeOption</mod><mod>properties.title</mod><mod>description</mod><mod>postinstallActions.actions</mod></pkmkdoc>
\ No newline at end of file diff --git a/tools/PackageMaker/XBMC_RemoteBuddy.zip b/tools/PackageMaker/XBMC_RemoteBuddy.zip Binary files differnew file mode 100644 index 0000000000..0ab77d75be --- /dev/null +++ b/tools/PackageMaker/XBMC_RemoteBuddy.zip diff --git a/tools/PackageMaker/background/DiskImageBackground.png b/tools/PackageMaker/background/DiskImageBackground.png Binary files differnew file mode 100644 index 0000000000..2299a1ac75 --- /dev/null +++ b/tools/PackageMaker/background/DiskImageBackground.png diff --git a/tools/PackageMaker/background/DiskImageBackgroundDebug.png b/tools/PackageMaker/background/DiskImageBackgroundDebug.png Binary files differnew file mode 100644 index 0000000000..2299a1ac75 --- /dev/null +++ b/tools/PackageMaker/background/DiskImageBackgroundDebug.png diff --git a/tools/PackageMaker/dmgmaker.pl b/tools/PackageMaker/dmgmaker.pl new file mode 100755 index 0000000000..839fae64c8 --- /dev/null +++ b/tools/PackageMaker/dmgmaker.pl @@ -0,0 +1,67 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +sub make_dmg { + my $mpkg = shift; + my $volname = shift; + my $pkgname = shift; + my $dev_handle; + + die("Could not find \"$mpkg\"\n") + if ! -d $mpkg; + + my $ext = $1 if $mpkg =~ /.*\.(.*?)$/; + $ext = "mpkg" if !$ext; + + # thanks to http://dev.simon-cozens.org/songbee/browser/release-manager-tools/build-dmg.sh + `rm -fr dist`; + `mkdir dist`; + `hdiutil create -fs HFS+ -volname "$volname" -format UDRW -srcfolder "$mpkg" "dist/$volname.dmg"`; + $dev_handle = `hdiutil attach -readwrite -noverify -noautoopen "dist/$volname.dmg" | grep Apple_HFS`; + chomp $dev_handle; + $dev_handle = $1 if $dev_handle =~ /^\/dev\/(disk.)/; + die("Could not obtain device handle\n") if !$dev_handle; + print "Got device handle \"$dev_handle\"\n"; + print "Ignore \"No space left on device\" warnings from ditto, they are an autosize artifact\n"; + `ditto "$mpkg" "/Volumes/$volname/$pkgname.$ext"`; + + # set a volume icon if we have one + if ( -f "VolumeIcon.icns" ) { + `ditto VolumeIcon.icns "/Volumes/$volname/.VolumeIcon.icns"`; + } + # make symlink to /Applications + `ln -s /Applications "/Volumes/$volname/Applications"`; + + if ( -d "background" ) { + `mkdir "/Volumes/$volname/background"`; + `ditto background "/Volumes/$volname/background/"`; + } + if ( -f "VolumeDSStore" ) { + `ditto VolumeDSStore "/Volumes/$volname/.DS_Store"` if $ext ne "app"; + `ditto VolumeDSStoreApp "/Volumes/$volname/.DS_Store"` if $ext eq "app"; + } + if ( -d "background" ) { + `/Developer/Tools/SetFile -a V "/Volumes/$volname/background"`; + } + `/Developer/Tools/SetFile -a C "/Volumes/$volname/"`; + `hdiutil detach $dev_handle`; + `hdiutil convert "dist/$volname.dmg" -format UDZO -imagekey zlib-level=9 -o "dist/$volname.udzo.dmg"`; + `rm -f "dist/$volname.dmg"`; + `mv "dist/$volname.udzo.dmg" "dist/$volname.dmg"`; + `hdiutil internet-enable -yes "dist/$volname.dmg"`; +} + +if (! defined $ARGV[0]) { + die("Please specify the mpkg to make a DMG of as the first argument\n". + "or -c to create a package and use it.\n"); +} + +if ( $ARGV[0] eq "-c" ) { + die("TODO: -c\n"); + #make_dmg(make_mpkg(), "XBMC Atlantis - 8.10", "XBMC Media Center"); + exit; +} + +make_dmg($ARGV[0], "XBMC", "XBMC"); diff --git a/tools/PackageMaker/post_install_user.pl b/tools/PackageMaker/post_install_user.pl new file mode 100755 index 0000000000..442e389539 --- /dev/null +++ b/tools/PackageMaker/post_install_user.pl @@ -0,0 +1,176 @@ +#!/usr/bin/perl + +############################################################################## +# Post install script +# -d4rk 09/13/08 +############################################################################## + +# use strict; # Apple TV's Perl doesn't support this +# use warnings; # + +my $installer_dir = "/var/tmp/installer.teamxbmc.xbmc"; + +# install any plugins that were copied +sub copy_plugins { + my $pluginsrc = "$installer_dir/plugins/"; + my $plugindst = get_home()."/Library/Application Support/XBMC/plugins/"; + + `mkdir -p "$plugindst"`; + `cp -r "$pluginsrc" "$plugindst"`; +} + +sub setup_sources { + my $xbmchome = get_xbmc_home(); + my $userdata = get_userdata_path(); + if (!$userdata) { + print STDERR "Unable to obtain userdata path\n"; + exit; + } + + my $sources = $userdata."/sources.xml"; + + # create userdata directory if it doesn't exist + `mkdir -p "$userdata"`; + + # check whether a sources.xml already exists, and if it does back it up + if ( -f $sources ) { + print STDERR "sources.xml found at \"$sources\", backing up\n"; + my $backup_sources = $sources.".".time().".xml"; + `cp -f \"$sources\" \"$backup_sources\"`; + } + + # construct a sources.xml string + my $sources_xml = get_sources_xml( get_default_sources() ); + if ( $sources_xml ) { + open SOURCES, ">$sources" || exit; + print SOURCES get_sources_xml( get_default_sources() ); + close SOURCES; + } +} + +sub get_userdata_path { + my $xhome = get_xbmc_home(); + return if !defined $xhome; + return "$xhome/userdata"; +} + +sub get_sources_xml { + my $sources = shift; + my ($sourcetype, $source); + + return if !defined $sources; + + my $xml = "<sources>\n"; + while ( ($sourcetype, $source) = each ( %$sources ) ) { + $xml .= (" " x 4)."<$sourcetype>\n"; + $xml .= (" " x 8)."<default></default>\n"; + my ($name, $path); + while ( ($name, $path) = each( %{ $source } ) ) { + $xml .= (" " x 8)."<source>\n"; + $xml .= (" " x 12)."<name>$name</name>\n"; + if ( $path =~ /(.*)\^\^(.*)/ ) { + $xml .= (" " x 12)."<path>".$1."</path>\n"; + $xml .= (" " x 12)."<thumbnail>".$2."</thumbnail>\n"; + } + else { + $xml .= (" " x 12)."<path>".$path."</path>\n"; + } + $xml .= (" " x 8)."</source>\n"; + } + $xml .= (" " x 4)."</$sourcetype>\n"; + } + $xml .= "</sources>\n"; + return $xml; +} + +sub get_home { + return $ENV{'HOME'} if defined $ENV{'HOME'}; +} + +sub get_xbmc_home { + my $os = get_os(); + my $home = get_home(); + return if !defined $home; + if ( $os eq "osx" ) { + return $home."/Library/Application Support/XBMC"; + } + elsif ( $os eq "linux" ) { + return $home."/.xbmc"; + } + return; +} + +sub get_os { + if ( defined $ENV{'OSTYPE'} && $ENV{'OSTYPE'} =~ /linux/ ) { + return "linux"; + } + return "osx"; +} + +sub get_default_sources { + my $sources = {}; + my $home = get_home(); + my $xbmchome = get_xbmc_home(); + return if !defined $xbmchome; + + $sources->{'programs'} = {}; + $sources->{'video'} = {}; + $sources->{'music'} = {}; + $sources->{'pictures'} = {}; + $sources->{'files'} = {}; + + if ( get_os() eq "osx" ) { + + # Default sources for OS X + for my $key ( keys %$sources ) { + $sources->{$key}->{'Volumes'} = "/Volumes"; + $sources->{$key}->{'Home'} = "$home"; + $sources->{$key}->{'Desktop'} = "$home/Desktop"; + } + + $sources->{'music'}->{'Music'} = $home."/Music"; + $sources->{'music'}->{'Music Playlists'} = "special://musicplaylists"; + $sources->{'video'}->{'Movies'} = $home."/Movies"; + $sources->{'video'}->{'Video Playlists'} = "special://videoplaylists"; + $sources->{'pictures'}->{'Pictures'} = $home."/Pictures"; + + my $plugindir = "$xbmchome/plugins/"; + + # iPhoto + if ( -f "$plugindir/pictures/iPhoto/default.py" ) { + $sources->{'pictures'}->{'iPhoto'} = + "plugin://pictures/iPhoto/^^$plugindir/pictures/iPhoto/default.tbn"; + } + + # iTunes + if ( -f "$plugindir/music/iTunes/default.py" ) { + $sources->{'music'}->{'iTunes'} = + "plugin://music/iTunes/^^$plugindir/music/iTunes/default.tbn"; + } + + # AMT + if ( -f "$plugindir/video/Apple Movie Trailers II/default.py" ) { + $sources->{'video'}->{'Apple Movie Trailers'} = + "plugin://video/Apple Movie Trailers II/^^$plugindir/video/Apple Movie Trailers II/default.tbn"; + } + } + elsif ( get_os() eq "linux" ) { + + # Default source for Linux + for my $key ( keys %$sources ) { + $sources->{$key}->{'Media'} = "/media"; + $sources->{$key}->{'Home'} = "$home"; + $sources->{$key}->{'Desktop'} = "$home/Desktop"; + $sources->{$key}->{'Root'} = "/"; + } + } + return $sources; +} + +sub cleanup() { + `rm -rf "$installer_dir"`; +} + +copy_plugins(); +setup_sources(); +cleanup(); diff --git a/tools/PackageMaker/setup window.png b/tools/PackageMaker/setup window.png Binary files differnew file mode 100644 index 0000000000..6214e4c267 --- /dev/null +++ b/tools/PackageMaker/setup window.png diff --git a/tools/Translator/Changelog.txt b/tools/Translator/Changelog.txt new file mode 100644 index 0000000000..d53a61adf0 --- /dev/null +++ b/tools/Translator/Changelog.txt @@ -0,0 +1,28 @@ +************************************************************************************************************* +************************************************************************************************************* + Translator CHANGELOG +************************************************************************************************************* +************************************************************************************************************* + +added/fixed: (dd-mm-yyyy) (please specify date in CET) + - 24-09-2006 fixed: possible crashes when loading the langinfo.xml + - 17-09-2006 fixed: No new languages could be created + - 17-09-2006 added: user is now asked if he wants to save changes on app exit or when opening a new file + - 10-09-2006 changed: help url now points to http://xbmc.org/wiki/index.php?title=XBMC_Translator + - 10-09-2006 added: Product information to the assembly + - 10-09-2006 changed: derived TranslatorException from ApplicationException + - 10-09-2006 fixed: corrected some typos + - 28-07-2006 added: new speed units + - 28-07-2006 fixed: tab stop order when editing a string + - 28-07-2006 added: Translator icon to Add/Remove Programs + - 28-07-2006 added: menu item help that links to http://xbmc.org/wiki/index.php?title=XBMC_Translator + - 07-07-2006 changed: better searching of stings by whole word + - 26-06-2006 changed: input focus is always set to the textbox in the find form + - 24-06-2006 added: better error message for files with duplicate string id's + - 24-06-2006 added: Tools/Validate to check if a language file is well formed + - 21-06-2006 added: now more then one region can specified in the language settings + - 21-06-2006 added: ability to add newline chars when editing a string + - 21-06-2006 fixed: corrected parsing of newline chars + - 21-06-2006 added: throwing an exception if file is not a language file + - 21-06-2006 added: Revision comment is added to each file when converting from old to new format + - 21-06-2006 changed: removed unneeded parameter from the Region.Save() function diff --git a/tools/Translator/Setup/Setup.vdproj b/tools/Translator/Setup/Setup.vdproj new file mode 100644 index 0000000000..a4d163062f --- /dev/null +++ b/tools/Translator/Setup/Setup.vdproj @@ -0,0 +1,1074 @@ +"DeployProject" +{ +"VSVersion" = "3:701" +"ProjectType" = "8:{2C2AF0D9-9B47-4FE5-BEF2-169778172667}" +"IsWebType" = "8:FALSE" +"ProjectName" = "8:Setup" +"LanguageId" = "3:1033" +"CodePage" = "3:1252" +"UILanguageId" = "3:1033" +"SccProjectName" = "8:" +"SccLocalPath" = "8:" +"SccAuxPath" = "8:" +"SccProvider" = "8:" + "Hierarchy" + { + "Entry" + { + "MsmKey" = "8:_06A7E233C0184D43976534F6D22D901A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_15F65061D55F45418AAEF2D60CB7B847" + "OwnerKey" = "8:_8DF39D3C82A542C4B2A77AB57D96302F" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8DF39D3C82A542C4B2A77AB57D96302F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + } + "Configurations" + { + "Debug" + { + "DisplayName" = "8:Debug" + "IsDebugOnly" = "11:TRUE" + "IsReleaseOnly" = "11:FALSE" + "OutputFilename" = "8:Debug\\Setup.msi" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:2" + } + "Release" + { + "DisplayName" = "8:Release" + "IsDebugOnly" = "11:FALSE" + "IsReleaseOnly" = "11:TRUE" + "OutputFilename" = "8:Release\\Setup.msi" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:2" + } + } + "Deployable" + { + "CustomAction" + { + } + "DefaultFeature" + { + "Name" = "8:DefaultFeature" + "Title" = "8:" + "Description" = "8:" + } + "ExternalPersistence" + { + "LaunchCondition" + { + "{2522A265-4974-4402-83C5-3B575A2E935A}:_3DEF919586F543A5B635EA07154B7AC3" + { + "Name" = "8:.NET Framework" + "Message" = "8:[VSDNETMSG]" + "SupportedRuntimes" = "8:1.1.4322" + "InstallUrl" = "8:http://go.microsoft.com/fwlink/?LinkId=9832" + } + } + } + "Feature" + { + } + "File" + { + "{A582A373-4685-4296-BEFE-614B80A702C3}:_06A7E233C0184D43976534F6D22D901A" + { + "SourcePath" = "8:..\\Translator\\App.ico" + "TargetName" = "8:App.ico" + "Tag" = "8:" + "Folder" = "8:_A27FF7782150426E8C0B3F894FAA4AAE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + } + "FileType" + { + } + "Folder" + { + "{78BAF5CE-F2E5-45BE-83BC-DB6AF387E941}:_186E24BB7F834634919C5B5D3C1A6BDF" + { + "Name" = "8:#1916" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:DesktopFolder" + "Folders" + { + } + } + "{58C0ADA3-3CEA-43BD-A3B3-2EA121BC8217}:_A27FF7782150426E8C0B3F894FAA4AAE" + { + "DefaultLocation" = "8:[ProgramFilesFolder][Manufacturer]\\[ProductName]" + "Name" = "8:#1925" + "AlwaysCreate" = "11:TRUE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:TARGETDIR" + "Folders" + { + } + } + "{78BAF5CE-F2E5-45BE-83BC-DB6AF387E941}:_F186081223AE46EB855F73828372471B" + { + "Name" = "8:#1919" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:ProgramMenuFolder" + "Folders" + { + "{F27BD5C5-A65D-4608-96D4-7C5DA1F76302}:_1DC52301BCE34042B390DE888763ACEA" + { + "Name" = "8:Team XBMC" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_ECF515590B0E4B229642B7D51AB5A4FD" + "Folders" + { + } + } + } + } + } + "LaunchCondition" + { + } + "Locator" + { + } + "MsiBootstrapper" + { + "LangId" = "3:1033" + } + "Product" + { + "Name" = "8:Microsoft Visual Studio" + "ProductName" = "8:Translator" + "ProductCode" = "8:{2C7E914A-C942-4AD5-BECD-70E3A916851B}" + "PackageCode" = "8:{261EC689-4F4A-4478-8876-63D66EAC2DA8}" + "UpgradeCode" = "8:{C448D307-6596-4437-88A2-A45CB80E62AF}" + "RestartWWWService" = "11:FALSE" + "RemovePreviousVersions" = "11:FALSE" + "DetectNewerInstalledVersion" = "11:TRUE" + "ProductVersion" = "8:1.0.0" + "Manufacturer" = "8:Team XBMC" + "ARPHELPTELEPHONE" = "8:" + "ARPHELPLINK" = "8:http://xbmc.org" + "Title" = "8:Team XBMC Translator" + "Subject" = "8:" + "ARPCONTACT" = "8:Team XBMC" + "Keywords" = "8:" + "ARPCOMMENTS" = "8:" + "ARPURLINFOABOUT" = "8:http://xbmc.org" + "ARPPRODUCTICON" = "8:_06A7E233C0184D43976534F6D22D901A" + "ARPIconIndex" = "3:0" + "SearchPath" = "8:" + "UseSystemSearchPath" = "11:TRUE" + } + "Registry" + { + "HKLM" + { + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_E0048E33FC2945188CEC0C66B5EE26A9" + { + "Name" = "8:Software" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_5451B466EF694C688946DC25704945AF" + { + "Name" = "8:[Manufacturer]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + } + "Values" + { + } + } + } + "Values" + { + } + } + } + } + "HKCU" + { + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_2406D7E33B72442DB1D084CDB767C1C0" + { + "Name" = "8:Software" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_40506B3910484842886EB65E90A1E199" + { + "Name" = "8:[Manufacturer]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_EF632AD9F2BD4D8EB7B09056087D4664" + { + "Name" = "8:[ProductName]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + } + "Values" + { + "{35AE352C-BC79-4EF9-ABD8-61F467188583}:_6BB62C54D4DD43D6B75B06F1EF5579C6" + { + "Name" = "8:Email" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "ValueTypes" = "3:1" + "Value" = "8:[TRANSLATOR_EMAIL]" + } + "{35AE352C-BC79-4EF9-ABD8-61F467188583}:_96BF26BA6B04466AA586774BAA4FA97A" + { + "Name" = "8:LanguageFolder" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "ValueTypes" = "3:1" + "Value" = "8:" + } + "{35AE352C-BC79-4EF9-ABD8-61F467188583}:_A7F3A5847F4745D6A657FB9FEACDF784" + { + "Name" = "8:Name" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "ValueTypes" = "3:1" + "Value" = "8:[TRANSLATOR_NAME]" + } + "{35AE352C-BC79-4EF9-ABD8-61F467188583}:_C8DDD9C5AEC34C60B8665318C2C58B43" + { + "Name" = "8:Language" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "ValueTypes" = "3:1" + "Value" = "8:" + } + } + } + } + "Values" + { + } + } + } + "Values" + { + } + } + } + } + "HKCR" + { + "Keys" + { + } + } + "HKU" + { + "Keys" + { + } + } + "HKPU" + { + "Keys" + { + } + } + } + "Sequences" + { + } + "Shortcut" + { + "{478F747B-8505-45D1-9AAE-8C3B645C26E3}:_A5EC8641F34E432A864FA82BF79FE70D" + { + "Name" = "8:XBMC Translator" + "Arguments" = "8:" + "Description" = "8:Helps to translate language files for XBMC" + "ShowCmd" = "3:1" + "IconIndex" = "3:0" + "Transitive" = "11:FALSE" + "Target" = "8:_8DF39D3C82A542C4B2A77AB57D96302F" + "Folder" = "8:_1DC52301BCE34042B390DE888763ACEA" + "WorkingFolder" = "8:_A27FF7782150426E8C0B3F894FAA4AAE" + "Icon" = "8:_06A7E233C0184D43976534F6D22D901A" + "Feature" = "8:" + } + } + "UserInterface" + { + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_06B791F8CCE242828BEAA0DA7272021A" + { + "Name" = "8:#1900" + "Sequence" = "3:1" + "Attributes" = "3:1" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_12CC3189E724476586EFB987D32B96F0" + { + "Sequence" = "3:310" + "DisplayName" = "8:Confirm Installation" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdConfirmDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_6E2B40ABD6434A7294C4FA5D9C9FB1EC" + { + "Sequence" = "3:200" + "DisplayName" = "8:Textboxes (A)" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdCustomText1Dlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "BannerText" + { + "Name" = "8:BannerText" + "DisplayName" = "8:#1014" + "Description" = "8:#1114" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:2" + "Value" = "8:Translator Information" + "DefaultValue" = "8:#1214" + "UsePlugInResources" = "11:TRUE" + } + "BodyText" + { + "Name" = "8:BodyText" + "DisplayName" = "8:#1015" + "Description" = "8:#1115" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:2" + "Value" = "8:Enter your name and email adress. The name and email will later be saved with your translated files." + "DefaultValue" = "8:#1215" + "UsePlugInResources" = "11:TRUE" + } + "Edit1Label" + { + "Name" = "8:Edit1Label" + "DisplayName" = "8:#1046" + "Description" = "8:#1146" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:2" + "Value" = "8:Name:" + "DefaultValue" = "8:#1246" + "UsePlugInResources" = "11:TRUE" + } + "Edit1Property" + { + "Name" = "8:Edit1Property" + "DisplayName" = "8:#1050" + "Description" = "8:#1150" + "Type" = "3:14" + "ContextData" = "8:Public" + "Attributes" = "3:2" + "Setting" = "3:2" + "Value" = "8:TRANSLATOR_NAME" + "DefaultValue" = "8:EDITA1" + "UsePlugInResources" = "11:TRUE" + } + "Edit1Value" + { + "Name" = "8:Edit1Value" + "DisplayName" = "8:#1054" + "Description" = "8:#1154" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:" + "DefaultValue" = "8:" + "UsePlugInResources" = "11:TRUE" + } + "Edit1Visible" + { + "Name" = "8:Edit1Visible" + "DisplayName" = "8:#1042" + "Description" = "8:#1142" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "Edit2Label" + { + "Name" = "8:Edit2Label" + "DisplayName" = "8:#1047" + "Description" = "8:#1147" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:2" + "Value" = "8:Email:" + "DefaultValue" = "8:#1247" + "UsePlugInResources" = "11:TRUE" + } + "Edit2Property" + { + "Name" = "8:Edit2Property" + "DisplayName" = "8:#1051" + "Description" = "8:#1151" + "Type" = "3:14" + "ContextData" = "8:Public" + "Attributes" = "3:2" + "Setting" = "3:2" + "Value" = "8:TRANSLATOR_EMAIL" + "DefaultValue" = "8:EDITA2" + "UsePlugInResources" = "11:TRUE" + } + "Edit2Value" + { + "Name" = "8:Edit2Value" + "DisplayName" = "8:#1055" + "Description" = "8:#1155" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:" + "DefaultValue" = "8:" + "UsePlugInResources" = "11:TRUE" + } + "Edit2Visible" + { + "Name" = "8:Edit2Visible" + "DisplayName" = "8:#1043" + "Description" = "8:#1143" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "Edit3Label" + { + "Name" = "8:Edit3Label" + "DisplayName" = "8:#1048" + "Description" = "8:#1148" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1248" + "DefaultValue" = "8:#1248" + "UsePlugInResources" = "11:TRUE" + } + "Edit3Property" + { + "Name" = "8:Edit3Property" + "DisplayName" = "8:#1052" + "Description" = "8:#1152" + "Type" = "3:14" + "ContextData" = "8:Public" + "Attributes" = "3:2" + "Setting" = "3:2" + "Value" = "8:EDITA3" + "DefaultValue" = "8:EDITA3" + "UsePlugInResources" = "11:TRUE" + } + "Edit3Value" + { + "Name" = "8:Edit3Value" + "DisplayName" = "8:#1056" + "Description" = "8:#1156" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:" + "DefaultValue" = "8:" + "UsePlugInResources" = "11:TRUE" + } + "Edit3Visible" + { + "Name" = "8:Edit3Visible" + "DisplayName" = "8:#1044" + "Description" = "8:#1144" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:0" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "Edit4Label" + { + "Name" = "8:Edit4Label" + "DisplayName" = "8:#1049" + "Description" = "8:#1149" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1249" + "DefaultValue" = "8:#1249" + "UsePlugInResources" = "11:TRUE" + } + "Edit4Property" + { + "Name" = "8:Edit4Property" + "DisplayName" = "8:#1053" + "Description" = "8:#1153" + "Type" = "3:14" + "ContextData" = "8:Public" + "Attributes" = "3:2" + "Setting" = "3:2" + "Value" = "8:EDITA4" + "DefaultValue" = "8:EDITA4" + "UsePlugInResources" = "11:TRUE" + } + "Edit4Value" + { + "Name" = "8:Edit4Value" + "DisplayName" = "8:#1057" + "Description" = "8:#1057" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:" + "DefaultValue" = "8:" + "UsePlugInResources" = "11:TRUE" + } + "Edit4Visible" + { + "Name" = "8:Edit4Visible" + "DisplayName" = "8:#1045" + "Description" = "8:#1145" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:0" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_EB2E51B34B7748D88E204E8DFD39EA0E" + { + "Sequence" = "3:300" + "DisplayName" = "8:Installation Folder" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdFolderDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_F79930341DCC416F819D7276D3EF333B" + { + "Sequence" = "3:100" + "DisplayName" = "8:Welcome" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdWelcomeDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "CopyrightWarning" + { + "Name" = "8:CopyrightWarning" + "DisplayName" = "8:#1002" + "Description" = "8:#1102" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1202" + "DefaultValue" = "8:#1202" + "UsePlugInResources" = "11:TRUE" + } + "Welcome" + { + "Name" = "8:Welcome" + "DisplayName" = "8:#1003" + "Description" = "8:#1103" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1203" + "DefaultValue" = "8:#1203" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_23E83C371897464E8EAE0BDEFEB2B44F" + { + "Name" = "8:#1901" + "Sequence" = "3:2" + "Attributes" = "3:2" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_F15CD55A9A124DEE8B3D631F1026AA09" + { + "Sequence" = "3:100" + "DisplayName" = "8:Progress" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdAdminProgressDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "ShowProgress" + { + "Name" = "8:ShowProgress" + "DisplayName" = "8:#1009" + "Description" = "8:#1109" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{B654A020-6903-4E6A-A86C-75DC463DB54B}:_269F24532BDA4169885FA5086E633E52" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdUserInterface.wim" + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_43FAF03054DE405A81AD0B2EF9D0387E" + { + "Name" = "8:#1901" + "Sequence" = "3:1" + "Attributes" = "3:2" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_C26EB658BB46440B8003CC4C2C28F1CE" + { + "Sequence" = "3:100" + "DisplayName" = "8:Progress" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdProgressDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "ShowProgress" + { + "Name" = "8:ShowProgress" + "DisplayName" = "8:#1009" + "Description" = "8:#1109" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{B654A020-6903-4E6A-A86C-75DC463DB54B}:_95D78D1EAD344EAA965D3FADCB36CC2C" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdBasicDialogs.wim" + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_AA563F317E8F4286949243A3FBDA1BAA" + { + "Name" = "8:#1900" + "Sequence" = "3:2" + "Attributes" = "3:1" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_56A167D9EE744CE9A1610436C2BD37D6" + { + "Sequence" = "3:100" + "DisplayName" = "8:Welcome" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdAdminWelcomeDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "CopyrightWarning" + { + "Name" = "8:CopyrightWarning" + "DisplayName" = "8:#1002" + "Description" = "8:#1102" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1202" + "DefaultValue" = "8:#1202" + "UsePlugInResources" = "11:TRUE" + } + "Welcome" + { + "Name" = "8:Welcome" + "DisplayName" = "8:#1003" + "Description" = "8:#1103" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1203" + "DefaultValue" = "8:#1203" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_F2C0EBB6F4874870ADD5471517CA054A" + { + "Sequence" = "3:300" + "DisplayName" = "8:Confirm Installation" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdAdminConfirmDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_F8623BBBD1BE48CBAE046D5D4EB3C320" + { + "Sequence" = "3:200" + "DisplayName" = "8:Installation Folder" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFolderDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_BC58D4AD6D9F4EEAAC405596FF203F64" + { + "Name" = "8:#1902" + "Sequence" = "3:2" + "Attributes" = "3:3" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_E74FBD9976034D1A924CEF26ADACD155" + { + "Sequence" = "3:100" + "DisplayName" = "8:Finished" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFinishedDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_F9ACA7AF7FEA4A85B1E2F5213DE90AF5" + { + "Name" = "8:#1902" + "Sequence" = "3:1" + "Attributes" = "3:3" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_3EE9B3F2DFBE497884BF510E376A36BB" + { + "Sequence" = "3:100" + "DisplayName" = "8:Finished" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:<VsdDialogDir>\\VsdFinishedDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "UpdateText" + { + "Name" = "8:UpdateText" + "DisplayName" = "8:#1058" + "Description" = "8:#1158" + "Type" = "3:15" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1258" + "DefaultValue" = "8:#1258" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + } + "MergeModule" + { + "{35A69C6E-5BA4-440D-803D-762B59A45393}:_15F65061D55F45418AAEF2D60CB7B847" + { + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:TRUE" + "SourcePath" = "8:dotnetfxredist_x86.msm" + "Properties" + { + } + "LanguageId" = "3:1033" + "Exclude" = "11:TRUE" + "Folder" = "8:" + "Feature" = "8:" + "IsolateTo" = "8:" + } + } + "ProjectOutput" + { + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_2A419B2AF19541678CAF43A93072EDE7" + { + "SourcePath" = "8:" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_A27FF7782150426E8C0B3F894FAA4AAE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:Release" + "OutputGroupCanonicalName" = "8:LocalizedResourceDlls" + "OutputProjectGuid" = "8:{75A56598-4600-401D-9F4B-B9F36C4AC86F}" + "ShowKeyOutput" = "11:TRUE" + "ExcludeFilters" + { + } + } + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_8DF39D3C82A542C4B2A77AB57D96302F" + { + "SourcePath" = "8:..\\Translator\\obj\\Release\\Translator.exe" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_A27FF7782150426E8C0B3F894FAA4AAE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:Release" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{75A56598-4600-401D-9F4B-B9F36C4AC86F}" + "ShowKeyOutput" = "11:TRUE" + "ExcludeFilters" + { + } + } + } + } +} diff --git a/tools/Translator/Translator.sln b/tools/Translator/Translator.sln new file mode 100644 index 0000000000..ad41e9d440 --- /dev/null +++ b/tools/Translator/Translator.sln @@ -0,0 +1,27 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Translator", "Translator\Translator.csproj", "{75A56598-4600-401D-9F4B-B9F36C4AC86F}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Setup", "Setup\Setup.vdproj", "{53CD3187-5874-4E09-8063-AE63DFEA4293}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {75A56598-4600-401D-9F4B-B9F36C4AC86F}.Debug.ActiveCfg = Debug|.NET + {75A56598-4600-401D-9F4B-B9F36C4AC86F}.Debug.Build.0 = Debug|.NET + {75A56598-4600-401D-9F4B-B9F36C4AC86F}.Release.ActiveCfg = Release|.NET + {75A56598-4600-401D-9F4B-B9F36C4AC86F}.Release.Build.0 = Release|.NET + {53CD3187-5874-4E09-8063-AE63DFEA4293}.Debug.ActiveCfg = Debug + {53CD3187-5874-4E09-8063-AE63DFEA4293}.Release.ActiveCfg = Release + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/tools/Translator/Translator/AboutForm.cs b/tools/Translator/Translator/AboutForm.cs new file mode 100644 index 0000000000..94b13756d7 --- /dev/null +++ b/tools/Translator/Translator/AboutForm.cs @@ -0,0 +1,157 @@ +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Shows info about the application. + /// </summary> + public sealed class AboutForm : System.Windows.Forms.Form + { + private System.Windows.Forms.Button buttonOk; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.GroupBox groupBox1; + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.Container components = null; + + public AboutForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // + // TODO: Add any constructor code after InitializeComponent call + // + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if(components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.buttonOk = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // buttonOk + // + this.buttonOk.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonOk.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonOk.Location = new System.Drawing.Point(109, 112); + this.buttonOk.Name = "buttonOk"; + this.buttonOk.TabIndex = 0; + this.buttonOk.Text = "OK"; + // + // label1 + // + this.label1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.label1.Location = new System.Drawing.Point(28, 16); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(208, 23); + this.label1.TabIndex = 1; + this.label1.Text = "Team XBMC Translator 0.21"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label1.UseMnemonic = false; + // + // label2 + // + this.label2.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.label2.Location = new System.Drawing.Point(28, 40); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(208, 23); + this.label2.TabIndex = 2; + this.label2.Text = "Copyright © 2006 Team XBMC"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label2.UseMnemonic = false; + // + // linkLabel1 + // + this.linkLabel1.Cursor = System.Windows.Forms.Cursors.Hand; + this.linkLabel1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.linkLabel1.Location = new System.Drawing.Point(28, 64); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(208, 23); + this.linkLabel1.TabIndex = 3; + this.linkLabel1.TabStop = true; + this.linkLabel1.Tag = ""; + this.linkLabel1.Text = "http://xbmc.org"; + this.linkLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.linkLabel1.UseMnemonic = false; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.linkLabel1); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox1.Location = new System.Drawing.Point(14, 8); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(264, 96); + this.groupBox1.TabIndex = 4; + this.groupBox1.TabStop = false; + // + // AboutForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.CancelButton = this.buttonOk; + this.ClientSize = new System.Drawing.Size(292, 142); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.buttonOk); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About"; + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + #region Control Events + + /// <summary> + /// Reacts on a click of the linklable and opens the url (label of the control) + /// in the standard browser. + /// </summary> + private void linkLabel1_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(linkLabel1.Text); + } + + #endregion + } +} diff --git a/tools/Translator/Translator/AboutForm.resx b/tools/Translator/Translator/AboutForm.resx new file mode 100644 index 0000000000..b2d6f6b8d2 --- /dev/null +++ b/tools/Translator/Translator/AboutForm.resx @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="buttonOk.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonOk.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonOk.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="linkLabel1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="linkLabel1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="linkLabel1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.Name"> + <value>AboutForm</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/App.ico b/tools/Translator/Translator/App.ico Binary files differnew file mode 100644 index 0000000000..0fee41ef5c --- /dev/null +++ b/tools/Translator/Translator/App.ico diff --git a/tools/Translator/Translator/AssemblyInfo.cs b/tools/Translator/Translator/AssemblyInfo.cs new file mode 100644 index 0000000000..ecea736e77 --- /dev/null +++ b/tools/Translator/Translator/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("Tool To Translate XBMC Language Files")] +[assembly: AssemblyDescription("Tool To Translate XBMC Language Files")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Team XBMC")] +[assembly: AssemblyProduct("Translator")] +[assembly: AssemblyCopyright("Team XBMC")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\<configuration>. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/tools/Translator/Translator/ChooseLanguageForm.cs b/tools/Translator/Translator/ChooseLanguageForm.cs new file mode 100644 index 0000000000..fe9e2c7e02 --- /dev/null +++ b/tools/Translator/Translator/ChooseLanguageForm.cs @@ -0,0 +1,183 @@ +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using TeamXBMC.TranslatorCore; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Shows all available languages. The user can choose + /// the language to be translated. + /// </summary> + public sealed class ChooseLanguageForm : System.Windows.Forms.Form + { + private System.Windows.Forms.ListBox listBox1; + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Label label1; + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.Container components = null; + + public ChooseLanguageForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // + // TODO: Add any constructor code after InitializeComponent call + // + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if(components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.buttonOK = new System.Windows.Forms.Button(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.listBox1 = new System.Windows.Forms.ListBox(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // buttonOK + // + this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonOK.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonOK.Location = new System.Drawing.Point(80, 200); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.TabIndex = 3; + this.buttonOK.Text = "OK"; + this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + // + // buttonCancel + // + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonCancel.Location = new System.Drawing.Point(168, 200); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.TabIndex = 4; + this.buttonCancel.Text = "Cancel"; + // + // listBox1 + // + this.listBox1.Location = new System.Drawing.Point(8, 32); + this.listBox1.Name = "listBox1"; + this.listBox1.Size = new System.Drawing.Size(232, 160); + this.listBox1.Sorted = true; + this.listBox1.TabIndex = 2; + this.listBox1.DoubleClick += new System.EventHandler(this.listBox1_DoubleClick); + this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); + // + // label1 + // + this.label1.Location = new System.Drawing.Point(8, 8); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(240, 23); + this.label1.TabIndex = 1; + this.label1.Text = "Select the language to be translated"; + // + // ChooseLanguageForm + // + this.AcceptButton = this.buttonOK; + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(250, 232); + this.Controls.Add(this.label1); + this.Controls.Add(this.listBox1); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.buttonOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ChooseLanguageForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Choose Language"; + this.Load += new System.EventHandler(this.ChooseLanguageForm_Load); + this.ResumeLayout(false); + + } + #endregion + + #region Form initialization + + /// <summary> + /// Fills the listbox with all available languages and selects the one currently edited + /// </summary> + private void ChooseLanguageForm_Load(object sender, System.EventArgs e) + { + string root=Settings.Instance.LanguageFolder; + string[] languages=TranslationManager.Instance.Languages; + + foreach (string language in languages) + { + listBox1.Items.Add(language); + + if (Settings.Instance.Language==language) + { + listBox1.SelectedItem=language; + } + } + + if (Settings.Instance.Language=="") + { // No language selected yet, disable ok button + buttonOK.Enabled=false; + } + } + + + #endregion + + #region Control Events + + /// <summary> + /// The double clicked language in the listbox is selected as the current one + /// and afterwards the dialog is closed + /// </summary> + private void listBox1_DoubleClick(object sender, System.EventArgs e) + { + Settings.Instance.Language=(string)listBox1.SelectedItem; + + DialogResult=DialogResult.OK; + Close(); + } + + /// <summary> + /// Sets the language selected in the listbox as the current one. + /// </summary> + private void buttonOK_Click(object sender, System.EventArgs e) + { + Settings.Instance.Language=(string)listBox1.SelectedItem; + } + + private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e) + { + buttonOK.Enabled=true; + } + + #endregion + } +} diff --git a/tools/Translator/Translator/ChooseLanguageForm.resx b/tools/Translator/Translator/ChooseLanguageForm.resx new file mode 100644 index 0000000000..f213de9277 --- /dev/null +++ b/tools/Translator/Translator/ChooseLanguageForm.resx @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="buttonOK.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonOK.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonOK.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="listBox1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="listBox1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="listBox1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.Name"> + <value>ChooseLanguageForm</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/EditStringForm.cs b/tools/Translator/Translator/EditStringForm.cs new file mode 100644 index 0000000000..1134746949 --- /dev/null +++ b/tools/Translator/Translator/EditStringForm.cs @@ -0,0 +1,239 @@ +using System; +using System.Drawing; +using System.ComponentModel; +using System.Windows.Forms; +using TeamXBMC.TranslatorCore; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Form to edit a selected string of the listview from the main form. + /// </summary> + public class EditStringForm : System.Windows.Forms.Form + { + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBoxTranslated; + private System.Windows.Forms.TextBox textBoxOriginal; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Button buttonOk; + private System.Windows.Forms.Button buttonNewline; + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.Container components = null; + + public EditStringForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // + // TODO: Add any constructor code after InitializeComponent call + // + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if(components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.buttonNewline = new System.Windows.Forms.Button(); + this.textBoxTranslated = new System.Windows.Forms.TextBox(); + this.textBoxOriginal = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.buttonOk = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.buttonNewline); + this.groupBox1.Controls.Add(this.textBoxTranslated); + this.groupBox1.Controls.Add(this.textBoxOriginal); + this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox1.Location = new System.Drawing.Point(8, 8); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(392, 152); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Selection"; + // + // buttonNewline + // + this.buttonNewline.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonNewline.Location = new System.Drawing.Point(352, 48); + this.buttonNewline.Name = "buttonNewline"; + this.buttonNewline.Size = new System.Drawing.Size(24, 23); + this.buttonNewline.TabIndex = 4; + this.buttonNewline.Text = "¶"; + this.buttonNewline.Click += new System.EventHandler(this.buttonNewline_Click); + // + // textBoxTranslated + // + this.textBoxTranslated.Location = new System.Drawing.Point(16, 48); + this.textBoxTranslated.Name = "textBoxTranslated"; + this.textBoxTranslated.Size = new System.Drawing.Size(328, 20); + this.textBoxTranslated.TabIndex = 3; + this.textBoxTranslated.Text = ""; + // + // textBoxOriginal + // + this.textBoxOriginal.Location = new System.Drawing.Point(16, 112); + this.textBoxOriginal.Name = "textBoxOriginal"; + this.textBoxOriginal.ReadOnly = true; + this.textBoxOriginal.Size = new System.Drawing.Size(360, 20); + this.textBoxOriginal.TabIndex = 6; + this.textBoxOriginal.TabStop = false; + this.textBoxOriginal.Text = ""; + // + // label2 + // + this.label2.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.label2.Location = new System.Drawing.Point(24, 32); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(352, 16); + this.label2.TabIndex = 2; + this.label2.Text = "&Translated:"; + // + // label1 + // + this.label1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.label1.Location = new System.Drawing.Point(24, 96); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(360, 16); + this.label1.TabIndex = 5; + this.label1.Text = "English:"; + // + // buttonCancel + // + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonCancel.Location = new System.Drawing.Point(328, 168); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.TabIndex = 8; + this.buttonCancel.Text = "Cancel"; + // + // buttonOk + // + this.buttonOk.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonOk.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonOk.Location = new System.Drawing.Point(240, 168); + this.buttonOk.Name = "buttonOk"; + this.buttonOk.TabIndex = 7; + this.buttonOk.Text = "OK"; + // + // EditStringForm + // + this.AcceptButton = this.buttonOk; + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(410, 200); + this.Controls.Add(this.buttonOk); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.label1); + this.Controls.Add(this.label2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditStringForm"; + this.ShowInTaskbar = false; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Edit String"; + this.Load += new System.EventHandler(this.EditStringForm_Load); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + #region Form initialization + + /// <summary> + /// Sets the label controls with the names of the languages + /// </summary> + private void EditStringForm_Load(object sender, System.EventArgs e) + { + label1.Text=TranslationManager.Instance.LanguageOriginal; + label2.Text=TranslationManager.Instance.LanguageTranslated; + } + + #endregion + + #region Control Events + + private void buttonNewline_Click(object sender, System.EventArgs e) + { + if (textBoxTranslated.SelectionStart>=0) + { + int start=textBoxTranslated.SelectionStart; + int length=textBoxTranslated.SelectionLength; + + if (length==0) + { // caret at a position but no text marked, + // just insert the ¶ + textBoxTranslated.Text=textBoxTranslated.Text.Insert(start, "¶"); + } + else + { // caret at a position with text marked, + // replace the marked text with ¶ + textBoxTranslated.Text=textBoxTranslated.Text.Remove(start, length); + textBoxTranslated.Text=textBoxTranslated.Text.Insert(start, "¶"); + } + + // Update caret position to where we inserted the newline + textBoxTranslated.Focus(); // Needs focus to move the caret + textBoxTranslated.SelectionStart=start+1; + textBoxTranslated.SelectionLength=0; + } + } + + #endregion + + #region Properties + + /// <summary> + /// Gets/Sets the translated string of the language + /// </summary> + public string Translated + { + get { return textBoxTranslated.Text; } + set { textBoxTranslated.Text=value; } + } + + /// <summary> + /// Gets/Sets the original string of the language + /// </summary> + public string Original + { + set { textBoxOriginal.Text=value; } + } + + #endregion + } +} diff --git a/tools/Translator/Translator/EditStringForm.resx b/tools/Translator/Translator/EditStringForm.resx new file mode 100644 index 0000000000..dcc80c5a3d --- /dev/null +++ b/tools/Translator/Translator/EditStringForm.resx @@ -0,0 +1,211 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="groupBox1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonNewline.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonNewline.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonNewline.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxTranslated.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxTranslated.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxTranslated.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxOriginal.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxOriginal.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxOriginal.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonOk.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonOk.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonOk.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.Name"> + <value>EditStringForm</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/Enumerator.cs b/tools/Translator/Translator/Enumerator.cs new file mode 100644 index 0000000000..029e8f9fdb --- /dev/null +++ b/tools/Translator/Translator/Enumerator.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// Available enumerators for the TranslatorArray class. + /// </summary> + public enum TranslatorArrayEnumerator + { + All=0, + Translated, + Untranslated, + Changed + }; + + /// <summary> + /// Enumerates a TranslatorArray class by items with the state translated. + /// </summary> + public class EnumeratorTranslated : IEnumerator + { + private IEnumerator enumerator=null; + + public EnumeratorTranslated(IEnumerator enumerator) + { + this.enumerator=enumerator; + } + + #region IEnumerator Members + + public void Reset() + { + enumerator.Reset(); + MoveNext(); + } + + public object Current + { + get + { + return enumerator.Current; + } + } + + public bool MoveNext() + { + if (!enumerator.MoveNext()) + return false; + + TranslatorItem item=(TranslatorItem)enumerator.Current; + while (item.State!=TranslationState.Translated) + { + if (!enumerator.MoveNext()) + return false; + item=(TranslatorItem)enumerator.Current; + } + + return true; + } + + #endregion + }; + + /// <summary> + /// Enumerates a TranslatorArray class by items with the state untranslated. + /// </summary> + public class EnumeratorUntranslated : IEnumerator + { + private IEnumerator enumerator=null; + + public EnumeratorUntranslated(IEnumerator enumerator) + { + this.enumerator=enumerator; + } + + #region IEnumerator Members + + public void Reset() + { + enumerator.Reset(); + MoveNext(); + } + + public object Current + { + get + { + return enumerator.Current; + } + } + + public bool MoveNext() + { + if (!enumerator.MoveNext()) + return false; + + TranslatorItem item=(TranslatorItem)enumerator.Current; + while (item.State!=TranslationState.Untranslated) + { + if (!enumerator.MoveNext()) + return false; + + item=(TranslatorItem)enumerator.Current; + } + + return true; + } + + #endregion + }; + + /// <summary> + /// Enumerates a TranslatorArray class by items with the state changed. + /// </summary> + public class EnumeratorChanged : IEnumerator + { + private IEnumerator enumerator=null; + + public EnumeratorChanged(IEnumerator enumerator) + { + this.enumerator=enumerator; + } + + #region IEnumerator Members + + public void Reset() + { + enumerator.Reset(); + MoveNext(); + } + + public object Current + { + get + { + return enumerator.Current; + } + } + + public bool MoveNext() + { + if (!enumerator.MoveNext()) + return false; + + TranslatorItem item=(TranslatorItem)enumerator.Current; + while (item.State!=TranslationState.Changed) + { + if (!enumerator.MoveNext()) + return false; + + item=(TranslatorItem)enumerator.Current; + } + + return true; + } + + #endregion + }; +} diff --git a/tools/Translator/Translator/FindForm.cs b/tools/Translator/Translator/FindForm.cs new file mode 100644 index 0000000000..e0f0529500 --- /dev/null +++ b/tools/Translator/Translator/FindForm.cs @@ -0,0 +1,257 @@ +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Form to enter find criteria. + /// </summary> + public sealed class FindForm : System.Windows.Forms.Form + { + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBoxFind; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Button buttonFindNext; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.RadioButton radioButtonUp; + private System.Windows.Forms.RadioButton radioButtonDown; + private System.Windows.Forms.CheckBox checkBoxMatchCase; + private System.Windows.Forms.CheckBox checkBoxMatchWholeWord; + private bool matchCase=false; + private bool matchWholeWord=false; + private bool searchDown=true; + private string textFind; + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.Container components = null; + + public FindForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if(components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.textBoxFind = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.buttonFindNext = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.radioButtonDown = new System.Windows.Forms.RadioButton(); + this.radioButtonUp = new System.Windows.Forms.RadioButton(); + this.checkBoxMatchWholeWord = new System.Windows.Forms.CheckBox(); + this.checkBoxMatchCase = new System.Windows.Forms.CheckBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // textBoxFind + // + this.textBoxFind.Location = new System.Drawing.Point(72, 8); + this.textBoxFind.Name = "textBoxFind"; + this.textBoxFind.Size = new System.Drawing.Size(184, 20); + this.textBoxFind.TabIndex = 1; + this.textBoxFind.Text = ""; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(8, 8); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(100, 24); + this.label1.TabIndex = 1; + this.label1.Text = "Find what:"; + // + // buttonCancel + // + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonCancel.Location = new System.Drawing.Point(264, 40); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.TabIndex = 3; + this.buttonCancel.Text = "Cancel"; + // + // buttonFindNext + // + this.buttonFindNext.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonFindNext.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonFindNext.Location = new System.Drawing.Point(264, 8); + this.buttonFindNext.Name = "buttonFindNext"; + this.buttonFindNext.TabIndex = 2; + this.buttonFindNext.Text = "Find &Next"; + this.buttonFindNext.Click += new System.EventHandler(this.buttonFindNext_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.radioButtonDown); + this.groupBox1.Controls.Add(this.radioButtonUp); + this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox1.Location = new System.Drawing.Point(168, 40); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(88, 72); + this.groupBox1.TabIndex = 6; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Direction"; + // + // radioButtonDown + // + this.radioButtonDown.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.radioButtonDown.Location = new System.Drawing.Point(16, 40); + this.radioButtonDown.Name = "radioButtonDown"; + this.radioButtonDown.Size = new System.Drawing.Size(56, 24); + this.radioButtonDown.TabIndex = 8; + this.radioButtonDown.Text = "Down"; + // + // radioButtonUp + // + this.radioButtonUp.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.radioButtonUp.Location = new System.Drawing.Point(16, 16); + this.radioButtonUp.Name = "radioButtonUp"; + this.radioButtonUp.Size = new System.Drawing.Size(56, 24); + this.radioButtonUp.TabIndex = 7; + this.radioButtonUp.Text = "Up"; + // + // checkBoxMatchWholeWord + // + this.checkBoxMatchWholeWord.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.checkBoxMatchWholeWord.Location = new System.Drawing.Point(8, 40); + this.checkBoxMatchWholeWord.Name = "checkBoxMatchWholeWord"; + this.checkBoxMatchWholeWord.Size = new System.Drawing.Size(128, 24); + this.checkBoxMatchWholeWord.TabIndex = 4; + this.checkBoxMatchWholeWord.Text = "Match whole word"; + // + // checkBoxMatchCase + // + this.checkBoxMatchCase.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.checkBoxMatchCase.Location = new System.Drawing.Point(8, 64); + this.checkBoxMatchCase.Name = "checkBoxMatchCase"; + this.checkBoxMatchCase.Size = new System.Drawing.Size(128, 24); + this.checkBoxMatchCase.TabIndex = 5; + this.checkBoxMatchCase.Text = "Match case"; + // + // FindForm + // + this.AcceptButton = this.buttonFindNext; + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(346, 120); + this.Controls.Add(this.checkBoxMatchCase); + this.Controls.Add(this.checkBoxMatchWholeWord); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.buttonFindNext); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.textBoxFind); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "FindForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Find"; + this.Load += new System.EventHandler(this.FindForm_Load); + this.Activated += new EventHandler(FindForm_Activated); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + #region Form initialization + + /// <summary> + /// Updates controls with the current seach criteria + /// </summary> + private void FindForm_Load(object sender, System.EventArgs e) + { + checkBoxMatchCase.Checked=matchCase; + checkBoxMatchWholeWord.Checked=matchWholeWord; + if (searchDown) radioButtonDown.Checked=true; + else radioButtonUp.Checked=true; + textBoxFind.Text=textFind; + } + + private void FindForm_Activated(object sender, EventArgs e) + { + textBoxFind.Focus(); + } + + #endregion + + #region Control Events + + /// <summary> + /// Closes the form and updates the properties + /// </summary> + private void buttonFindNext_Click(object sender, System.EventArgs e) + { + matchCase=checkBoxMatchCase.Checked; + matchWholeWord=checkBoxMatchWholeWord.Checked; + searchDown=radioButtonDown.Checked; + textFind=textBoxFind.Text; + } + + #endregion + + #region Properties + + /// <summary> + /// Returns true if the search should be case sensitive + /// </summary> + public bool MatchCase + { + get { return matchCase; } + } + + /// <summary> + /// Returns true if the search should match the whole word + /// </summary> + public bool MatchWholeWord + { + get { return matchWholeWord; } + } + + /// <summary> + /// True if the search direction should be down, otherwise false + /// </summary> + public bool SearchDown + { + get { return searchDown; } + } + + /// <summary> + /// Gets the text to be seached for + /// </summary> + public string TextFind + { + get { return textFind; } + } + + #endregion + } +} diff --git a/tools/Translator/Translator/FindForm.resx b/tools/Translator/Translator/FindForm.resx new file mode 100644 index 0000000000..ba62595099 --- /dev/null +++ b/tools/Translator/Translator/FindForm.resx @@ -0,0 +1,220 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="textBoxFind.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxFind.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxFind.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonFindNext.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonFindNext.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonFindNext.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="radioButtonDown.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="radioButtonDown.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="radioButtonDown.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="radioButtonUp.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="radioButtonUp.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="radioButtonUp.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="checkBoxMatchWholeWord.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="checkBoxMatchWholeWord.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="checkBoxMatchWholeWord.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="checkBoxMatchCase.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="checkBoxMatchCase.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="checkBoxMatchCase.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Name"> + <value>FindForm</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/LanguageInfo.cs b/tools/Translator/Translator/LanguageInfo.cs new file mode 100644 index 0000000000..7a25272525 --- /dev/null +++ b/tools/Translator/Translator/LanguageInfo.cs @@ -0,0 +1,419 @@ +using System; +using System.Xml; +using System.Collections; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// Holds language specific settings like date/time format or codepages. + /// </summary> + public class LanguageInfo + { + + public class Region + { + private string dateLong="DDDD, D MMMM YYYY"; + private string dateShort="DD/MM/YYYY"; + private string time="H:mm:ss"; + private string symbolAM=""; + private string symbolPM=""; + private string speedUnit="kmh"; + private string tempUnit="C"; + private string name="(default)"; + + public Region() + { + + } + + public string DateLong + { + get { return dateLong; } + set { dateLong=value; } + } + + public string DateShort + { + get { return dateShort; } + set { dateShort=value; } + } + + public string Time + { + get { return time; } + set { time=value; } + } + + public string SymbolAM + { + get { return symbolAM; } + set { symbolAM=value; } + } + + public string SymbolPM + { + get { return symbolPM; } + set { symbolPM=value; } + } + + public string SpeedUnit + { + get { return speedUnit; } + set { speedUnit=value; } + } + + public string TempUnit + { + get { return tempUnit; } + set { tempUnit=value; } + } + + public string Name + { + get { return name; } + set { name=value; } + } + + public void Load(XmlElement element) + { + if (element.GetAttribute("name")!="") + name=element.GetAttribute("name"); + + XmlNode node=null; + + node=element.SelectSingleNode("dateshort"); + if (node!=null) + dateShort=node.InnerText; + + node=element.SelectSingleNode("datelong"); + if (node!=null) + dateLong=node.InnerText; + + XmlElement timeElement=(XmlElement)element.SelectSingleNode("time"); + if (timeElement!=null) + { + symbolAM=timeElement.GetAttribute("symbolAM"); + symbolPM=timeElement.GetAttribute("symbolPM"); + time=timeElement.InnerText; + } + + node=element.SelectSingleNode("speedunit"); + if (node!=null) + speedUnit=node.InnerText; + + node=element.SelectSingleNode("tempunit"); + if (node!=null) + tempUnit=node.InnerText; + } + + public void Save(ref XmlElement element) + { + if (name!="(default)") + element.SetAttribute("name", name); + XmlElement dateShortElement=element.OwnerDocument.CreateElement("dateshort"); + dateShortElement.InnerText=dateShort; + element.AppendChild(dateShortElement); + + XmlElement dateLongElement=element.OwnerDocument.CreateElement("datelong"); + dateLongElement.InnerText=dateLong; + element.AppendChild(dateLongElement); + + XmlElement timeElement=element.OwnerDocument.CreateElement("time"); + timeElement.InnerText=time; + timeElement.SetAttribute("symbolAM", symbolAM); + timeElement.SetAttribute("symbolPM", symbolPM); + element.AppendChild(timeElement); + + XmlElement tempUnitElement=element.OwnerDocument.CreateElement("tempunit"); + tempUnitElement.InnerText=tempUnit; + element.AppendChild(tempUnitElement); + + XmlElement speedUnitElement=element.OwnerDocument.CreateElement("speedunit"); + speedUnitElement.InnerText=speedUnit; + element.AppendChild(speedUnitElement); + + } + }; + + private string dvdMenu="en"; + private string dvdAudio="en"; + private string dvdSubtitle="en"; + private string charsetGui="CP1251"; + private string charsetSubtitle="CP1251"; + private bool forceUnicodeFont=false; + private ArrayList regions=new ArrayList(); + + public LanguageInfo() + { + // Add a region with default values + regions.Add(new Region()); + } + + /// <summary> + /// Load a language info from filename + /// </summary> + public void Load(string filename) + { + XmlTextReader reader=null; + + try + { + reader=new XmlTextReader(filename); + + XmlDocument doc=new XmlDocument(); + doc.Load(reader); + + XmlNode node=null; + + node=doc.DocumentElement.SelectSingleNode("/language/charsets/gui"); + if (node!=null) + { + XmlElement gui=(XmlElement)node; + charsetGui=gui.InnerText; + forceUnicodeFont=(gui.GetAttribute("unicodefont")=="true"); + } + + node=doc.DocumentElement.SelectSingleNode("/language/charsets/subtitle"); + if (node!=null) + { + charsetSubtitle=node.InnerText; + } + + + node=doc.DocumentElement.SelectSingleNode("/language/dvd/menu"); + if (node!=null) + { + dvdMenu=node.InnerText; + } + + node=doc.DocumentElement.SelectSingleNode("/language/dvd/audio"); + if (node!=null) + { + dvdAudio=node.InnerText; + } + + node=doc.DocumentElement.SelectSingleNode("/language/dvd/subtitle"); + if (node!=null) + { + dvdSubtitle=node.InnerText; + } + + XmlNodeList regionNodes=doc.DocumentElement.SelectNodes("/language/regions/region"); + + if (regionNodes.Count>0) + { + regions.Clear(); // remove default region + + foreach (XmlNode regionNode in regionNodes) + { + Region region=new Region(); + region.Load((XmlElement)regionNode); + regions.Add(region); + } + } + } + catch(Exception e) + { + throw new TranslatorException("Error loading "+filename, e); + } + finally + { + if (reader!=null) + reader.Close(); + } + } + + /// <summary> + /// Save the language info to filename + /// </summary> + public void Save(string filename) + { + XmlTextWriter writer=null; + + try + { + XmlDocument doc=new XmlDocument(); + + doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", "yes")); + + XmlElement root=doc.CreateElement("language"); + doc.AppendChild(root); + + XmlNode charsetsNode=doc.CreateElement("charsets"); + root.AppendChild(charsetsNode); + + XmlElement guiElement=doc.CreateElement("gui"); + guiElement.InnerText=charsetGui; + guiElement.SetAttribute("unicodefont", forceUnicodeFont ? "true" : "false"); + charsetsNode.AppendChild(guiElement); + + XmlNode subtitleNode=doc.CreateElement("subtitle"); + subtitleNode.InnerText=charsetSubtitle; + charsetsNode.AppendChild(subtitleNode); + + XmlNode dvdNode=doc.CreateElement("dvd"); + root.AppendChild(dvdNode); + + XmlNode dvdMenuNode=doc.CreateElement("menu"); + dvdMenuNode.InnerText=dvdMenu; + dvdNode.AppendChild(dvdMenuNode); + + XmlNode dvdAudioNode=doc.CreateElement("audio"); + dvdAudioNode.InnerText=dvdAudio; + dvdNode.AppendChild(dvdAudioNode); + + XmlNode dvdSubtitleNode=doc.CreateElement("subtitle"); + dvdSubtitleNode.InnerText=dvdSubtitle; + dvdNode.AppendChild(dvdSubtitleNode); + + XmlNode regionsNode=doc.CreateElement("regions"); + root.AppendChild(regionsNode); + + foreach (Region region in regions) + { + XmlElement regionNode=doc.CreateElement("region"); + regionsNode.AppendChild(regionNode); + region.Save(ref regionNode); + } + + writer=new XmlTextWriter(filename, System.Text.Encoding.UTF8); + + writer.Formatting=Formatting.Indented; + + doc.Save(writer); + } + catch(Exception e) + { + throw new TranslatorException("Error saving "+filename, e); + } + finally + { + if (writer!=null) + writer.Close(); + } + } + + /// <summary> + /// Gets/Sets the dvd menu language as ISO-639:1988 language code + /// </summary> + public string DvdMenu + { + get { return dvdMenu; } + set { dvdMenu=value; } + } + + /// <summary> + /// Gets/Sets the dvd audio language as ISO-639:1988 language code + /// </summary> + public string DvdAudio + { + get { return dvdAudio; } + set { dvdAudio=value; } + } + + /// <summary> + /// Gets/Sets the dvd subtitle language as ISO-639:1988 language code + /// </summary> + public string DvdSubtitle + { + get { return dvdSubtitle; } + set { dvdSubtitle=value; } + } + + /// <summary> + /// Gets/Sets the charset used for the user interface of xbmc + /// </summary> + public string CharsetGui + { + get { return charsetGui; } + set { charsetGui=value; } + } + + /// <summary> + /// Gets/Sets the default charset used for the subtitles in xbmc + /// </summary> + public string CharsetSubtitle + { + get { return charsetSubtitle; } + set { charsetSubtitle=value; } + } + + /// <summary> + /// Gets/Sets if the language need a unicode font to display properly + /// </summary> + public bool ForceUnicodeFont + { + get { return forceUnicodeFont; } + set { forceUnicodeFont=value; } + } + + /// <summary> + /// Returns the available region, a region contains + /// things like date/time format or speed and temp units + /// </summary> + public Region[] Regions + { + get { return (Region[])regions.ToArray(typeof(Region)); } + } + + /// <summary> + /// Removes a region from the language info by name + /// </summary> + public void RemoveRegion(string regionName) + { + Region toDelete=null; + foreach (Region region in regions) + { + if (region.Name==regionName) + { + // Region to remove is found + toDelete=region; + break; + } + } + + // remove it + if (toDelete!=null) + regions.Remove(toDelete); + } + + /// <summary> + /// Adds a region to the language info. + /// The name of the new region is returned. + /// </summary> + public string AddRegion() + { + int i=1; + string newName=""; + bool found=false; + while (!found) + { + // Try next name + newName="Region"+i.ToString(); + i++; + // Does the new region name already exist + bool exists=false; + foreach (Region region in regions) + { + if (region.Name==newName) + { + exists=true; + break; + } + } + + if (!exists) + { // none existing name found + // add a region with this name + found=true; + Region region=new Region(); + region.Name=newName; + regions.Add(region); + break; + } + } + + return newName; + } + } +} diff --git a/tools/Translator/Translator/LanguageInfoForm.cs b/tools/Translator/Translator/LanguageInfoForm.cs new file mode 100644 index 0000000000..399d40c137 --- /dev/null +++ b/tools/Translator/Translator/LanguageInfoForm.cs @@ -0,0 +1,740 @@ +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Globalization; +using System.IO; +using TeamXBMC.TranslatorCore; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Summary description for LangInfoForm. + /// </summary> + public class LanguageInfoForm : System.Windows.Forms.Form + { + private LanguageInfo languageInfo=new LanguageInfo(); + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.Button buttonRemove; + private System.Windows.Forms.Button buttonAdd; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.GroupBox groupBox5; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.ComboBox comboBoxSubtitle; + private System.Windows.Forms.ComboBox comboBoxGUI; + private System.Windows.Forms.ComboBox comboBoxDvdSubtitle; + private System.Windows.Forms.ComboBox comboBoxDvdAudio; + private System.Windows.Forms.ComboBox comboBoxDvdMenu; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Button buttonCharsetSystemDefault; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Button buttonDvdDefault; + private System.Windows.Forms.Button buttonProperties; + private System.Windows.Forms.GroupBox groupBox6; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.CheckBox checkBoxUnicodeFont; + private System.Windows.Forms.ColumnHeader columnHeaderRegion; + private System.Windows.Forms.ListView listViewRegions; + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.Container components = null; + + public LanguageInfoForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // + // TODO: Add any constructor code after InitializeComponent call + // + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if(components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.buttonOK = new System.Windows.Forms.Button(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.checkBoxUnicodeFont = new System.Windows.Forms.CheckBox(); + this.label10 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.comboBoxSubtitle = new System.Windows.Forms.ComboBox(); + this.label3 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.comboBoxGUI = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.buttonCharsetSystemDefault = new System.Windows.Forms.Button(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.label8 = new System.Windows.Forms.Label(); + this.buttonDvdDefault = new System.Windows.Forms.Button(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.label6 = new System.Windows.Forms.Label(); + this.comboBoxDvdSubtitle = new System.Windows.Forms.ComboBox(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.label5 = new System.Windows.Forms.Label(); + this.comboBoxDvdAudio = new System.Windows.Forms.ComboBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.label4 = new System.Windows.Forms.Label(); + this.comboBoxDvdMenu = new System.Windows.Forms.ComboBox(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.listViewRegions = new System.Windows.Forms.ListView(); + this.columnHeaderRegion = new System.Windows.Forms.ColumnHeader(); + this.label9 = new System.Windows.Forms.Label(); + this.buttonProperties = new System.Windows.Forms.Button(); + this.buttonRemove = new System.Windows.Forms.Button(); + this.buttonAdd = new System.Windows.Forms.Button(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.tabPage1.SuspendLayout(); + this.groupBox6.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.SuspendLayout(); + // + // buttonOK + // + this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonOK.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonOK.Location = new System.Drawing.Point(152, 328); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.TabIndex = 1; + this.buttonOK.Text = "OK"; + this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + // + // tabPage1 + // + this.tabPage1.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.tabPage1.Controls.Add(this.groupBox6); + this.tabPage1.Controls.Add(this.label7); + this.tabPage1.Controls.Add(this.groupBox2); + this.tabPage1.Controls.Add(this.groupBox1); + this.tabPage1.Controls.Add(this.label1); + this.tabPage1.Controls.Add(this.buttonCharsetSystemDefault); + this.tabPage1.ForeColor = System.Drawing.SystemColors.WindowText; + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Size = new System.Drawing.Size(296, 286); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Charsets"; + // + // groupBox6 + // + this.groupBox6.Controls.Add(this.checkBoxUnicodeFont); + this.groupBox6.Controls.Add(this.label10); + this.groupBox6.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox6.Location = new System.Drawing.Point(8, 168); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Size = new System.Drawing.Size(280, 72); + this.groupBox6.TabIndex = 8; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "Font"; + // + // checkBoxUnicodeFont + // + this.checkBoxUnicodeFont.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.checkBoxUnicodeFont.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.checkBoxUnicodeFont.Location = new System.Drawing.Point(120, 48); + this.checkBoxUnicodeFont.Name = "checkBoxUnicodeFont"; + this.checkBoxUnicodeFont.Size = new System.Drawing.Size(120, 16); + this.checkBoxUnicodeFont.TabIndex = 10; + this.checkBoxUnicodeFont.Text = "Force unicode font"; + // + // label10 + // + this.label10.Location = new System.Drawing.Point(8, 16); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(264, 40); + this.label10.TabIndex = 9; + this.label10.Text = "Click if the language needs a unicode font to display properly, eg. the language " + + "has none latin characters."; + // + // label7 + // + this.label7.Location = new System.Drawing.Point(8, 248); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(200, 32); + this.label7.TabIndex = 11; + this.label7.Text = "Use this button to set the charsets from the current local windows settings"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.comboBoxSubtitle); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox2.Location = new System.Drawing.Point(8, 96); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(280, 64); + this.groupBox2.TabIndex = 5; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Subtitle"; + // + // comboBoxSubtitle + // + this.comboBoxSubtitle.ItemHeight = 13; + this.comboBoxSubtitle.Location = new System.Drawing.Point(88, 32); + this.comboBoxSubtitle.Name = "comboBoxSubtitle"; + this.comboBoxSubtitle.Size = new System.Drawing.Size(121, 21); + this.comboBoxSubtitle.Sorted = true; + this.comboBoxSubtitle.TabIndex = 7; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 16); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(224, 23); + this.label3.TabIndex = 6; + this.label3.Text = "Select the charset for subtitles"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.comboBoxGUI); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox1.Location = new System.Drawing.Point(8, 24); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(280, 64); + this.groupBox1.TabIndex = 2; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "User Interface"; + // + // comboBoxGUI + // + this.comboBoxGUI.ItemHeight = 13; + this.comboBoxGUI.Location = new System.Drawing.Point(88, 32); + this.comboBoxGUI.Name = "comboBoxGUI"; + this.comboBoxGUI.Size = new System.Drawing.Size(120, 21); + this.comboBoxGUI.Sorted = true; + this.comboBoxGUI.TabIndex = 4; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 16); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(224, 23); + this.label2.TabIndex = 3; + this.label2.Text = "Select the charset of the user interface"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(8, 8); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(264, 23); + this.label1.TabIndex = 1; + this.label1.Text = "Select the standard charsets for this language"; + // + // buttonCharsetSystemDefault + // + this.buttonCharsetSystemDefault.BackColor = System.Drawing.SystemColors.Control; + this.buttonCharsetSystemDefault.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonCharsetSystemDefault.Location = new System.Drawing.Point(208, 248); + this.buttonCharsetSystemDefault.Name = "buttonCharsetSystemDefault"; + this.buttonCharsetSystemDefault.TabIndex = 12; + this.buttonCharsetSystemDefault.Text = "Default"; + this.buttonCharsetSystemDefault.Click += new System.EventHandler(this.buttonCharsetSystemDefault_Click); + // + // tabPage2 + // + this.tabPage2.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.tabPage2.Controls.Add(this.label8); + this.tabPage2.Controls.Add(this.buttonDvdDefault); + this.tabPage2.Controls.Add(this.groupBox5); + this.tabPage2.Controls.Add(this.groupBox4); + this.tabPage2.Controls.Add(this.groupBox3); + this.tabPage2.ForeColor = System.Drawing.SystemColors.WindowText; + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Size = new System.Drawing.Size(296, 286); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "DVD Language"; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(8, 248); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(200, 32); + this.label8.TabIndex = 10; + this.label8.Text = "Use this button to set the language from the current local windows settings"; + // + // buttonDvdDefault + // + this.buttonDvdDefault.BackColor = System.Drawing.SystemColors.Control; + this.buttonDvdDefault.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonDvdDefault.Location = new System.Drawing.Point(208, 248); + this.buttonDvdDefault.Name = "buttonDvdDefault"; + this.buttonDvdDefault.TabIndex = 11; + this.buttonDvdDefault.Text = "Default"; + this.buttonDvdDefault.Click += new System.EventHandler(this.buttonDvdDefault_Click); + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.label6); + this.groupBox5.Controls.Add(this.comboBoxDvdSubtitle); + this.groupBox5.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox5.Location = new System.Drawing.Point(8, 168); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(280, 72); + this.groupBox5.TabIndex = 7; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "Subtitle"; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(16, 32); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(96, 23); + this.label6.TabIndex = 8; + this.label6.Text = "Language:"; + // + // comboBoxDvdSubtitle + // + this.comboBoxDvdSubtitle.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxDvdSubtitle.ItemHeight = 13; + this.comboBoxDvdSubtitle.Location = new System.Drawing.Point(136, 32); + this.comboBoxDvdSubtitle.Name = "comboBoxDvdSubtitle"; + this.comboBoxDvdSubtitle.Size = new System.Drawing.Size(121, 21); + this.comboBoxDvdSubtitle.Sorted = true; + this.comboBoxDvdSubtitle.TabIndex = 9; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.label5); + this.groupBox4.Controls.Add(this.comboBoxDvdAudio); + this.groupBox4.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox4.ForeColor = System.Drawing.SystemColors.ControlText; + this.groupBox4.Location = new System.Drawing.Point(8, 88); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(280, 72); + this.groupBox4.TabIndex = 4; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Audio"; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(16, 32); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(96, 23); + this.label5.TabIndex = 5; + this.label5.Text = "Language:"; + // + // comboBoxDvdAudio + // + this.comboBoxDvdAudio.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxDvdAudio.ItemHeight = 13; + this.comboBoxDvdAudio.Location = new System.Drawing.Point(136, 32); + this.comboBoxDvdAudio.Name = "comboBoxDvdAudio"; + this.comboBoxDvdAudio.Size = new System.Drawing.Size(121, 21); + this.comboBoxDvdAudio.Sorted = true; + this.comboBoxDvdAudio.TabIndex = 6; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.label4); + this.groupBox3.Controls.Add(this.comboBoxDvdMenu); + this.groupBox3.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox3.ForeColor = System.Drawing.SystemColors.ControlText; + this.groupBox3.Location = new System.Drawing.Point(8, 8); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(280, 72); + this.groupBox3.TabIndex = 1; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Menu"; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(16, 32); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(96, 23); + this.label4.TabIndex = 2; + this.label4.Text = "Language:"; + // + // comboBoxDvdMenu + // + this.comboBoxDvdMenu.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxDvdMenu.ItemHeight = 13; + this.comboBoxDvdMenu.Location = new System.Drawing.Point(136, 32); + this.comboBoxDvdMenu.Name = "comboBoxDvdMenu"; + this.comboBoxDvdMenu.Size = new System.Drawing.Size(121, 21); + this.comboBoxDvdMenu.Sorted = true; + this.comboBoxDvdMenu.TabIndex = 3; + // + // tabPage3 + // + this.tabPage3.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.tabPage3.Controls.Add(this.listViewRegions); + this.tabPage3.Controls.Add(this.label9); + this.tabPage3.Controls.Add(this.buttonProperties); + this.tabPage3.Controls.Add(this.buttonRemove); + this.tabPage3.Controls.Add(this.buttonAdd); + this.tabPage3.ForeColor = System.Drawing.SystemColors.WindowText; + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(296, 286); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Regions"; + // + // listViewRegions + // + this.listViewRegions.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeaderRegion}); + this.listViewRegions.FullRowSelect = true; + this.listViewRegions.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listViewRegions.HideSelection = false; + this.listViewRegions.LabelEdit = true; + this.listViewRegions.Location = new System.Drawing.Point(24, 64); + this.listViewRegions.MultiSelect = false; + this.listViewRegions.Name = "listViewRegions"; + this.listViewRegions.Size = new System.Drawing.Size(160, 184); + this.listViewRegions.Sorting = System.Windows.Forms.SortOrder.Ascending; + this.listViewRegions.TabIndex = 1; + this.listViewRegions.View = System.Windows.Forms.View.Details; + this.listViewRegions.DoubleClick += new System.EventHandler(this.listViewRegions_DoubleClick); + this.listViewRegions.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.listViewRegions_AfterLabelEdit); + // + // columnHeaderRegion + // + this.columnHeaderRegion.Text = "Region"; + this.columnHeaderRegion.Width = 139; + // + // label9 + // + this.label9.Location = new System.Drawing.Point(24, 8); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(248, 48); + this.label9.TabIndex = 0; + this.label9.Text = "If the language can be used in more then one location, but date and time format d" + + "iffers, an addition region can be specified."; + // + // buttonProperties + // + this.buttonProperties.BackColor = System.Drawing.SystemColors.Control; + this.buttonProperties.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonProperties.Location = new System.Drawing.Point(192, 128); + this.buttonProperties.Name = "buttonProperties"; + this.buttonProperties.TabIndex = 4; + this.buttonProperties.Text = "Properties"; + this.buttonProperties.Click += new System.EventHandler(this.buttonProperties_Click); + // + // buttonRemove + // + this.buttonRemove.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonRemove.Location = new System.Drawing.Point(192, 96); + this.buttonRemove.Name = "buttonRemove"; + this.buttonRemove.TabIndex = 3; + this.buttonRemove.Text = "Remove"; + this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click); + // + // buttonAdd + // + this.buttonAdd.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonAdd.Location = new System.Drawing.Point(192, 64); + this.buttonAdd.Name = "buttonAdd"; + this.buttonAdd.TabIndex = 2; + this.buttonAdd.Text = "Add..."; + this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.ItemSize = new System.Drawing.Size(53, 18); + this.tabControl1.Location = new System.Drawing.Point(8, 8); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(304, 312); + this.tabControl1.TabIndex = 0; + // + // buttonCancel + // + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonCancel.Location = new System.Drawing.Point(240, 328); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.TabIndex = 2; + this.buttonCancel.Text = "Cancel"; + // + // LanguageInfoForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.ClientSize = new System.Drawing.Size(322, 360); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.buttonOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "LanguageInfoForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Language Settings"; + this.Load += new System.EventHandler(this.LangInfoForm_Load); + this.tabPage1.ResumeLayout(false); + this.groupBox6.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.groupBox5.ResumeLayout(false); + this.groupBox4.ResumeLayout(false); + this.groupBox3.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + #region Form initialization + + /// <summary> + /// Fills the values of a langinfo file into the tabpages + /// </summary> + private void LangInfoForm_Load(object sender, System.EventArgs e) + { + // Fill comboBoxes with all available codepages and iso dvd languages + CultureInfo[] cultures=CultureInfo.GetCultures(CultureTypes.NeutralCultures); + foreach (CultureInfo info in cultures) + { + if (!comboBoxDvdMenu.Items.Contains(info.TwoLetterISOLanguageName)) + { + comboBoxDvdMenu.Items.Add(info.TwoLetterISOLanguageName); + comboBoxDvdAudio.Items.Add(info.TwoLetterISOLanguageName); + comboBoxDvdSubtitle.Items.Add(info.TwoLetterISOLanguageName); + } + if (info.TextInfo.ANSICodePage>0 && !comboBoxGUI.Items.Contains("CP"+info.TextInfo.ANSICodePage)) + { + comboBoxGUI.Items.Add("CP"+info.TextInfo.ANSICodePage); + comboBoxSubtitle.Items.Add("CP"+info.TextInfo.ANSICodePage); + } + } + + // Load teh langinfo file if it exists + if (File.Exists(Settings.Instance.FilenameLanguageInfo)) + languageInfo.Load(Settings.Instance.FilenameLanguageInfo); + + // Update comboBoxes with the values from langinfo + comboBoxGUI.Text=languageInfo.CharsetGui; + checkBoxUnicodeFont.Checked=languageInfo.ForceUnicodeFont; + comboBoxSubtitle.Text=languageInfo.CharsetSubtitle; + + comboBoxDvdMenu.Text=languageInfo.DvdMenu; + comboBoxDvdAudio.Text=languageInfo.DvdAudio; + comboBoxDvdSubtitle.Text=languageInfo.DvdSubtitle; + + // Fill listbox with region form langinfo + foreach (LanguageInfo.Region region in languageInfo.Regions) + { + listViewRegions.Items.Add(region.Name); + } + + if (listViewRegions.Items.Count>0) + listViewRegions.Items[0].Selected=true; + } + + #endregion + + #region Control events + + private void buttonOK_Click(object sender, System.EventArgs e) + { + languageInfo.CharsetGui=comboBoxGUI.Text; + languageInfo.ForceUnicodeFont=checkBoxUnicodeFont.Checked; + languageInfo.CharsetSubtitle=comboBoxSubtitle.Text; + + languageInfo.DvdMenu=comboBoxDvdMenu.Text; + languageInfo.DvdAudio=comboBoxDvdAudio.Text; + languageInfo.DvdSubtitle=comboBoxDvdSubtitle.Text; + + languageInfo.Save(Settings.Instance.FilenameLanguageInfo); + } + + /// <summary> + /// Sets the Windows default codepage for gui and subtitles + /// </summary> + private void buttonCharsetSystemDefault_Click(object sender, System.EventArgs e) + { + CultureInfo culture=CultureInfo.CurrentCulture; + comboBoxSubtitle.SelectedItem="CP"+culture.TextInfo.ANSICodePage; + comboBoxGUI.SelectedItem="CP"+culture.TextInfo.ANSICodePage; + } + + /// <summary> + /// Sets the Windows default ISO-639:1988 language code for dvd language + /// </summary> + private void buttonDvdDefault_Click(object sender, System.EventArgs e) + { + CultureInfo culture=CultureInfo.CurrentCulture; + comboBoxDvdMenu.SelectedItem=culture.TwoLetterISOLanguageName; + comboBoxDvdAudio.SelectedItem=culture.TwoLetterISOLanguageName; + comboBoxDvdSubtitle.SelectedItem=culture.TwoLetterISOLanguageName; + } + + /// <summary> + /// Remove a region to the listView + /// </summary> + private void buttonAdd_Click(object sender, System.EventArgs e) + { + if (listViewRegions.SelectedItems.Count>0) + { + string newRegion=languageInfo.AddRegion(); + listViewRegions.Items.Add(newRegion); + + // Find the new item + foreach (ListViewItem item in listViewRegions.Items) + { + if (item.Text==newRegion) + { // and select it + item.Selected=true; + break; + } + } + } + } + + /// <summary> + /// Remove a region from the listView + /// </summary> + private void buttonRemove_Click(object sender, System.EventArgs e) + { + if (listViewRegions.SelectedItems.Count>0) + { + string regionName=listViewRegions.SelectedItems[0].Text; + languageInfo.RemoveRegion(regionName); + + int lastPos=listViewRegions.SelectedIndices[0]; + listViewRegions.Items.RemoveAt(lastPos); + + if (listViewRegions.Items.Count>0) + { + // new selected item out of range? + if (lastPos>listViewRegions.Items.Count-1) + lastPos--; + + listViewRegions.Items[lastPos].Selected=true; + } + } + + if (listViewRegions.Items.Count==0) + { // no regions left, add a default region + string newRegion=languageInfo.AddRegion(); + listViewRegions.Items.Add(newRegion); + listViewRegions.Items[0].Selected=true; + } + } + + /// <summary> + /// Shows a form to edit the selected region + /// </summary> + private void buttonProperties_Click(object sender, System.EventArgs e) + { + foreach (LanguageInfo.Region region in languageInfo.Regions) + { + if (region.Name==listViewRegions.SelectedItems[0].Text) + { + RegionForm form=new RegionForm(); + form.RegionInfo=region; + form.ShowDialog(); + return; + } + } + } + + /// <summary> + /// Shows a form to edit the selected region + /// </summary> + private void listViewRegions_DoubleClick(object sender, System.EventArgs e) + { + foreach (LanguageInfo.Region region in languageInfo.Regions) + { + if (region.Name==listViewRegions.SelectedItems[0].Text) + { + RegionForm form=new RegionForm(); + form.RegionInfo=region; + form.ShowDialog(); + return; + } + } + } + + /// <summary> + /// Changes the name of a region + /// </summary> + private void listViewRegions_AfterLabelEdit(object sender, LabelEditEventArgs e) + { + if (e.Label==null) // user pressed esc key + { + e.CancelEdit=true; + return; + } + + // Does the new name exist + foreach (LanguageInfo.Region region in languageInfo.Regions) + { + if (region.Name==e.Label) + { + e.CancelEdit=true; + return; + } + } + + // Find the item the user renames and set the new region name + foreach (LanguageInfo.Region region in languageInfo.Regions) + { + if (region.Name==listViewRegions.Items[e.Item].Text) + { + region.Name=e.Label; + return; + } + } + + // Region not found + e.CancelEdit=true; + } + + #endregion + } +} diff --git a/tools/Translator/Translator/LanguageInfoForm.resx b/tools/Translator/Translator/LanguageInfoForm.resx new file mode 100644 index 0000000000..e3c1934865 --- /dev/null +++ b/tools/Translator/Translator/LanguageInfoForm.resx @@ -0,0 +1,532 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="buttonOK.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonOK.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonOK.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox6.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox6.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox6.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox6.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox6.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox6.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="checkBoxUnicodeFont.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="checkBoxUnicodeFont.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="checkBoxUnicodeFont.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label10.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label10.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label10.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label7.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label7.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label7.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox2.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox2.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox2.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxSubtitle.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxSubtitle.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="comboBoxSubtitle.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxGUI.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxGUI.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="comboBoxGUI.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCharsetSystemDefault.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonCharsetSystemDefault.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCharsetSystemDefault.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage2.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage2.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage2.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="label8.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label8.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label8.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonDvdDefault.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonDvdDefault.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonDvdDefault.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox5.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox5.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox5.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox5.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox5.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox5.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label6.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label6.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label6.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxDvdSubtitle.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxDvdSubtitle.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="comboBoxDvdSubtitle.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox4.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox4.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox4.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox4.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label5.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label5.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label5.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxDvdAudio.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxDvdAudio.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxDvdAudio.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox3.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox3.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox3.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label4.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxDvdMenu.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxDvdMenu.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="comboBoxDvdMenu.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage3.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage3.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="listViewRegions.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="listViewRegions.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="listViewRegions.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeaderRegion.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeaderRegion.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label9.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label9.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label9.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonProperties.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonProperties.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonProperties.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonRemove.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonRemove.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonRemove.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonAdd.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonAdd.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonAdd.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabControl1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabControl1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabControl1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.Name"> + <value>LanguageInfoForm</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/ListViewItemString.cs b/tools/Translator/Translator/ListViewItemString.cs new file mode 100644 index 0000000000..74bb997618 --- /dev/null +++ b/tools/Translator/Translator/ListViewItemString.cs @@ -0,0 +1,28 @@ +using System; +using System.Windows.Forms; +using TeamXBMC.TranslatorCore; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Summary description for ListViewItemString. + /// </summary> + public sealed class ListViewItemString : ListViewItem + { + public ListViewItemString(TranslatorItem item) + { + Text=item.StringTranslated.Id.ToString(); + SubItems.Add(item.StringTranslated.Text); + SubItems.Add(item.StringOriginal.Text); + item.StringTranslated.stringUpdated+=new StringItem.StringUpdatedDelegate(StringUpdated); + } + + /// <summary> + /// Is called when the string a ListViewItemString represents is changed + /// </summary> + private void StringUpdated(StringItem item) + { + SubItems[1].Text=item.Text; + } + } +} diff --git a/tools/Translator/Translator/MainForm.cs b/tools/Translator/Translator/MainForm.cs new file mode 100644 index 0000000000..eedb74d1f7 --- /dev/null +++ b/tools/Translator/Translator/MainForm.cs @@ -0,0 +1,1084 @@ +using System; +using System.Drawing; +using System.ComponentModel; +using System.Windows.Forms; +using System.IO; +using TeamXBMC.TranslatorCore; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Main form of the application. + /// </summary> + public sealed class MainForm : System.Windows.Forms.Form + { + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.MainMenu mainMenu1; + private System.Windows.Forms.MenuItem menuItemExit; + private System.Windows.Forms.MenuItem menuItemFile; + private System.Windows.Forms.MenuItem menuItem1; + private System.Windows.Forms.MenuItem menuItemAbout; + private System.Windows.Forms.MenuItem menuItem3; + private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1; + private System.Windows.Forms.MenuItem menuItemSave; + private System.Windows.Forms.MenuItem menuItem4; + private System.Windows.Forms.MenuItem menuItem2; + private System.Windows.Forms.ListView listView2; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ListView listView3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ColumnHeader String; + private System.Windows.Forms.ColumnHeader Original; + private System.Windows.Forms.ColumnHeader StingId; + private System.Windows.Forms.MenuItem menuItemOpen; + private System.Windows.Forms.MenuItem menuItemLanguageFolder; + private System.Windows.Forms.MenuItem menuItemEdit; + private System.Windows.Forms.MenuItem menuItemFind; + private System.ComponentModel.IContainer components=null; + private System.Windows.Forms.MenuItem menuItemFindNext; + private System.Windows.Forms.MenuItem menuItemLanguageInfo; + private System.Windows.Forms.MenuItem menuItem6; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private System.Windows.Forms.MenuItem menuItemConvert; + private System.Windows.Forms.SaveFileDialog saveFileDialog1; + private System.Windows.Forms.MenuItem menuItemUserName; + private System.Windows.Forms.MenuItem menuItemNew; + private System.Windows.Forms.MenuItem menuItem7; + private System.Windows.Forms.MenuItem menuItemOptions; + private System.Windows.Forms.MenuItem menuItemTools; + private System.Windows.Forms.MenuItem menuItemValidate; + private System.Windows.Forms.MenuItem menuItemHelp; + private System.Windows.Forms.MenuItem menuItem8; + private FindForm findForm=new FindForm(); + + public MainForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // + // TODO: Add any constructor code after InitializeComponent call + // + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(MainForm)); + this.listView1 = new System.Windows.Forms.ListView(); + this.StingId = new System.Windows.Forms.ColumnHeader(); + this.String = new System.Windows.Forms.ColumnHeader(); + this.Original = new System.Windows.Forms.ColumnHeader(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.listView2 = new System.Windows.Forms.ListView(); + this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader3 = new System.Windows.Forms.ColumnHeader(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.listView3 = new System.Windows.Forms.ListView(); + this.columnHeader4 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader5 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader6 = new System.Windows.Forms.ColumnHeader(); + this.mainMenu1 = new System.Windows.Forms.MainMenu(); + this.menuItemFile = new System.Windows.Forms.MenuItem(); + this.menuItemNew = new System.Windows.Forms.MenuItem(); + this.menuItem7 = new System.Windows.Forms.MenuItem(); + this.menuItemOpen = new System.Windows.Forms.MenuItem(); + this.menuItem2 = new System.Windows.Forms.MenuItem(); + this.menuItemSave = new System.Windows.Forms.MenuItem(); + this.menuItem4 = new System.Windows.Forms.MenuItem(); + this.menuItemLanguageFolder = new System.Windows.Forms.MenuItem(); + this.menuItem3 = new System.Windows.Forms.MenuItem(); + this.menuItemExit = new System.Windows.Forms.MenuItem(); + this.menuItemEdit = new System.Windows.Forms.MenuItem(); + this.menuItemFind = new System.Windows.Forms.MenuItem(); + this.menuItemFindNext = new System.Windows.Forms.MenuItem(); + this.menuItem6 = new System.Windows.Forms.MenuItem(); + this.menuItemLanguageInfo = new System.Windows.Forms.MenuItem(); + this.menuItemOptions = new System.Windows.Forms.MenuItem(); + this.menuItemUserName = new System.Windows.Forms.MenuItem(); + this.menuItemTools = new System.Windows.Forms.MenuItem(); + this.menuItemValidate = new System.Windows.Forms.MenuItem(); + this.menuItemConvert = new System.Windows.Forms.MenuItem(); + this.menuItem1 = new System.Windows.Forms.MenuItem(); + this.menuItemHelp = new System.Windows.Forms.MenuItem(); + this.menuItem8 = new System.Windows.Forms.MenuItem(); + this.menuItemAbout = new System.Windows.Forms.MenuItem(); + this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog(); + this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); + this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.SuspendLayout(); + // + // listView1 + // + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.StingId, + this.String, + this.Original}); + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView1.HideSelection = false; + this.listView1.LabelWrap = false; + this.listView1.Location = new System.Drawing.Point(0, 0); + this.listView1.MultiSelect = false; + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(696, 360); + this.listView1.TabIndex = 0; + this.listView1.View = System.Windows.Forms.View.Details; + this.listView1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.listView_KeyPress); + this.listView1.DoubleClick += new System.EventHandler(this.listView_DoubleClick); + // + // StingId + // + this.StingId.Text = "String Id"; + this.StingId.Width = 59; + // + // String + // + this.String.Text = "String"; + this.String.Width = 308; + // + // Original + // + this.Original.Text = "Original"; + this.Original.Width = 308; + // + // tabControl1 + // + this.tabControl1.Appearance = System.Windows.Forms.TabAppearance.FlatButtons; + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.ItemSize = new System.Drawing.Size(55, 21); + this.tabControl1.Location = new System.Drawing.Point(8, 8); + this.tabControl1.Multiline = true; + this.tabControl1.Name = "tabControl1"; + this.tabControl1.RightToLeft = System.Windows.Forms.RightToLeft.No; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(704, 392); + this.tabControl1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.BackColor = System.Drawing.SystemColors.Control; + this.tabPage1.Controls.Add(this.listView1); + this.tabPage1.Location = new System.Drawing.Point(4, 25); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Size = new System.Drawing.Size(696, 363); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "All Strings"; + // + // tabPage2 + // + this.tabPage2.BackColor = System.Drawing.SystemColors.Control; + this.tabPage2.Controls.Add(this.listView2); + this.tabPage2.Location = new System.Drawing.Point(4, 25); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Size = new System.Drawing.Size(696, 363); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Untranslated"; + // + // listView2 + // + this.listView2.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.listView2.FullRowSelect = true; + this.listView2.GridLines = true; + this.listView2.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView2.HideSelection = false; + this.listView2.LabelWrap = false; + this.listView2.Location = new System.Drawing.Point(0, 0); + this.listView2.MultiSelect = false; + this.listView2.Name = "listView2"; + this.listView2.Size = new System.Drawing.Size(696, 360); + this.listView2.TabIndex = 1; + this.listView2.View = System.Windows.Forms.View.Details; + this.listView2.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.listView_KeyPress); + this.listView2.DoubleClick += new System.EventHandler(this.listView_DoubleClick); + // + // columnHeader1 + // + this.columnHeader1.Text = "String Id"; + this.columnHeader1.Width = 59; + // + // columnHeader2 + // + this.columnHeader2.Text = "String"; + this.columnHeader2.Width = 308; + // + // columnHeader3 + // + this.columnHeader3.Text = "Original"; + this.columnHeader3.Width = 308; + // + // tabPage3 + // + this.tabPage3.BackColor = System.Drawing.SystemColors.Control; + this.tabPage3.Controls.Add(this.listView3); + this.tabPage3.Location = new System.Drawing.Point(4, 25); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(696, 363); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Changed"; + // + // listView3 + // + this.listView3.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader4, + this.columnHeader5, + this.columnHeader6}); + this.listView3.FullRowSelect = true; + this.listView3.GridLines = true; + this.listView3.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView3.HideSelection = false; + this.listView3.LabelWrap = false; + this.listView3.Location = new System.Drawing.Point(0, 0); + this.listView3.MultiSelect = false; + this.listView3.Name = "listView3"; + this.listView3.Size = new System.Drawing.Size(696, 360); + this.listView3.TabIndex = 1; + this.listView3.View = System.Windows.Forms.View.Details; + this.listView3.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.listView_KeyPress); + this.listView3.DoubleClick += new System.EventHandler(this.listView_DoubleClick); + // + // columnHeader4 + // + this.columnHeader4.Text = "String Id"; + this.columnHeader4.Width = 59; + // + // columnHeader5 + // + this.columnHeader5.Text = "String"; + this.columnHeader5.Width = 308; + // + // columnHeader6 + // + this.columnHeader6.Text = "Original"; + this.columnHeader6.Width = 308; + // + // mainMenu1 + // + this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItemFile, + this.menuItemEdit, + this.menuItemOptions, + this.menuItemTools, + this.menuItem1}); + // + // menuItemFile + // + this.menuItemFile.Index = 0; + this.menuItemFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItemNew, + this.menuItem7, + this.menuItemOpen, + this.menuItem2, + this.menuItemSave, + this.menuItem4, + this.menuItemLanguageFolder, + this.menuItem3, + this.menuItemExit}); + this.menuItemFile.Text = "&File"; + // + // menuItemNew + // + this.menuItemNew.Index = 0; + this.menuItemNew.Shortcut = System.Windows.Forms.Shortcut.CtrlN; + this.menuItemNew.Text = "&New Language..."; + this.menuItemNew.Click += new System.EventHandler(this.menuItemNew_Click); + // + // menuItem7 + // + this.menuItem7.Index = 1; + this.menuItem7.Text = "-"; + // + // menuItemOpen + // + this.menuItemOpen.Index = 2; + this.menuItemOpen.Shortcut = System.Windows.Forms.Shortcut.CtrlO; + this.menuItemOpen.Text = "&Open Language..."; + this.menuItemOpen.Click += new System.EventHandler(this.menuItemOpen_Click); + // + // menuItem2 + // + this.menuItem2.Index = 3; + this.menuItem2.Text = "-"; + // + // menuItemSave + // + this.menuItemSave.Index = 4; + this.menuItemSave.Shortcut = System.Windows.Forms.Shortcut.CtrlS; + this.menuItemSave.Text = "&Save"; + this.menuItemSave.Click += new System.EventHandler(this.menuItemSave_Click); + // + // menuItem4 + // + this.menuItem4.Index = 5; + this.menuItem4.Text = "-"; + // + // menuItemLanguageFolder + // + this.menuItemLanguageFolder.Index = 6; + this.menuItemLanguageFolder.Text = "Set &Language Folder..."; + this.menuItemLanguageFolder.Click += new System.EventHandler(this.menuItemLanguageFolder_Click); + // + // menuItem3 + // + this.menuItem3.Index = 7; + this.menuItem3.Text = "-"; + // + // menuItemExit + // + this.menuItemExit.Index = 8; + this.menuItemExit.Shortcut = System.Windows.Forms.Shortcut.AltF4; + this.menuItemExit.Text = "&Exit"; + this.menuItemExit.Click += new System.EventHandler(this.menuItemExit_Click); + // + // menuItemEdit + // + this.menuItemEdit.Index = 1; + this.menuItemEdit.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItemFind, + this.menuItemFindNext, + this.menuItem6, + this.menuItemLanguageInfo}); + this.menuItemEdit.Text = "&Edit"; + // + // menuItemFind + // + this.menuItemFind.Index = 0; + this.menuItemFind.Shortcut = System.Windows.Forms.Shortcut.CtrlF; + this.menuItemFind.Text = "&Find..."; + this.menuItemFind.Click += new System.EventHandler(this.menuItemFind_Click); + // + // menuItemFindNext + // + this.menuItemFindNext.Enabled = false; + this.menuItemFindNext.Index = 1; + this.menuItemFindNext.Shortcut = System.Windows.Forms.Shortcut.F3; + this.menuItemFindNext.Text = "Find &Next"; + this.menuItemFindNext.Click += new System.EventHandler(this.menuItemFindNext_Click); + // + // menuItem6 + // + this.menuItem6.Index = 2; + this.menuItem6.Text = "-"; + // + // menuItemLanguageInfo + // + this.menuItemLanguageInfo.Index = 3; + this.menuItemLanguageInfo.Text = "Language &Settings..."; + this.menuItemLanguageInfo.Click += new System.EventHandler(this.menuItemLanguageInfo_Click); + // + // menuItemOptions + // + this.menuItemOptions.Index = 2; + this.menuItemOptions.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItemUserName}); + this.menuItemOptions.Text = "&Options"; + // + // menuItemUserName + // + this.menuItemUserName.Index = 0; + this.menuItemUserName.Text = "&Translator Name..."; + this.menuItemUserName.Click += new System.EventHandler(this.menuItemUserName_Click); + // + // menuItemTools + // + this.menuItemTools.Index = 3; + this.menuItemTools.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItemValidate, + this.menuItemConvert}); + this.menuItemTools.Text = "&Tools"; + // + // menuItemValidate + // + this.menuItemValidate.Index = 0; + this.menuItemValidate.Text = "&Validate Language File..."; + this.menuItemValidate.Click += new System.EventHandler(this.menuItemValidateFile_Click); + // + // menuItemConvert + // + this.menuItemConvert.Index = 1; + this.menuItemConvert.Text = "&Convert Language File..."; + this.menuItemConvert.Click += new System.EventHandler(this.menuItemConvert_Click); + // + // menuItem1 + // + this.menuItem1.Index = 4; + this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItemHelp, + this.menuItem8, + this.menuItemAbout}); + this.menuItem1.Text = "&?"; + // + // menuItemHelp + // + this.menuItemHelp.Index = 0; + this.menuItemHelp.Text = "&Help..."; + this.menuItemHelp.Click += new System.EventHandler(this.menuItemHelp_Click); + // + // menuItem8 + // + this.menuItem8.Index = 1; + this.menuItem8.Text = "-"; + // + // menuItemAbout + // + this.menuItemAbout.Index = 2; + this.menuItemAbout.Text = "&About..."; + this.menuItemAbout.Click += new System.EventHandler(this.menuItemAbout_Click); + // + // openFileDialog1 + // + this.openFileDialog1.DefaultExt = "xml"; + this.openFileDialog1.FileName = "strings.xml"; + this.openFileDialog1.Filter = "Language File|strings.xml|All Files|*.*"; + this.openFileDialog1.Title = "Choose the language file"; + // + // saveFileDialog1 + // + this.saveFileDialog1.FileName = "strings.xml"; + this.saveFileDialog1.Filter = "Language File|strings.xml|All Files|*.*"; + this.saveFileDialog1.Title = "Save converted file as"; + // + // MainForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.ClientSize = new System.Drawing.Size(722, 411); + this.Controls.Add(this.tabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.Menu = this.mainMenu1; + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Team XBMC Translator"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.Closing +=new CancelEventHandler(MainForm_Closing); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + #region Application initialization + /// <summary> + /// The main entry point for the application. + /// </summary> + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.DoEvents(); + Application.Run(new MainForm()); + } + #endregion + + #region Form initialization + + /// <summary> + /// Loaded the last edited language, if any + /// </summary> + private void MainForm_Load(object sender, System.EventArgs e) + { + Initialize(); + } + + /// <summary> + /// Check if we have to save the language file + /// </summary> + private void MainForm_Closing(object sender, CancelEventArgs e) + { + DialogResult result=ShouldSaveLanguageFile(); + if (result==DialogResult.Yes) + SaveLanguageFile(); + else if (result==DialogResult.Cancel) + e.Cancel=true; + } + + /// <summary> + /// Initializes the user interface + /// </summary> + private bool Initialize() + { + try + { + // disable menu items that are unsave + // in an undefined state + EnableMenuItems(false); + + // Reset the form + Reset(); + + // Tell the TranslationManager to load the currently selected + // language + TranslationManager.Instance.Initialize(); + } + catch (TranslatorException e) + { + Settings.Instance.Language=""; // Failed to load language, remove the current one + ShowMessageBox(BuildErrorMessageText(e), MessageBoxIcon.Error); + return false; + } + + // Fill listView with strings + UpdateListViews(); + + if (Settings.Instance.Language=="" && Settings.Instance.LanguageFolder=="") + { // No language folder and language available, disable menuItemNew + menuItemNew.Enabled=false; + } + else + { // Everything is fine enable all menuItems + EnableMenuItems(true); + } + + return true; + } + + /// <summary> + /// Resets the user interface + /// </summary> + private void Reset() + { + ClearListView(listView1); + ClearListView(listView2); + ClearListView(listView3); + + EnableMenuItems(false); + } + + /// <summary> + /// Disables/enalbes the menu items + /// </summary> + void EnableMenuItems(bool enabled) + { + menuItemNew.Enabled=true; + menuItemSave.Enabled=enabled; + + menuItemLanguageInfo.Enabled=enabled; + menuItemFind.Enabled=enabled; + menuItemFindNext.Enabled=false; + } + + #endregion + + #region Error presentation + + /// <summary> + /// Shows a predefined error message box + /// </summary> + private void ShowMessageBox(string message, MessageBoxIcon icon) + { + MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, icon); + } + + /// <summary> + /// Construct an error message text from a TranslatorException + /// </summary> + private string BuildErrorMessageText(TranslatorException exception) + { + string message="The following error occured:\n"; + message+=exception.Message; + if (exception.InnerException!=null) + { + message+="\nAdditional Info:\n"; + message+=exception.InnerException.Message; + } + + return message; + } + + #endregion + + #region List View control + + /// <summary> + /// Update all listviews with its strings + /// </summary> + private void UpdateListViews() + { + UpdateListView(listView1, TranslationManager.Instance.All); + UpdateListView(listView2, TranslationManager.Instance.Untranslated); + UpdateListView(listView3, TranslationManager.Instance.Changed); + } + + /// <summary> + /// Update a listview with its strings + /// </summary> + private void UpdateListView(ListView listView, TranslatorArray strings) + { + listView.Columns[1].Text=TranslationManager.Instance.LanguageTranslated; + listView.Columns[2].Text=TranslationManager.Instance.LanguageOriginal; + + foreach (TranslatorItem item in strings) + { + listView.Items.Add(new ListViewItemString(item)); + } + } + + /// <summary> + /// Removes items from a listview + /// </summary> + private void ClearListView(ListView listView) + { + listView.Items.Clear(); + } + + /// <summary> + /// Shows the EditStringForm when a listview is double clicked + /// </summary> + void listView_DoubleClick(object sender, System.EventArgs e) + { + ShowEditForm((ListView)sender); + } + + /// <summary> + /// Shows the EditStringForm when enter is pressed in a listview + /// </summary> + void listView_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar==(char)13) + { + ShowEditForm((ListView)sender); + } + } + + /// <summary> + /// Shows the EditStringForm for a certain listview + /// </summary> + void ShowEditForm(ListView listView) + { + if (listView.SelectedItems.Count>0) + { + ListViewItem item=listView.SelectedItems[0]; + long stringId=Convert.ToInt32(item.SubItems[0].Text); + + EditStringForm form=new EditStringForm(); + form.Translated=item.SubItems[1].Text; + form.Original=item.SubItems[2].Text; + if (form.ShowDialog(this)==DialogResult.Cancel) + return; + + TranslatorItem translatorItem=null; + TranslationManager.Instance.All.GetItemById(stringId, ref translatorItem); + + if (translatorItem==null) + return; + + if (form.Translated=="") + translatorItem.State=TranslationState.Untranslated; + else + translatorItem.State=TranslationState.Translated; + + translatorItem.StringTranslated.Text=form.Translated; + } + } + + #endregion + + #region Menu Item Handler File + + /// <summary> + /// Creates a new language + /// </summary> + private void menuItemNew_Click(object sender, System.EventArgs e) + { + if (Settings.Instance.LanguageFolder=="" && !ShowFolderBrowser()) + return; + + DialogResult result=ShouldSaveLanguageFile(); + if (result==DialogResult.Yes) + SaveLanguageFile(); + else if (result==DialogResult.Cancel) + return; + + NewLanguageForm form=new NewLanguageForm(); + if (form.ShowDialog()==DialogResult.Cancel) + return; + + try + { + TranslationManager.Instance.CreateLanguage(form.LanguageName); + } + catch (TranslatorException ex) + { + ShowMessageBox(BuildErrorMessageText(ex), MessageBoxIcon.Error); + return; + } + + Settings.Instance.Language=form.LanguageName; + Initialize(); + } + + /// <summary> + /// Opens a language + /// </summary> + private void menuItemOpen_Click(object sender, System.EventArgs e) + { + if (Settings.Instance.LanguageFolder=="" && !ShowFolderBrowser()) + return; + + DialogResult result=ShouldSaveLanguageFile(); + if (result==DialogResult.Yes) + SaveLanguageFile(); + else if (result==DialogResult.Cancel) + return; + + ChooseLanguageForm form=new ChooseLanguageForm(); + if (form.ShowDialog()==DialogResult.Cancel) + return; + + Initialize(); + } + + /// <summary> + /// Opens a folder browser to choose the language folder. + /// It also tests if the folder selected contains the english folder, + /// if not it will prompt again. Returns false if the user cancels out. + /// </summary> + private bool ShowFolderBrowser() + { + folderBrowserDialog1.Description="Please choose the root folder where your language files are located. This folder needs at least the english language folder."; + folderBrowserDialog1.SelectedPath=Settings.Instance.LanguageFolder; + folderBrowserDialog1.ShowNewFolderButton=false; + + if (folderBrowserDialog1.ShowDialog()!=DialogResult.Cancel) + { + Settings.Instance.LanguageFolder=folderBrowserDialog1.SelectedPath; + if (!File.Exists(Settings.Instance.FilenameOriginal)) + { + Settings.Instance.LanguageFolder=""; + ShowMessageBox("The english language folder was not found in this directory.\nPlease choose another folder.", MessageBoxIcon.Error); + return ShowFolderBrowser(); + } + + return true; + } + + return false; + } + + /// <summary> + /// Saves the language file + /// </summary> + private void menuItemSave_Click(object sender, System.EventArgs e) + { + SaveLanguageFile(); + } + + /// <summary> + /// Asks the user if he wants to save the language file is it's modified + /// </summary> + private DialogResult ShouldSaveLanguageFile() + { + if (TranslationManager.Instance.IsModified) + { + string message="The language file has been modified.\n\nSave changes?"; + return MessageBox.Show(message, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); + } + + return DialogResult.No; + } + + /// <summary> + /// Saves the active language file + /// </summary> + private void SaveLanguageFile() + { + try + { + TranslationManager.Instance.SaveTranslated(); + } + catch (TranslatorException ex) + { + ShowMessageBox(BuildErrorMessageText(ex), MessageBoxIcon.Error); + } + } + + /// <summary> + /// Sets the language folder + /// </summary> + private void menuItemLanguageFolder_Click(object sender, System.EventArgs e) + { + DialogResult result=ShouldSaveLanguageFile(); + if (result==DialogResult.Yes) + SaveLanguageFile(); + else if (result==DialogResult.Cancel) + return; + + if (ShowFolderBrowser()) + Initialize(); + } + + /// <summary> + /// Exits the application + /// </summary> + private void menuItemExit_Click(object sender, System.EventArgs e) + { + DialogResult result=ShouldSaveLanguageFile(); + if (result==DialogResult.Yes) + SaveLanguageFile(); + else if (result==DialogResult.Cancel) + return; + + Application.Exit(); + } + + #endregion + + #region Menu Item Handler Edit + + /// <summary> + /// Edits the langinfo of the current language + /// </summary> + private void menuItemLanguageInfo_Click(object sender, System.EventArgs e) + { + try + { + LanguageInfoForm form=new LanguageInfoForm(); + form.ShowDialog(); + } + catch(TranslatorException ex) + { + ShowMessageBox(BuildErrorMessageText(ex), MessageBoxIcon.Error); + } + } + + /// <summary> + /// Shows the FindForm to search in the active listView + /// </summary> + private void menuItemFind_Click(object sender, System.EventArgs e) + { + findForm.ShowDialog(); + if (findForm.DialogResult==DialogResult.Cancel) + return; + + menuItemFindNext_Click(sender, e); + + menuItemFindNext.Enabled=true; + } + + /// <summary> + /// Searches the active listView for the search criteria set with + /// the FindForm. + /// </summary> + private void menuItemFindNext_Click(object sender, System.EventArgs e) + { + ListView listView=null; + if (tabControl1.SelectedIndex==0) + listView=listView1; + else if (tabControl1.SelectedIndex==1) + listView=listView2; + else + listView=listView3; + + if (listView==null) + return; + + int startIndex=0; + if (listView.SelectedIndices.Count>0) + startIndex=listView.SelectedIndices[0]+1; + + string findText=findForm.MatchCase ? findForm.TextFind : findForm.TextFind.ToLower(); + + bool found=false; + for (int i=startIndex; findForm.SearchDown ? i<listView.Items.Count : i>=0; i+=findForm.SearchDown ? 1 : -1) + { + ListViewItem item=listView.Items[i]; + foreach (ListViewItem.ListViewSubItem subItem in item.SubItems) + { + string text=findForm.MatchCase ? subItem.Text : subItem.Text.ToLower(); + + int pos=text.IndexOf(findText); + if (pos>-1) + { + if (findForm.MatchWholeWord) + { + if (pos==0 && findText.Length==text.Length) + { + if (text!=findText) + continue; + } + else if (pos==0) + { + if (Char.IsLetterOrDigit(text[pos+findText.Length])) + continue; + } + else if (pos>0) + { + if (Char.IsLetterOrDigit(text[pos-1])) + continue; + + if (text.Length>pos+findText.Length) + { + if (Char.IsLetterOrDigit(text[pos+findText.Length])) + continue; + } + } + } + item.Selected=true; + item.EnsureVisible(); + found=true; + break; + } + } + + if (found) + break; + } + + if (!found) + { + ShowMessageBox("\""+findForm.TextFind+"\" was not found.", MessageBoxIcon.Information); + } + + } + + #endregion + + #region Menu Item Handler Options + + /// <summary> + /// Shows the UserForm where the name and email of the translator can be set + /// </summary> + private void menuItemUserName_Click(object sender, System.EventArgs e) + { + UserForm form=new UserForm(); + form.ShowDialog(); + } + + #endregion + + #region Menu Item Handler Tools + + /// <summary> + /// Checks if a language file is valid + /// </summary> + private void menuItemValidateFile_Click(object sender, System.EventArgs e) + { + openFileDialog1.InitialDirectory=Settings.Instance.LanguageFolder; + if (openFileDialog1.ShowDialog()==DialogResult.Cancel) + return; + + StringArray strings=new StringArray(); + + try + { + strings.Load(openFileDialog1.FileName); + } + catch(TranslatorException ex) + { + ShowMessageBox(BuildErrorMessageText(ex), MessageBoxIcon.Error); + return; + } + + ShowMessageBox("The file " + openFileDialog1.FileName + " is valid.", MessageBoxIcon.Information); + } + + /// <summary> + /// Converts a language file to the new format + /// </summary> + private void menuItemConvert_Click(object sender, System.EventArgs e) + { + openFileDialog1.InitialDirectory=Settings.Instance.LanguageFolder; + if (openFileDialog1.ShowDialog()==DialogResult.Cancel) + return; + + StringArray strings=new StringArray(); + + try + { + strings.Load(openFileDialog1.FileName); + } + catch(TranslatorException ex) + { + ShowMessageBox(BuildErrorMessageText(ex), MessageBoxIcon.Error); + return; + } + + saveFileDialog1.InitialDirectory=openFileDialog1.FileName.Substring(0, openFileDialog1.FileName.LastIndexOf(@"\")); + if (saveFileDialog1.ShowDialog()==DialogResult.Cancel) + return; + + try + { + string[] comment=new string[1]; + comment[0]="$"+"Revision"+"$"; + strings.Save(saveFileDialog1.FileName, comment); + } + catch(TranslatorException ex) + { + ShowMessageBox(BuildErrorMessageText(ex), MessageBoxIcon.Error); + return; + } + + MessageBox.Show("File "+saveFileDialog1.FileName+" was succesfully saved.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + #endregion + + #region Menu Item Handler ? + + /// <summary> + /// Opens the standard webbrowser and shows the help page of the online manual + /// </summary> + private void menuItemHelp_Click(object sender, System.EventArgs e) + { + System.Diagnostics.Process.Start("http://xbmc.org/wiki/index.php?title=XBMC_Translator"); + } + + /// <summary> + /// Shows the AboutForm + /// </summary> + private void menuItemAbout_Click(object sender, System.EventArgs e) + { + AboutForm form=new AboutForm(); + form.ShowDialog(); + } + + #endregion + } +} diff --git a/tools/Translator/Translator/MainForm.de.resx b/tools/Translator/Translator/MainForm.de.resx new file mode 100644 index 0000000000..602ec481d2 --- /dev/null +++ b/tools/Translator/Translator/MainForm.de.resx @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="menuItemOpen.Shortcut" type="System.Windows.Forms.Shortcut, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>None</value> + </data> + <data name="menuItemFind.Shortcut" type="System.Windows.Forms.Shortcut, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>None</value> + </data> + <data name="$this.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>NoControl</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/MainForm.en.resx b/tools/Translator/Translator/MainForm.en.resx new file mode 100644 index 0000000000..569e98d395 --- /dev/null +++ b/tools/Translator/Translator/MainForm.en.resx @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="$this.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>NoControl</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/MainForm.resx b/tools/Translator/Translator/MainForm.resx new file mode 100644 index 0000000000..c19e760dfa --- /dev/null +++ b/tools/Translator/Translator/MainForm.resx @@ -0,0 +1,485 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="listView1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="listView1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="listView1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="StingId.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="StingId.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="String.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="String.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="Original.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="Original.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabControl1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabControl1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabControl1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="tabPage1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="tabPage2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage2.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage2.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage2.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="listView2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="listView2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="listView2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage3.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage3.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="listView3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="listView3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="listView3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader5.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader5.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader6.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="columnHeader6.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="mainMenu1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="mainMenu1.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </data> + <data name="mainMenu1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemFile.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemFile.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemNew.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemNew.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem7.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem7.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemOpen.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemOpen.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemSave.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemSave.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemLanguageFolder.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemLanguageFolder.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemExit.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemExit.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemEdit.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemEdit.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemFind.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemFind.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemFindNext.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemFindNext.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem6.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem6.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemLanguageInfo.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemLanguageInfo.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemOptions.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemOptions.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemUserName.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemUserName.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemTools.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemTools.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemValidate.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemValidate.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemConvert.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemConvert.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemHelp.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemHelp.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem8.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItem8.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemAbout.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="menuItemAbout.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="folderBrowserDialog1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="folderBrowserDialog1.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>126, 17</value> + </data> + <data name="folderBrowserDialog1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="openFileDialog1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="openFileDialog1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="openFileDialog1.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>284, 17</value> + </data> + <data name="saveFileDialog1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="saveFileDialog1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="saveFileDialog1.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>414, 17</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Name"> + <value>MainForm</value> + </data> + <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + AAABAAIAICAQAAAAAADoAgAAJgAAABAQEAAAAAAAKAEAAA4DAAAoAAAAIAAAAEAAAAABAAQAAAAAAAAC + AAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/ + AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIiIiAAAAAAAAAAAAAAAAA + gAAAgAAAAAAAAAAAAAAAAIAAAIAAAAAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAAgAAAgAAAAAAAAAAA + AAAAAIAAAIAAAAAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAAgAAAgAAAAAAAAAAAAAAAAIAAAIAAAAAA + AAAAAAAAAACAAACAAAAAAAAAAAAAAAAAgAAAgAAAAAAAAAAAAAAAAIAAAIAAAAAAAAAAAAAAAACAAACA + AAAAAAAAAAAAAAAAgAAAgAAAAAAAAAAAAAAAAIAAAIAAAAAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAA + gAAAgAAAAAAAAAAAAAAAAIAAAIAAAAAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAAgAAAgAAAAAAAAAAA + AAAAAIAAAIAAAAAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAAgAAAgAAAAAAAAACIiIiIiIAAAIiIiIiI + gAAAgAAAAAAAAAAAAAAAAIAAAIAAAAAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAAgAAAgAAAAAAAAAAA + AAAAAIAAAIiIiIiIiIiIiIiIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////w + H///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///w + H///8B////Af///wH///8B////Af///wH///8B//wAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAH//////// + //8oAAAAEAAAACAAAAABAAQAAAAAAIAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAgAAAgAAAAICAAIAA + AACAAIAAgIAAAICAgADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAIiIAAAAAAAAgAgA + AAAAAACACAAAAAAAAIAIAAAAAAAAgAgAAAAAAACACAAAAAAAAIAIAAAAAAAAgAgAAAAAAACACAAAAAAA + AIAIAAAAAAAAgAgAAAAAAACACAAAAAiIiIAIiIiACAAAAAAAAIAIiIiIiIiIgAAAAAAAAAAA/D8AAPw/ + AAD8PwAA/D8AAPw/AAD8PwAA/D8AAPw/AAD8PwAA/D8AAPw/AAD8PwAAgAEAAIABAACAAQAA//8AAA== +</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/NewLanguageForm.cs b/tools/Translator/Translator/NewLanguageForm.cs new file mode 100644 index 0000000000..2fefa3d265 --- /dev/null +++ b/tools/Translator/Translator/NewLanguageForm.cs @@ -0,0 +1,145 @@ +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Summary description for NewLanguageForm. + /// </summary> + public class NewLanguageForm : System.Windows.Forms.Form + { + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBoxName; + private System.Windows.Forms.Label label2; + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.Container components = null; + + public NewLanguageForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // + // TODO: Add any constructor code after InitializeComponent call + // + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if(components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.buttonOK = new System.Windows.Forms.Button(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.textBoxName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // buttonOK + // + this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonOK.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonOK.Location = new System.Drawing.Point(72, 88); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.TabIndex = 4; + this.buttonOK.Text = "OK"; + // + // buttonCancel + // + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonCancel.Location = new System.Drawing.Point(160, 88); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.TabIndex = 5; + this.buttonCancel.Text = "Cancel"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(8, 48); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(56, 23); + this.label1.TabIndex = 2; + this.label1.Text = "Name:"; + // + // textBoxName + // + this.textBoxName.Location = new System.Drawing.Point(80, 48); + this.textBoxName.Name = "textBoxName"; + this.textBoxName.Size = new System.Drawing.Size(152, 20); + this.textBoxName.TabIndex = 3; + this.textBoxName.Text = ""; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(8, 8); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(224, 32); + this.label2.TabIndex = 1; + this.label2.Text = "Please enter the country name of the new language to be created"; + // + // NewLanguageForm + // + this.AcceptButton = this.buttonOK; + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(242, 120); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBoxName); + this.Controls.Add(this.label1); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.buttonOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "NewLanguageForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "New Language"; + this.ResumeLayout(false); + + } + #endregion + + #region Properties + + /// <summary> + /// Gets the name of the language to be created + /// </summary> + public string LanguageName + { + get + { + return textBoxName.Text; + } + } + + #endregion + } +} diff --git a/tools/Translator/Translator/NewLanguageForm.resx b/tools/Translator/Translator/NewLanguageForm.resx new file mode 100644 index 0000000000..55cbfeaee9 --- /dev/null +++ b/tools/Translator/Translator/NewLanguageForm.resx @@ -0,0 +1,175 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="buttonOK.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonOK.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonOK.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxName.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxName.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxName.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.Name"> + <value>NewLanguageForm</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/RegionForm.cs b/tools/Translator/Translator/RegionForm.cs new file mode 100644 index 0000000000..b6c87ab91f --- /dev/null +++ b/tools/Translator/Translator/RegionForm.cs @@ -0,0 +1,634 @@ +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using TeamXBMC.TranslatorCore; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Summary description for RegionForm. + /// </summary> + public class RegionForm : System.Windows.Forms.Form + { + private class Unit + { + public Unit(string nameShort, string nameLong) + { + this.nameShort=nameShort; + this.nameLong=nameLong; + } + + public string NameShort + { + get { return nameShort; } + } + + public string NameLong + { + get { return nameLong; } + } + + private string nameShort; + private string nameLong; + }; + + private ArrayList speedUnits=new ArrayList(); + private ArrayList tempUnits=new ArrayList(); + private LanguageInfo.Region region=null; + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.Label label19; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.Label label21; + private System.Windows.Forms.TextBox textBoxDateShort; + private System.Windows.Forms.TextBox textBoxDateLong; + private System.Windows.Forms.TextBox textBoxAM; + private System.Windows.Forms.TextBox textBoxPM; + private System.Windows.Forms.TextBox textBoxTime; + private System.Windows.Forms.ComboBox comboBoxTempUnit; + private System.Windows.Forms.ComboBox comboBoxSpeedUnit; + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.Container components = null; + + public RegionForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // + // TODO: Add any constructor code after InitializeComponent call + // + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if(components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.buttonOK = new System.Windows.Forms.Button(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label11 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.textBoxDateShort = new System.Windows.Forms.TextBox(); + this.textBoxDateLong = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label20 = new System.Windows.Forms.Label(); + this.label19 = new System.Windows.Forms.Label(); + this.label18 = new System.Windows.Forms.Label(); + this.label17 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.textBoxAM = new System.Windows.Forms.TextBox(); + this.textBoxPM = new System.Windows.Forms.TextBox(); + this.textBoxTime = new System.Windows.Forms.TextBox(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.comboBoxTempUnit = new System.Windows.Forms.ComboBox(); + this.label21 = new System.Windows.Forms.Label(); + this.comboBoxSpeedUnit = new System.Windows.Forms.ComboBox(); + this.label16 = new System.Windows.Forms.Label(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.SuspendLayout(); + // + // buttonOK + // + this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonOK.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonOK.Location = new System.Drawing.Point(184, 336); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.TabIndex = 1; + this.buttonOK.Text = "OK"; + this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + // + // buttonCancel + // + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonCancel.Location = new System.Drawing.Point(272, 336); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.TabIndex = 2; + this.buttonCancel.Text = "Cancel"; + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Location = new System.Drawing.Point(8, 8); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(344, 320); + this.tabControl1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.tabPage1.Controls.Add(this.groupBox1); + this.tabPage1.Controls.Add(this.textBoxDateShort); + this.tabPage1.Controls.Add(this.textBoxDateLong); + this.tabPage1.Controls.Add(this.label2); + this.tabPage1.Controls.Add(this.label1); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Size = new System.Drawing.Size(336, 294); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Date"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.label11); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.label10); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label9); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox1.Location = new System.Drawing.Point(8, 72); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(312, 216); + this.groupBox1.TabIndex = 12; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Date Format"; + // + // label11 + // + this.label11.Location = new System.Drawing.Point(32, 176); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(208, 32); + this.label11.TabIndex = 12; + this.label11.Text = "Optional text can be placed between apostrophes (\' \')"; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(32, 112); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(208, 23); + this.label8.TabIndex = 9; + this.label8.Text = "M = numeric month without prefixed zero"; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(32, 56); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(208, 23); + this.label5.TabIndex = 6; + this.label5.Text = "D = numeric day without prefixed zero"; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(32, 40); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(208, 23); + this.label4.TabIndex = 5; + this.label4.Text = "DD = numeric day with prefixed zero"; + // + // label10 + // + this.label10.Location = new System.Drawing.Point(32, 152); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(208, 23); + this.label10.TabIndex = 11; + this.label10.Text = "YY = Year as two-digit number"; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(32, 24); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(208, 16); + this.label3.TabIndex = 4; + this.label3.Text = "DDDD = Day of week as string"; + // + // label9 + // + this.label9.Location = new System.Drawing.Point(32, 136); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(208, 23); + this.label9.TabIndex = 10; + this.label9.Text = "YYYY = Year as four-digit number"; + // + // label7 + // + this.label7.Location = new System.Drawing.Point(32, 96); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(208, 23); + this.label7.TabIndex = 8; + this.label7.Text = "MM = numeric month with prefixed zero"; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(32, 80); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(208, 23); + this.label6.TabIndex = 7; + this.label6.Text = "MMMM = Month as string"; + // + // textBoxDateShort + // + this.textBoxDateShort.Location = new System.Drawing.Point(96, 48); + this.textBoxDateShort.Name = "textBoxDateShort"; + this.textBoxDateShort.Size = new System.Drawing.Size(224, 20); + this.textBoxDateShort.TabIndex = 3; + this.textBoxDateShort.Text = ""; + // + // textBoxDateLong + // + this.textBoxDateLong.Location = new System.Drawing.Point(96, 16); + this.textBoxDateLong.Name = "textBoxDateLong"; + this.textBoxDateLong.Size = new System.Drawing.Size(224, 20); + this.textBoxDateLong.TabIndex = 1; + this.textBoxDateLong.Text = ""; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(8, 48); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(80, 23); + this.label2.TabIndex = 2; + this.label2.Text = "Date Short:"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(8, 16); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(80, 23); + this.label1.TabIndex = 0; + this.label1.Text = "Date Long:"; + // + // tabPage2 + // + this.tabPage2.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.tabPage2.Controls.Add(this.groupBox2); + this.tabPage2.Controls.Add(this.label14); + this.tabPage2.Controls.Add(this.label13); + this.tabPage2.Controls.Add(this.label12); + this.tabPage2.Controls.Add(this.textBoxAM); + this.tabPage2.Controls.Add(this.textBoxPM); + this.tabPage2.Controls.Add(this.textBoxTime); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Size = new System.Drawing.Size(336, 294); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Time"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.label20); + this.groupBox2.Controls.Add(this.label19); + this.groupBox2.Controls.Add(this.label18); + this.groupBox2.Controls.Add(this.label17); + this.groupBox2.Controls.Add(this.label15); + this.groupBox2.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.groupBox2.Location = new System.Drawing.Point(8, 112); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(320, 176); + this.groupBox2.TabIndex = 6; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Time Format"; + // + // label20 + // + this.label20.Location = new System.Drawing.Point(16, 128); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(232, 23); + this.label20.TabIndex = 5; + this.label20.Text = "hh, mm, ss = with prefixed zero"; + // + // label19 + // + this.label19.Location = new System.Drawing.Point(16, 104); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(232, 23); + this.label19.TabIndex = 4; + this.label19.Text = "h, m, s = without prefixed zero"; + // + // label18 + // + this.label18.Location = new System.Drawing.Point(16, 80); + this.label18.Name = "label18"; + this.label18.TabIndex = 3; + this.label18.Text = "H=24 hour clock"; + // + // label17 + // + this.label17.Location = new System.Drawing.Point(16, 56); + this.label17.Name = "label17"; + this.label17.TabIndex = 2; + this.label17.Text = "h=12 hour clock"; + // + // label15 + // + this.label15.Location = new System.Drawing.Point(16, 32); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(280, 23); + this.label15.TabIndex = 0; + this.label15.Text = "h=hour, m=minute, s=second, x=meridiem symbol"; + // + // label14 + // + this.label14.Location = new System.Drawing.Point(8, 80); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(72, 23); + this.label14.TabIndex = 5; + this.label14.Text = "AM symbol:"; + // + // label13 + // + this.label13.Location = new System.Drawing.Point(8, 48); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(72, 23); + this.label13.TabIndex = 3; + this.label13.Text = "PM symbol:"; + // + // label12 + // + this.label12.Location = new System.Drawing.Point(8, 16); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(72, 23); + this.label12.TabIndex = 1; + this.label12.Text = "Time:"; + // + // textBoxAM + // + this.textBoxAM.Location = new System.Drawing.Point(88, 80); + this.textBoxAM.Name = "textBoxAM"; + this.textBoxAM.Size = new System.Drawing.Size(72, 20); + this.textBoxAM.TabIndex = 6; + this.textBoxAM.Text = ""; + // + // textBoxPM + // + this.textBoxPM.Location = new System.Drawing.Point(88, 48); + this.textBoxPM.Name = "textBoxPM"; + this.textBoxPM.Size = new System.Drawing.Size(72, 20); + this.textBoxPM.TabIndex = 4; + this.textBoxPM.Text = ""; + // + // textBoxTime + // + this.textBoxTime.Location = new System.Drawing.Point(88, 16); + this.textBoxTime.Name = "textBoxTime"; + this.textBoxTime.Size = new System.Drawing.Size(136, 20); + this.textBoxTime.TabIndex = 2; + this.textBoxTime.Text = ""; + // + // tabPage3 + // + this.tabPage3.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.tabPage3.Controls.Add(this.comboBoxTempUnit); + this.tabPage3.Controls.Add(this.label21); + this.tabPage3.Controls.Add(this.comboBoxSpeedUnit); + this.tabPage3.Controls.Add(this.label16); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(336, 294); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Other"; + // + // comboBoxTempUnit + // + this.comboBoxTempUnit.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxTempUnit.Location = new System.Drawing.Point(136, 112); + this.comboBoxTempUnit.Name = "comboBoxTempUnit"; + this.comboBoxTempUnit.Size = new System.Drawing.Size(121, 21); + this.comboBoxTempUnit.TabIndex = 4; + // + // label21 + // + this.label21.Location = new System.Drawing.Point(24, 112); + this.label21.Name = "label21"; + this.label21.TabIndex = 3; + this.label21.Text = "Temperature Unit:"; + // + // comboBoxSpeedUnit + // + this.comboBoxSpeedUnit.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxSpeedUnit.Location = new System.Drawing.Point(136, 48); + this.comboBoxSpeedUnit.Name = "comboBoxSpeedUnit"; + this.comboBoxSpeedUnit.Size = new System.Drawing.Size(121, 21); + this.comboBoxSpeedUnit.TabIndex = 1; + // + // label16 + // + this.label16.Location = new System.Drawing.Point(24, 48); + this.label16.Name = "label16"; + this.label16.TabIndex = 0; + this.label16.Text = "Speed Unit:"; + // + // RegionForm + // + this.AcceptButton = this.buttonOK; + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(362, 368); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.buttonOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "RegionForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Region Properties"; + this.Load += new System.EventHandler(this.RegionForm_Load); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + #region Form initialization + + /// <summary> + /// Updates controls with its values from a region + /// </summary> + private void RegionForm_Load(object sender, System.EventArgs e) + { + // setup abbreviation array for speed units + speedUnits.Add(new Unit("kmh", "km/h")); + speedUnits.Add(new Unit("mpmin", "m/min")); + speedUnits.Add(new Unit("mps", "m/s")); + speedUnits.Add(new Unit("fth", "foot/h")); + speedUnits.Add(new Unit("ftm", "foot/min")); + speedUnits.Add(new Unit("fts", "foot/s")); + speedUnits.Add(new Unit("mph", "mph")); + speedUnits.Add(new Unit("kts", "knots")); + speedUnits.Add(new Unit("beaufort", "beaufort")); + speedUnits.Add(new Unit("inchs", "inch/s")); + speedUnits.Add(new Unit("yards", "yard/s")); + speedUnits.Add(new Unit("fpf", "Furlong/Fortnight")); + + // fill combobox with long names + foreach (Unit speedUnit in speedUnits) + { + comboBoxSpeedUnit.Items.Add(speedUnit.NameLong); + } + + // select the combobox item based on the abbreviation + foreach (Unit speedUnit in speedUnits) + { + if (speedUnit.NameShort==region.SpeedUnit) + { + comboBoxSpeedUnit.Text=speedUnit.NameLong; + } + } + + // setup abbreviation array for temp units + tempUnits.Add(new Unit("F", "°F")); + tempUnits.Add(new Unit("K", "K")); + tempUnits.Add(new Unit("C", "°C")); + tempUnits.Add(new Unit("Re", "°Ré")); + tempUnits.Add(new Unit("Ra", "°Ra")); + tempUnits.Add(new Unit("Ro", "°Rø")); + tempUnits.Add(new Unit("De", "°De")); + tempUnits.Add(new Unit("N", "°N")); + + // fill combobox with long names + foreach (Unit tempUnit in tempUnits) + { + comboBoxTempUnit.Items.Add(tempUnit.NameLong); + } + + // select the combobox item based on the abbreviation + foreach (Unit tempUnit in tempUnits) + { + if (tempUnit.NameShort==region.TempUnit) + { + comboBoxTempUnit.Text=tempUnit.NameLong; + } + } + + // fill in the rest of the region info + textBoxDateShort.Text=region.DateShort; + textBoxDateLong.Text=region.DateLong; + textBoxTime.Text=region.Time; + textBoxAM.Text=region.SymbolAM; + textBoxPM.Text=region.SymbolPM; + } + + #endregion + + #region Control events + + /// <summary> + /// Updates the region with the values of the controls + /// </summary> + private void buttonOK_Click(object sender, System.EventArgs e) + { + region.DateShort=textBoxDateShort.Text; + region.DateLong=textBoxDateLong.Text; + region.Time=textBoxTime.Text; + region.SymbolAM=textBoxAM.Text; + region.SymbolPM=textBoxPM.Text; + + // tranlate the speed unit text of the combobox to + // the abbreviation used in the xml file + foreach (Unit speedUnit in speedUnits) + { + if (speedUnit.NameLong==comboBoxSpeedUnit.Text) + { + region.SpeedUnit=speedUnit.NameShort; + } + } + + // tranlate the temp unit text of the combobox to + // the abbreviation used in the xml file + foreach (Unit tempUnit in tempUnits) + { + if (tempUnit.NameLong==comboBoxTempUnit.Text) + { + region.TempUnit=tempUnit.NameShort; + } + } + } + + #endregion + + #region Properties + + /// <summary> + /// Set/get the region to be edited + /// </summary> + public LanguageInfo.Region RegionInfo + { + get { return region; } + set { region=value; } + } + + #endregion + } +} diff --git a/tools/Translator/Translator/RegionForm.resx b/tools/Translator/Translator/RegionForm.resx new file mode 100644 index 0000000000..8098d131d8 --- /dev/null +++ b/tools/Translator/Translator/RegionForm.resx @@ -0,0 +1,508 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="buttonOK.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonOK.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonOK.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabControl1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabControl1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabControl1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabControl1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="tabPage1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label11.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label11.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label11.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label8.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label8.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label8.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label5.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label5.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label5.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label4.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label10.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label10.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label10.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label9.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label9.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label9.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label7.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label7.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label7.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label6.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label6.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label6.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxDateShort.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxDateShort.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxDateShort.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxDateLong.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxDateLong.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxDateLong.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage2.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage2.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage2.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="groupBox2.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="groupBox2.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="groupBox2.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="groupBox2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label20.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label20.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label20.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label19.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label19.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label19.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label18.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label18.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label18.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label17.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label17.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label17.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label15.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label15.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label15.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label14.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label14.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label14.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label13.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label13.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label13.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label12.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label12.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label12.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxAM.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxAM.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxAM.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxPM.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxPM.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxPM.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxTime.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxTime.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxTime.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="tabPage3.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage3.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="tabPage3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="tabPage3.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="comboBoxTempUnit.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxTempUnit.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="comboBoxTempUnit.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label21.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label21.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label21.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxSpeedUnit.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="comboBoxSpeedUnit.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="comboBoxSpeedUnit.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label16.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label16.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label16.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.Name"> + <value>RegionForm</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/Translator/Translator/Settings.cs b/tools/Translator/Translator/Settings.cs new file mode 100644 index 0000000000..4d574ccb27 --- /dev/null +++ b/tools/Translator/Translator/Settings.cs @@ -0,0 +1,170 @@ +using System; +using System.IO; +using Microsoft.Win32; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// Application wide settings + /// </summary> + public sealed class Settings + { + private string languageFolder; + private string language; + private const string languageOriginal="English"; + private string name=""; + private string email=""; + private static Settings instance=null; + + #region Constructor + + private Settings() + { + + } + + #endregion + + #region Registry + + /// <summary> + /// Loads settings from the registry + /// </summary> + private void ReadSettings() + { + RegistryKey keyUser=Registry.CurrentUser; + RegistryKey keyTranslator=keyUser.CreateSubKey(@"SOFTWARE\Team XBMC\Translator"); + languageFolder=(string)keyTranslator.GetValue("LanguageFolder"); + language=(string)keyTranslator.GetValue("Language"); + name=(string)keyTranslator.GetValue("Name"); + email=(string)keyTranslator.GetValue("Email"); + + if (!Directory.Exists(languageFolder) || + !File.Exists(FilenameOriginal)) + { + languageFolder=""; + language=""; + } + + } + + /// <summary> + /// Saves settings to the registry + /// </summary> + private void WriteSettings() + { + RegistryKey keyUser=Registry.CurrentUser; + RegistryKey keyTranslator=keyUser.CreateSubKey(@"SOFTWARE\Team XBMC\Translator"); + if (languageFolder!=null) keyTranslator.SetValue("LanguageFolder", languageFolder); + if (language!=null) keyTranslator.SetValue("Language", language); + if (name!=null) keyTranslator.SetValue("Name", name); + if (email!=null) keyTranslator.SetValue("Email", email); + } + #endregion + + #region Properties + + /// <summary> + /// Returns the instance of the settings object + /// </summary> + public static Settings Instance + { + get + { + if (instance==null) + { + instance=new Settings(); + instance.ReadSettings(); + } + + return instance; + } + } + + /// <summary> + /// Gets/Sets the language folder + /// </summary> + public string LanguageFolder + { + get { return languageFolder; } + set + { + languageFolder=value; + WriteSettings(); + } + } + + /// <summary> + /// Gets/Sets the language currently edited + /// </summary> + public string Language + { + get { return language; } + set + { + language=value; + WriteSettings(); + } + } + + /// <summary> + /// Gets the language uses a master + /// </summary> + public string LanguageOriginal + { + get { return languageOriginal; } + } + + /// <summary> + /// Gets the filename of the active language + /// </summary> + public string FilenameTranslated + { + get { return LanguageFolder+@"\"+Language+@"\strings.xml"; } + } + + /// <summary> + /// Gets the filename of the master language + /// </summary> + public string FilenameOriginal + { + get { return LanguageFolder+@"\"+LanguageOriginal+@"\strings.xml"; } + } + + /// <summary> + /// Gets the filename of the langinfo of the active language + /// </summary> + public string FilenameLanguageInfo + { + get { return LanguageFolder+@"\"+Language+@"\langinfo.xml"; } + } + + /// <summary> + /// Gets/Sets the name of the translator + /// </summary> + public string TranslatorName + { + get { return name==null ? "" : name; } + set + { + name=value; + WriteSettings(); + } + } + + /// <summary> + /// Gets/Sets the email adress of the translator + /// </summary> + public string TranslatorEmail + { + get { return email==null ? "" : email; } + set + { + email=value; + WriteSettings(); + } + } + + #endregion + } +} diff --git a/tools/Translator/Translator/StringArray.cs b/tools/Translator/Translator/StringArray.cs new file mode 100644 index 0000000000..7b5bd6895f --- /dev/null +++ b/tools/Translator/Translator/StringArray.cs @@ -0,0 +1,292 @@ +using System; +using System.Xml; +using System.Collections; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// Represents a xml language file of XBMC + /// </summary> + /// + public class StringArray : ICollection + { + private ArrayList strings=new ArrayList(); + private Hashtable stringsMap=new Hashtable(); + private double version=0.0; + + #region Constructors + + public StringArray() + { + } + + #endregion + + #region Language file procressing + + /// <summary> + /// Loads a language file by filename + /// </summary> + public void Load(string filename) + { + XmlTextReader reader=null; + + try + { + reader=new XmlTextReader(filename); + + XmlDocument doc=new XmlDocument(); + doc.Load(reader); + + foreach (XmlNode node in doc) + { + if (node.NodeType==XmlNodeType.Comment && node.InnerText.IndexOf("$Revision")>-1) + { + string comment=node.InnerText; + int startPos=comment.IndexOf("$Revision")+10; + int endPos=comment.IndexOf("$", startPos); + + if (endPos>startPos) + { + string str=comment.Substring(startPos, endPos-startPos); + version=Convert.ToDouble(str, System.Globalization.CultureInfo.InvariantCulture); + } + break; + } + } + + XmlNode root=doc.DocumentElement.SelectSingleNode("/strings"); + if (root==null) + throw new TranslatorException(filename+" is not a language file."); + + XmlNodeList list=doc.DocumentElement.SelectNodes("/strings/string"); + + if (list.Count>0) + { + foreach (XmlNode node in list) + { + StringItem item=new StringItem(); + item.LoadFromXml((XmlElement)node); + + Add(item); + } + + strings.Sort(); + } + } + catch(Exception e) + { + throw new TranslatorException("Error loading "+filename, e); + } + finally + { + if (reader!=null) + reader.Close(); + } + } + + /// <summary> + /// Saves a language file by filename + /// </summary> + public bool Save(string filename) + { + return Save(filename, null); + } + + /// <summary> + /// Saves a language file by filename, with additional comments + /// </summary> + public bool Save(string filename, string[] comments) + { + XmlTextWriter writer=null; + + try + { + XmlDocument doc=new XmlDocument(); + + doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", "yes")); + + if (comments!=null) + { + foreach(string comment in comments) + { + doc.AppendChild(doc.CreateComment(comment)); + } + } + + XmlElement root=doc.CreateElement("strings"); + doc.AppendChild(root); + + foreach (StringItem item in this) + { + XmlElement element=doc.CreateElement("string"); + root.AppendChild(element); + item.SaveToXml(ref element); + } + + writer=new XmlTextWriter(filename, System.Text.Encoding.UTF8); + + writer.Formatting=Formatting.Indented; + + doc.Save(writer); + } + catch(Exception e) + { + throw new TranslatorException("Error saving "+filename, e); + } + finally + { + if (writer!=null) + writer.Close(); + } + + return true; + } + + #endregion + + #region Array methods + + /// <summary> + /// Add a StringItem to the StringArray + /// </summary> + public void Add(StringItem item) + { + try + { + stringsMap.Add(item.Id, item); + } + catch (ArgumentException e) + { + throw new TranslatorException("The string with the id " + item.Id.ToString() + " appears more then once in this file.", e); + } + + strings.Add(item); + + } + + /// <summary> + /// Remove all StringItems from the StringArray + /// </summary> + public void Clear() + { + strings.Clear(); + stringsMap.Clear(); + } + + /// <summary> + /// Sort the StringArray by StringItem id + /// </summary> + public void Sort() + { + strings.Sort(); + } + + /// <summary> + /// Returns a string with a certain id + /// </summary> + public bool GetStringById(long id, ref StringItem item) + { + if (!stringsMap.Contains(id)) + { + item=null; + return false; + } + + item=(StringItem)stringsMap[id]; + + return true; + } + + /// <summary> + /// Returns a StringArray with all string not in + /// arr. + /// </summary> + public StringArray GetStringsNotIn(StringArray arr) + { + StringArray ret=new StringArray(); + + foreach (StringItem item in strings) + { + if (item.Id!=6) // "XBMC SVN" + { + StringItem stringItem=null; + arr.GetStringById(item.Id, ref stringItem); + if (stringItem==null) + ret.Add(item); + } + } + + return ret; + } + + /// <summary> + /// Returns the ids of all changed strings + /// of arr. + /// </summary> + public long[] GetStringsChangedIn(StringArray arr) + { + ArrayList ret=new ArrayList(); + + foreach (StringItem item in strings) + { + if (item.Id!=6) // "XBMC SVN" + { + StringItem stringItem=null; + arr.GetStringById(item.Id, ref stringItem); + if (stringItem!=null && stringItem.Text!=item.Text) + ret.Add(item.Id); + } + } + + return (long[])ret.ToArray(typeof(long)); + } + + #endregion + + #region Properties + + /// <summary> + /// Returns the version of the strings file + /// </summary> + public double Version + { + get { return version; } + } + + #endregion + + #region ICollection Members + + public void CopyTo(Array array, int index) + { + strings.CopyTo(array, index); + } + + public int Count + { + get{return strings.Count;} + } + + public object SyncRoot + { + get{return this;} + } + + public bool IsSynchronized + { + get{return false;} + } + + #endregion + + #region IEnumerable Members + + public IEnumerator GetEnumerator() + { + return strings.GetEnumerator(); + } + + #endregion + } +} diff --git a/tools/Translator/Translator/StringItem.cs b/tools/Translator/Translator/StringItem.cs new file mode 100644 index 0000000000..cf09030a36 --- /dev/null +++ b/tools/Translator/Translator/StringItem.cs @@ -0,0 +1,115 @@ +using System; +using System.Xml; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// Represent a single string of a language file + /// </summary> + public class StringItem : IComparable + { + /// <summary> + /// The delegate is called to notify that a StringItem has changed + /// </summary> + public delegate void StringUpdatedDelegate(StringItem item); + + private long id=0; + private string text=""; + public event StringUpdatedDelegate stringUpdated=null; + + #region Constructors + + public StringItem() + { + + } + + public StringItem(StringItem right) + { + id=right.id; + Text=right.Text; + } + + #endregion + + #region Properties + + /// <summary> + /// Get the id of the StingItem + /// </summary> + public long Id + { + get { return id; } + } + + /// <summary> + /// Get the value of the StingItem + /// </summary> + public string Text + { + get { return text; } + set + { + text=value; + if (stringUpdated!=null) + { + stringUpdated(this); + } + } + } + + #endregion + + #region IComparable Members + + public int CompareTo(object obj) + { + StringItem right=(StringItem)obj; + return Convert.ToInt32(Id)-Convert.ToInt32(right.Id); + } + + #endregion + + #region Xml Io + + /// <summary> + /// Load a single StringItem from a XmlElement + /// </summary> + public void LoadFromXml(XmlElement element) + { + if (element.Attributes.Count==1) + { // new language file layout with id as attribute + id=Convert.ToInt32(element.GetAttribute("id")); + text=element.InnerText; + } + else + { // old language file layout with nodes for ids and values + id=Convert.ToInt32(element.SelectSingleNode("id").InnerText); + text=element.SelectSingleNode("value").InnerText; + } + + // Replace \n and \r with the visible newline char ¶ to make it editable + if (Text.IndexOf("\r\n")>-1) + text=text.Replace("\r\n", "¶"); + else if (Text.IndexOf("\n")>-1) + text=text.Replace("\n", "¶"); + else if (Text.IndexOf("\r")>-1) + text=text.Replace("\r", "¶"); + } + + /// <summary> + /// Save a single StringItem to a XmlElement + /// </summary> + public void SaveToXml(ref XmlElement element) + { + element.SetAttribute("id", Id.ToString()); + element.InnerText=Text; + + // Replace the visible newline char ¶ with \n for saving + if (element.InnerText.IndexOf("¶")>-1) + element.InnerText=element.InnerText.Replace("¶", "\n"); + } + + #endregion + } +} diff --git a/tools/Translator/Translator/TranslationManager.cs b/tools/Translator/Translator/TranslationManager.cs new file mode 100644 index 0000000000..44c8c78bef --- /dev/null +++ b/tools/Translator/Translator/TranslationManager.cs @@ -0,0 +1,185 @@ +using System; +using System.IO; +using System.Collections; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// Object to communicate with the gui. + /// </summary> + public sealed class TranslationManager + { + private TranslatorArray strings = new TranslatorArray(); + private static TranslationManager instance=null; + + private TranslationManager() + { + + } + + /// <summary> + /// Loads the current language + /// </summary> + public void Initialize() + { + strings.Clear(); + strings.Load(); + } + + #region Language file processing + + /// <summary> + /// Create a new language + /// </summary> + public void CreateLanguage(string name) + { + if (File.Exists(Settings.Instance.LanguageFolder+@"\"+name+@"\strings.xml")) + throw new TranslatorException("The language \""+name+"\" already exists."); + + try + { + Directory.CreateDirectory(Settings.Instance.LanguageFolder+@"\"+name); + } + catch (Exception e) + { + throw new TranslatorException("Unable to create the directory "+Settings.Instance.LanguageFolder+@"\"+name, e); + } + + + // Save an empty strings.xml file + StringArray stringsNew=new StringArray(); + stringsNew.Save(Settings.Instance.LanguageFolder+@"\"+name+@"\strings.xml"); + + LanguageInfo langinfo=new LanguageInfo(); + langinfo.Save(Settings.Instance.LanguageFolder+@"\"+name+@"\langinfo.xml"); + } + + /// <summary> + /// Save the current language + /// </summary> + public void SaveTranslated() + { + strings.Save(); + } + + #endregion + + #region Properties + + /// <summary> + /// Gets the instance of the TranslationManager + /// </summary> + public static TranslationManager Instance + { + get + { + if (instance==null) + { + instance=new TranslationManager(); + } + + return instance; + } + } + + /// <summary> + /// Get the strings of the current language with the state translated + /// </summary> + public TranslatorArray Translated + { + get + { + strings.Enumerator=TranslatorArrayEnumerator.Translated; + return strings; + } + } + + /// <summary> + /// Get the strings of the current language with the state untranslated + /// </summary> + public TranslatorArray Untranslated + { + get + { + strings.Enumerator=TranslatorArrayEnumerator.Untranslated; + return strings; + } + } + + /// <summary> + /// Get the strings of the current language with the state changed + /// </summary> + public TranslatorArray Changed + { + get + { + strings.Enumerator=TranslatorArrayEnumerator.Changed; + return strings; + } + } + + /// <summary> + /// Get all strings of the current language + /// </summary> + public TranslatorArray All + { + get + { + strings.Enumerator=TranslatorArrayEnumerator.All; + return strings; + } + } + + /// <summary> + /// Get the name of the current language + /// </summary> + public string LanguageTranslated + { + get { return Settings.Instance.Language; } + } + + /// <summary> + /// Get the name of the master language + /// </summary> + public string LanguageOriginal + { + get { return Settings.Instance.LanguageOriginal; } + } + + /// <summary> + /// Get all available languages + /// </summary> + public string[] Languages + { + get + { + string root=Settings.Instance.LanguageFolder; + string[] dirs=Directory.GetDirectories(root); + ArrayList languages=new ArrayList(); + + foreach (string dir in dirs) + { + if (File.Exists(dir+@"\strings.xml")) + { + // Extract language name from path + string language=dir.Substring(root.Length+1, dir.Length-root.Length-1); + if (!language.Equals(Settings.Instance.LanguageOriginal) ) + languages.Add(language); + } + } + + return (string[])languages.ToArray(typeof(string)); + } + } + + /// <summary> + /// Returns true if the currently edited language file is has been changed by the user + /// </summary> + public bool IsModified + { + get { return strings.IsModified; } + } + + #endregion + } +} diff --git a/tools/Translator/Translator/Translator.csproj b/tools/Translator/Translator/Translator.csproj new file mode 100644 index 0000000000..84fce481fa --- /dev/null +++ b/tools/Translator/Translator/Translator.csproj @@ -0,0 +1,259 @@ +<VisualStudioProject> + <CSHARP + ProjectType = "Local" + ProductVersion = "7.10.3077" + SchemaVersion = "2.0" + ProjectGuid = "{75A56598-4600-401D-9F4B-B9F36C4AC86F}" + > + <Build> + <Settings + ApplicationIcon = "App.ico" + AssemblyKeyContainerName = "" + AssemblyName = "Translator" + AssemblyOriginatorKeyFile = "" + DefaultClientScript = "JScript" + DefaultHTMLPageLayout = "Grid" + DefaultTargetSchema = "IE50" + DelaySign = "false" + OutputType = "WinExe" + PreBuildEvent = "" + PostBuildEvent = "" + RootNamespace = "TeamXBMC" + RunPostBuildEvent = "OnBuildSuccess" + StartupObject = "" + > + <Config + Name = "Debug" + AllowUnsafeBlocks = "false" + BaseAddress = "285212672" + CheckForOverflowUnderflow = "false" + ConfigurationOverrideFile = "" + DefineConstants = "DEBUG;TRACE" + DocumentationFile = "" + DebugSymbols = "true" + FileAlignment = "4096" + IncrementalBuild = "false" + NoStdLib = "false" + NoWarn = "" + Optimize = "false" + OutputPath = "bin\Debug\" + RegisterForComInterop = "false" + RemoveIntegerChecks = "false" + TreatWarningsAsErrors = "false" + WarningLevel = "4" + /> + <Config + Name = "Release" + AllowUnsafeBlocks = "false" + BaseAddress = "285212672" + CheckForOverflowUnderflow = "false" + ConfigurationOverrideFile = "" + DefineConstants = "TRACE" + DocumentationFile = "" + DebugSymbols = "false" + FileAlignment = "4096" + IncrementalBuild = "false" + NoStdLib = "false" + NoWarn = "" + Optimize = "true" + OutputPath = "bin\Release\" + RegisterForComInterop = "false" + RemoveIntegerChecks = "false" + TreatWarningsAsErrors = "false" + WarningLevel = "4" + /> + </Settings> + <References> + <Reference + Name = "System" + AssemblyName = "System" + HintPath = "..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll" + /> + <Reference + Name = "System.Data" + AssemblyName = "System.Data" + HintPath = "..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" + /> + <Reference + Name = "System.Drawing" + AssemblyName = "System.Drawing" + HintPath = "..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll" + /> + <Reference + Name = "System.Windows.Forms" + AssemblyName = "System.Windows.Forms" + HintPath = "..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Windows.Forms.dll" + /> + <Reference + Name = "System.XML" + AssemblyName = "System.Xml" + HintPath = "..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" + /> + </References> + </Build> + <Files> + <Include> + <File + RelPath = "AboutForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "AboutForm.resx" + DependentUpon = "AboutForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "App.ico" + BuildAction = "Content" + /> + <File + RelPath = "AssemblyInfo.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "ChooseLanguageForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "ChooseLanguageForm.resx" + DependentUpon = "ChooseLanguageForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "EditStringForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "EditStringForm.resx" + DependentUpon = "EditStringForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "Enumerator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "FindForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "FindForm.resx" + DependentUpon = "FindForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "LanguageInfo.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "LanguageInfoForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "LanguageInfoForm.resx" + DependentUpon = "LanguageInfoForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "ListViewItemString.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "MainForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "MainForm.de.resx" + DependentUpon = "MainForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "MainForm.en.resx" + DependentUpon = "MainForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "MainForm.resx" + DependentUpon = "MainForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "NewLanguageForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "NewLanguageForm.resx" + DependentUpon = "NewLanguageForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "RegionForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "RegionForm.resx" + DependentUpon = "RegionForm.cs" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "Settings.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "StringArray.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "StringItem.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "TranslationManager.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "TranslatorArray.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "TranslatorException.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "TranslatorItem.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "UserForm.cs" + SubType = "Form" + BuildAction = "Compile" + /> + <File + RelPath = "UserForm.resx" + DependentUpon = "UserForm.cs" + BuildAction = "EmbeddedResource" + /> + </Include> + </Files> + </CSHARP> +</VisualStudioProject> + diff --git a/tools/Translator/Translator/TranslatorArray.cs b/tools/Translator/Translator/TranslatorArray.cs new file mode 100644 index 0000000000..ccb639bf7a --- /dev/null +++ b/tools/Translator/Translator/TranslatorArray.cs @@ -0,0 +1,312 @@ +using System; +using System.IO; +using System.Collections; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// Represents an array of strings to be translated. + /// </summary> + public class TranslatorArray : ICollection + { + private ArrayList strings=new ArrayList(); + private Hashtable stringsMap=new Hashtable(); + private TranslatorArrayEnumerator enumerator=TranslatorArrayEnumerator.All; + private double versionOriginal=0.0; + private bool modified=false; + + #region Constructors + + public TranslatorArray() + { + // + // TODO: Add constructor logic here + // + } + + #endregion + + #region ICollection Members + + public bool IsSynchronized + { + get{return false;} + } + + public int Count + { + get{return strings.Count;} + } + + public void CopyTo(Array array, int index) + { + strings.CopyTo(array, index); + } + + public object SyncRoot + { + get{return this;} + } + + #endregion + + #region IEnumerable Members + + public IEnumerator GetEnumerator() + { + switch (enumerator) + { + case TranslatorArrayEnumerator.All: + return strings.GetEnumerator(); + case TranslatorArrayEnumerator.Translated: + return new EnumeratorTranslated(strings.GetEnumerator()); + case TranslatorArrayEnumerator.Untranslated: + return new EnumeratorUntranslated(strings.GetEnumerator()); + case TranslatorArrayEnumerator.Changed: + return new EnumeratorChanged(strings.GetEnumerator()); + default: + return strings.GetEnumerator(); + } + } + + #endregion + + #region Array methods + + /// <summary> + /// Adds a TranslatorItem to the array. + /// </summary> + private void Add(TranslatorItem item) + { + strings.Add(item); + stringsMap.Add(item.StringOriginal.Id, item); + } + + /// <summary> + /// Sorts the array + /// </summary> + private void Sort() + { + strings.Sort(); + } + + /// <summary> + /// Clears the array + /// </summary> + public void Clear() + { + strings.Clear(); + stringsMap.Clear(); + versionOriginal=0.0; + } + + /// <summary> + /// Returns a TranslatorItem by a certain id + /// </summary> + public bool GetItemById(long id, ref TranslatorItem item) + { + if (!stringsMap.Contains(id)) + { + item=null; + return false; + } + + item=(TranslatorItem)stringsMap[id]; + + return true; + } + + #endregion + + #region Language file processing + + /// <summary> + /// Loads the current language file and checks its string for its state + /// </summary> + public void Load() + { + if (Settings.Instance.LanguageFolder=="" || Settings.Instance.Language=="") + return; + + modified=false; + + if (!File.Exists(Settings.Instance.FilenameOriginal)) + throw new TranslatorException("File "+Settings.Instance.FilenameOriginal+" was not found. Please be sure your language folder is set properly."); + + if (!File.Exists(Settings.Instance.FilenameTranslated)) + throw new TranslatorException("File "+Settings.Instance.FilenameTranslated+" was not found. Please be sure your language folder is set properly."); + + StringArray stringsOriginal=new StringArray(); + stringsOriginal.Load(Settings.Instance.FilenameOriginal); + + versionOriginal=stringsOriginal.Version; + + StringArray stringsTranslated=new StringArray(); + stringsTranslated.Load(Settings.Instance.FilenameTranslated); + + try + { + DetermineTranslated(stringsTranslated, stringsOriginal); + DetermineUntranslated(stringsTranslated, stringsOriginal); + DetermineChanged(stringsTranslated, stringsOriginal); + Sort(); + + foreach (TranslatorItem item in strings) + { // Add StringModified to the stringUpdated delegate + // to be informed if a string has changed + item.StringTranslated.stringUpdated+=new StringItem.StringUpdatedDelegate(StringModified); + } + } + catch(Exception e) + { + throw new TranslatorException("Error processing xml data", e); + } + } + + /// <summary> + /// Returns true if the current language file is modified + /// </summary> + public bool IsModified + { + get { return modified; } + } + + /// <summary> + /// Save the current language file + /// </summary> + public void Save() + { + StringArray strings=new StringArray(); + + enumerator=TranslatorArrayEnumerator.All; + foreach (TranslatorItem item in this) + { + if (item.State==TranslationState.Translated || item.State==TranslationState.Changed) + strings.Add(item.StringTranslated); + } + + strings.Sort(); + + ArrayList comments=new ArrayList(); + comments.Add("Language file translated with Team XBMC Translator"); + if (Settings.Instance.TranslatorName!="") + comments.Add("Translator: "+Settings.Instance.TranslatorName); + if (Settings.Instance.TranslatorEmail!="") + comments.Add("Email: "+Settings.Instance.TranslatorEmail); + + DateTime time=DateTime.Now; + comments.Add("Date of translation: "+time.GetDateTimeFormats(System.Globalization.CultureInfo.InvariantCulture)[0]); + comments.Add("$"+"Revision"+"$"); + if (versionOriginal>0.0) + comments.Add("Based on english strings version "+versionOriginal.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + strings.Save(Settings.Instance.FilenameTranslated, (string[])comments.ToArray(typeof(string))); + + modified=false; + } + + /// <summary> + /// Creates all TranlatorItems with the state translated + /// </summary> + private void DetermineTranslated(StringArray stringsTranslated, StringArray stringsOriginal) + { + foreach (StringItem item in stringsOriginal) + { + StringItem itemTranslated=null; + if (stringsTranslated.GetStringById(item.Id, ref itemTranslated)) + { + Add(new TranslatorItem(itemTranslated, item, TranslationState.Translated)); + } + } + } + + /// <summary> + /// Creates all TranlatorItems with the state untranslated + /// </summary> + private void DetermineUntranslated(StringArray stringsTranslated, StringArray stringsOriginal) + { + foreach (StringItem item in stringsOriginal.GetStringsNotIn(stringsTranslated)) + { + StringItem itemUntranslated=new StringItem(item); + itemUntranslated.Text=""; + Add(new TranslatorItem(itemUntranslated, item, TranslationState.Untranslated)); + } + } + + /// <summary> + /// Creates all TranlatorItems with the state changed. + /// It also saves the master language history + /// </summary> + private void DetermineChanged(StringArray stringsTranslated, StringArray stringsOriginal) + { + string filenameSaved=System.Windows.Forms.Application.LocalUserAppDataPath.Substring(0, System.Windows.Forms.Application.LocalUserAppDataPath.LastIndexOf(@"\"))+@"\strings.xml"; + string filenamePrev=System.Windows.Forms.Application.LocalUserAppDataPath.Substring(0, System.Windows.Forms.Application.LocalUserAppDataPath.LastIndexOf(@"\"))+@"\stringsPrev.xml"; + + // No history yet? + if (!File.Exists(filenameSaved)) + { // Copy our master language, to have a history + File.Copy(Settings.Instance.FilenameOriginal, filenameSaved, true); + return; + } + + StringArray stringsSaved=new StringArray(); + + stringsSaved.Load(filenameSaved); + + // Check the version of the saved master language + if (stringsOriginal.Version>stringsSaved.Version) + { // saved is older then our current master language, + // update history + File.Copy(filenameSaved, filenamePrev, true); + File.Copy(Settings.Instance.FilenameOriginal, filenameSaved, true); + } + else if (stringsOriginal.Version<stringsSaved.Version) + { // Oh Oh, current master is older then the saved one, thow exception + throw new TranslatorException("File "+Settings.Instance.FilenameOriginal+" is older then the one last used for this translation."); + } + + stringsSaved.Clear(); + + if (File.Exists(filenamePrev)) + { // we need at two file to do the diff + StringArray stringsPrev=new StringArray(); + stringsPrev.Load(filenamePrev); + + // check for changed items + foreach (long id in stringsPrev.GetStringsChangedIn(stringsOriginal)) + { + TranslatorItem translatorItem=null; + if (GetItemById(id, ref translatorItem)) + { + if (translatorItem.StringTranslated.Text!="") + translatorItem.State=TranslationState.Changed; + } + } + } + } + + /// <summary> + /// This function is called if a StringItem has beeen modified + /// </summary> + private void StringModified(StringItem item) + { + modified=true; + } + + #endregion + + #region Properties + + /// <summary> + /// Gets/Sets the current enumerator. See + /// TranslatorArrayEnumerator for more info. + /// </summary> + public TranslatorArrayEnumerator Enumerator + { + get { return enumerator; } + set { enumerator=value; } + } + + #endregion + } +} diff --git a/tools/Translator/Translator/TranslatorException.cs b/tools/Translator/Translator/TranslatorException.cs new file mode 100644 index 0000000000..540f508282 --- /dev/null +++ b/tools/Translator/Translator/TranslatorException.cs @@ -0,0 +1,24 @@ +using System; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// Exception thrown by the TranslatorCore namespace + /// </summary> + public class TranslatorException : ApplicationException + { + #region Constructors + + public TranslatorException(string message, Exception innerException) : base(message, innerException) + { + + } + + public TranslatorException(string message) : base(message) + { + + } + + #endregion + } +} diff --git a/tools/Translator/Translator/TranslatorItem.cs b/tools/Translator/Translator/TranslatorItem.cs new file mode 100644 index 0000000000..cc16d93c32 --- /dev/null +++ b/tools/Translator/Translator/TranslatorItem.cs @@ -0,0 +1,76 @@ +using System; + +namespace TeamXBMC.TranslatorCore +{ + /// <summary> + /// State of a TranslatorItem + /// </summary> + public enum TranslationState + { + Unknown=0, + Translated, + Untranslated, + Changed + }; + + /// <summary> + /// Single item of a languge to be translated. + /// Used in the TranslatorArray. + /// </summary> + public class TranslatorItem : IComparable + { + private StringItem translated=null; + private StringItem original=null; + private TranslationState state=TranslationState.Unknown; + + #region Constructors + + public TranslatorItem(StringItem translated, StringItem original, TranslationState state) + { + this.translated=translated; + this.original=original; + this.state=state; + } + + #endregion + + #region Properties + + /// <summary> + /// Returns a StringItem with the translated text + /// </summary> + public StringItem StringTranslated + { + get { return translated; } + } + + /// <summary> + /// Returns a StringItem with the original text + /// </summary> + public StringItem StringOriginal + { + get { return original; } + } + + /// <summary> + /// Gets/Sets the state of the item + /// </summary> + public TranslationState State + { + get { return state; } + set { state=value; } + } + + #endregion + + #region IComparable Members + + public int CompareTo(object obj) + { + TranslatorItem right=(TranslatorItem)obj; + return Convert.ToInt32(StringTranslated.Id)-Convert.ToInt32(right.StringTranslated.Id); + } + + #endregion + } +} diff --git a/tools/Translator/Translator/UserForm.cs b/tools/Translator/Translator/UserForm.cs new file mode 100644 index 0000000000..6367315f52 --- /dev/null +++ b/tools/Translator/Translator/UserForm.cs @@ -0,0 +1,184 @@ +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using TeamXBMC.TranslatorCore; + +namespace TeamXBMC.Translator +{ + /// <summary> + /// Summary description for UserForm. + /// </summary> + public class UserForm : System.Windows.Forms.Form + { + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBoxName; + private System.Windows.Forms.TextBox textBoxEmail; + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.Container components = null; + + public UserForm() + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // + // TODO: Add any constructor code after InitializeComponent call + // + } + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if(components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.buttonOK = new System.Windows.Forms.Button(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.textBoxName = new System.Windows.Forms.TextBox(); + this.textBoxEmail = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // buttonOK + // + this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonOK.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonOK.Location = new System.Drawing.Point(120, 104); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.TabIndex = 5; + this.buttonOK.Text = "OK"; + this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + // + // buttonCancel + // + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.buttonCancel.Location = new System.Drawing.Point(208, 104); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.TabIndex = 6; + this.buttonCancel.Text = "Cancel"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(8, 40); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(56, 23); + this.label1.TabIndex = 1; + this.label1.Text = "Name:"; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(8, 72); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(56, 23); + this.label2.TabIndex = 3; + this.label2.Text = "Email:"; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(8, 8); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(272, 32); + this.label3.TabIndex = 0; + this.label3.Text = "Set your name and email adress (optional). They will be automatically saved to yo" + + "ur translation."; + // + // textBoxName + // + this.textBoxName.Location = new System.Drawing.Point(64, 40); + this.textBoxName.Name = "textBoxName"; + this.textBoxName.Size = new System.Drawing.Size(216, 20); + this.textBoxName.TabIndex = 2; + this.textBoxName.Text = ""; + // + // textBoxEmail + // + this.textBoxEmail.Location = new System.Drawing.Point(64, 72); + this.textBoxEmail.Name = "textBoxEmail"; + this.textBoxEmail.Size = new System.Drawing.Size(216, 20); + this.textBoxEmail.TabIndex = 4; + this.textBoxEmail.Text = ""; + // + // UserForm + // + this.AcceptButton = this.buttonOK; + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(292, 136); + this.Controls.Add(this.textBoxEmail); + this.Controls.Add(this.textBoxName); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.buttonOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UserForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Translator Name"; + this.Load += new System.EventHandler(this.UserForm_Load); + this.ResumeLayout(false); + + } + #endregion + + #region Form initialization + + /// <summary> + /// Sets the text of the controls from the settings values + /// </summary> + private void UserForm_Load(object sender, System.EventArgs e) + { + textBoxName.Text=Settings.Instance.TranslatorName; + textBoxEmail.Text=Settings.Instance.TranslatorEmail; + } + + #endregion + + #region Control Events + + /// <summary> + /// Sets the settings values from the text of the controls + /// </summary> + private void buttonOK_Click(object sender, System.EventArgs e) + { + Settings.Instance.TranslatorName=textBoxName.Text; + Settings.Instance.TranslatorEmail=textBoxEmail.Text; + DialogResult=DialogResult.OK; + Close(); + } + + #endregion + } +} diff --git a/tools/Translator/Translator/UserForm.resx b/tools/Translator/Translator/UserForm.resx new file mode 100644 index 0000000000..92d6178f2d --- /dev/null +++ b/tools/Translator/Translator/UserForm.resx @@ -0,0 +1,193 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 1.3 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">1.3</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1">this is my long string</data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + [base64 mime encoded serialized .NET Framework object] + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used forserialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>1.3</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="buttonOK.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonOK.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonOK.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="label3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="label3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxName.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxName.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxName.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxEmail.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="textBoxEmail.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="textBoxEmail.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> + <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>(Default)</value> + </data> + <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </data> + <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>8, 8</value> + </data> + <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>80</value> + </data> + <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </data> + <data name="$this.Name"> + <value>UserForm</value> + </data> + <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>Private</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/UpdateThumbs.py b/tools/UpdateThumbs.py new file mode 100755 index 0000000000..cffdcded86 --- /dev/null +++ b/tools/UpdateThumbs.py @@ -0,0 +1,36 @@ +# +# Copyright (C) 2005-2008 Team XBMC +# http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +# + +import xbmc, xbmcgui, re, os + +thumbDir = "Q:\\thumbs" +files = os.listdir(thumbDir) +test = re.compile("\.tbn$", re.IGNORECASE) +files = filter(test.search, files) + +for file in files: + srcPath = thumbDir + "\\" + file + size = len(file) + diff = 12 - size + dest = ("0" * diff) + file.lower() + subDir = dest[0] + destPath = thumbDir + "\\" + subDir + "\\" + dest + if not os.path.exists(destPath): + os.rename(srcPath,destPath) diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/e2fs_stage1_5 b/tools/XBMCLive/BootCD/cdimage/boot/grub/e2fs_stage1_5 Binary files differnew file mode 100644 index 0000000000..2c612015b0 --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/e2fs_stage1_5 diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/fat_stage1_5 b/tools/XBMCLive/BootCD/cdimage/boot/grub/fat_stage1_5 Binary files differnew file mode 100644 index 0000000000..fac9cedc77 --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/fat_stage1_5 diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/jfs_stage1_5 b/tools/XBMCLive/BootCD/cdimage/boot/grub/jfs_stage1_5 Binary files differnew file mode 100644 index 0000000000..90f97e4a01 --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/jfs_stage1_5 diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/menu.lst b/tools/XBMCLive/BootCD/cdimage/boot/grub/menu.lst new file mode 100755 index 0000000000..ed57eac1a4 --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/menu.lst @@ -0,0 +1,52 @@ +# +default 0 +timeout 10 + +foreground eeeeee +background 333333 + +splashimage=/boot/xbmc.xpm.gz + +# + +title XBMCLive - NVIDIA GPU +kernel /vmlinuz initrd=initrd0.img boot=cd quiet splash xbmc=nvidia,nodiskmount,tempfs,setvolume loglevel=0 +initrd /initrd0.img +quiet +boot + +title XBMCLive - ATI/AMD GPU +kernel /vmlinuz initrd=initrd0.img boot=cd quiet splash xbmc=amd,nodiskmount,tempfs,setvolume loglevel=0 +initrd /initrd0.img +quiet +boot + +title XBMCLive - Intel GPU +kernel /vmlinuz initrd=initrd0.img boot=cd quiet splash xbmc=intel,nodiskmount,tempfs,setvolume loglevel=0 +initrd /initrd0.img +quiet +boot + +title XBMCLive - SAFE MODE, NVIDIA GPU +kernel /vmlinuz initrd=initrd0.img boot=cd quiet xbmc=nvidia,nodiskmount,noredir,tempfs loglevel=0 +initrd /initrd0.img +quiet +boot + +title XBMCLive - SAFE MODE, ATI/AMD GPU +kernel /vmlinuz initrd=initrd0.img boot=cd quiet xbmc=amd,nodiskmount,noredir,tempfs loglevel=0 +initrd /initrd0.img +quiet +boot + +title XBMCLive - SAFE MODE, Intel GPU +kernel /vmlinuz initrd=initrd0.img boot=cd xbmc=nodiskmount,noredir +initrd /initrd0.img +quiet +boot + +title Install XBMCLive to disk (USB or HDD) +kernel /vmlinuz initrd=initrd0.img boot=cd quiet splash xbmc=install,nodiskmount,noredir +initrd /initrd0.img +quiet +boot diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/minix_stage1_5 b/tools/XBMCLive/BootCD/cdimage/boot/grub/minix_stage1_5 Binary files differnew file mode 100644 index 0000000000..2b1a587321 --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/minix_stage1_5 diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/reiserfs_stage1_5 b/tools/XBMCLive/BootCD/cdimage/boot/grub/reiserfs_stage1_5 Binary files differnew file mode 100644 index 0000000000..c8758b400d --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/reiserfs_stage1_5 diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/stage1 b/tools/XBMCLive/BootCD/cdimage/boot/grub/stage1 Binary files differnew file mode 100644 index 0000000000..c10df8082c --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/stage1 diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/stage2 b/tools/XBMCLive/BootCD/cdimage/boot/grub/stage2 Binary files differnew file mode 100644 index 0000000000..d577e039aa --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/stage2 diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/stage2_eltorito b/tools/XBMCLive/BootCD/cdimage/boot/grub/stage2_eltorito Binary files differnew file mode 100644 index 0000000000..70cb852b09 --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/stage2_eltorito diff --git a/tools/XBMCLive/BootCD/cdimage/boot/grub/xfs_stage1_5 b/tools/XBMCLive/BootCD/cdimage/boot/grub/xfs_stage1_5 Binary files differnew file mode 100644 index 0000000000..a85f2808fb --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/grub/xfs_stage1_5 diff --git a/tools/XBMCLive/BootCD/cdimage/boot/xbmc.xpm.gz b/tools/XBMCLive/BootCD/cdimage/boot/xbmc.xpm.gz Binary files differnew file mode 100755 index 0000000000..18cdfb6fb6 --- /dev/null +++ b/tools/XBMCLive/BootCD/cdimage/boot/xbmc.xpm.gz diff --git a/tools/XBMCLive/BootCD/make-iso.sh b/tools/XBMCLive/BootCD/make-iso.sh new file mode 100755 index 0000000000..f11febb49a --- /dev/null +++ b/tools/XBMCLive/BootCD/make-iso.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# NAME: make-iso.sh + +# Creates an iso9660 image with rockridge extensions from the contents +# of directory cdimage. + +CDIMAGE=cdimage +if [ ! -d $CDIMAGE ];then + echo "You need to be cd'd to the directory above 'cdimage'" + exit +fi + +ISO=XBMCLive.iso + +mkisofs -R -l -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $ISO $CDIMAGE +# -V "XBMCLiveCD" -P "http://xbmc.org" -p "http://xbmc.org" + +echo "ISO generated in $ISO" diff --git a/tools/XBMCLive/BootCD/updateFiles.sh b/tools/XBMCLive/BootCD/updateFiles.sh new file mode 100755 index 0000000000..8a5045e905 --- /dev/null +++ b/tools/XBMCLive/BootCD/updateFiles.sh @@ -0,0 +1,5 @@ +sudo mount -o loop $1 Image +cp Image/rootfs.img Image/vmlinuz Image/initrd0.img cdimage +sudo umount Image +rm XBMCLive.iso +./make-iso.sh diff --git a/tools/XBMCLive/Creator/enterChroot.sh b/tools/XBMCLive/Creator/enterChroot.sh new file mode 100755 index 0000000000..c712e43d21 --- /dev/null +++ b/tools/XBMCLive/Creator/enterChroot.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sudo image-creator --command=chroot-target --project-name=Intrepid --target-name=XBMCLive diff --git a/tools/XBMCLive/Creator/image-creator.cfg b/tools/XBMCLive/Creator/image-creator.cfg new file mode 100644 index 0000000000..1865f884b0 --- /dev/null +++ b/tools/XBMCLive/Creator/image-creator.cfg @@ -0,0 +1,14 @@ + +[platform.i386-jaunty-xbmc] +buildroot_mirror = http://archive.ubuntu.com/ubuntu/ +buildroot_codename = jaunty +hd_use_squashfs = 1 +architecture=i386 +buildroot_extras = squashfs-tools dosfstools syslinux module-init-tools mtools busybox + +[platform.i386-intrepid-xbmc] +buildroot_mirror = http://archive.ubuntu.com/ubuntu/ +buildroot_codename = intrepid +hd_use_squashfs = 1 +architecture=i386 +buildroot_extras = squashfs-tools dosfstools syslinux module-init-tools mtools busybox diff --git a/tools/XBMCLive/Creator/mkUSBImage.sh b/tools/XBMCLive/Creator/mkUSBImage.sh new file mode 100755 index 0000000000..fc2053d409 --- /dev/null +++ b/tools/XBMCLive/Creator/mkUSBImage.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +sudo image-creator --command=create-live-usb --project-name=Intrepid --target-name=XBMCLive --image-name=XBMCLive.img + diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/exclude b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/exclude new file mode 100644 index 0000000000..cd3d05eb2c --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/exclude @@ -0,0 +1,2 @@ +boot +usr/sbin/policy-rc.d diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/base.fset b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/base.fset new file mode 100644 index 0000000000..4c822934d4 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/base.fset @@ -0,0 +1,25 @@ +[Core] +DESC=Fundamental fset that provide a basic console based system +PKGS=ubuntu-minimal usplash-theme-ubuntu pm-utils vbetool busybox-initramfs initramfs-tools dosfstools psmisc +DEPS= + +[i386-Image-Generic] +DESC=Packages needed for the i386 platform (Generic) +PKGS=linux-image +DEPS=core + +#[i386-Image] +#DESC=Packages needed for the i386 platform (i386) +#PKGS=linux-image-386 +#DEPS=core + +[Generic-X11] +DESC=Minimal X11 packages set +PKGS=xorg fluxbox +DEPS= + +[RemoteAccess] +DESC=Install SSH +PKGS=openssh-server + + diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/custom.fset b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/custom.fset new file mode 100644 index 0000000000..ae1fc62683 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/custom.fset @@ -0,0 +1,25 @@ +[DevelTools] +DESC=Application Development Toolkit +PKGS=subversion make build-essential autoconf automake gawk + +[MiscUtils] +DESC=Additional packages +PKGS=mingetty unrar nano lirc ntfs-3g hfsprogs grub dosfstools language-pack-en +#lcdproc + +[HWUtils] +DESC=Additional HW-related packages +PKGS=powernowd acpi acpi-support alsa-utils + +[OpenGL-X11] +DESC=OpenGl-enabled X11 package set +PKGS=mesa-utils libgl1-mesa-dri xlibmesa-glu + +[XBMC] +DESC=Install XBMC from PPAs +PKGS=xbmc hal + +[ModuleBuildTools] +DESC=Required packages to build kernel modules (e.g. ATI/AMD and nvidia) +PKGS=build-essential fakeroot dh-make debhelper debconf libstdc++5 dkms +# linux-headers-$(uname -r) diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/moblin.org.fset b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/moblin.org.fset new file mode 100644 index 0000000000..3fc59cf2cc --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fsets/moblin.org.fset @@ -0,0 +1,30 @@ +[GNOME-Mobile] +DESC=Subset of GNOME components for building mobile Linux stacks +PKGS=xorg xserver-xorg-input-evtouch libgl1-mesa-dri matchbox-window-manager libglib2.0-0 dbus libdbus-1-3 libdbus-glib-1-2 gconf2 libgnomevfs2-0 libgstreamer0.10-0 libtelepathy-glib0 libavahi-glib1 libgtk2.0-0 libpango1.0-0 libcairo2 libatk1.0-0 python python-dbus python-cairo python-gconf python-gst0.10 telepathy-core telepathy-mission-control gnome-icon-theme gnome-menus +# apt-get -y --force-yes install xorg xserver-xorg-input-evtouch libgl1-mesa-dri matchbox-window-manager libglib2.0-0 dbus libdbus-1-3 libdbus-glib-1-2 gconf2 libgnomevfs2-0 libgstreamer0.10-0 libbluetooth2 libtelepathy-glib0 libavahi-glib1 libgtk2.0-0 libpango1.0-0 libcairo2 libatk1.0-0 python python-dbuspython-cairo python-gconf python-gst0.10 telepathy-core telepathy-mission-control gnome-icon-theme gnome-menus +DEBUG_PKGS=xrestop + +[Ubuntu-Mobile] +DESC=Ubuntu Mobile using Hildon, and any base applications for same +PKGS=ubuntu-mobile gstreamer-dbus-media-service gstreamer0.10-x gstreamer0.10-ffmpeg gstreamer0.10-plugins-ugly gstreamer0.10-plugins-bad moblin-keyboard-manager mousepad gnome-nettool galculator moblin-applets moblin-media moblin-media-import evince hildon-libs-l10n-engb +DEBUG_PKGS=powertop +DEPS=gnome-mobile + +[Ubuntu-Staging] +DESC=Packages that are ready for inclusion into Ubuntu +PKGS=moblin-notes moblin-calc moblin-media-browser-plugin ppm moblin-clutter-home +DEBUG_PKGS= +DEPS=ubuntu-mobile + +# Not in Ubuntu yet/broken: moblin-chat moblin-applets moblin-media + +[Developer-Tools] +DESC=Tools for building source in the target (gcc, make, etc.) +PKGS=ubuntu-mobile-dev libtool autoconf automake hildon-desktop-dev man manpages curl python-dev dh-make libosso-dev +DEBUG_PKGS= +DEPS=core + +[FlashPlugin] +DESC=Adobe Flash plugin +PKGS=flashplugin-nonfree + diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fstab b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fstab new file mode 100644 index 0000000000..55cc26e1a3 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/fstab @@ -0,0 +1,3 @@ +unionfs / unionfs defaults 0 0 +proc /proc proc defaults 0 0 + diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/cd b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/cd new file mode 100755 index 0000000000..a5a4489175 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/cd @@ -0,0 +1,208 @@ +#!/bin/bash +# Live CD filesystem mounting -*- shell-script -*- + +#Function for parsing command line options with "=" in them +# get_opt("init=/sbin/init") will return "/sbin/init" +get_opt() { + echo "$@" | cut -d "=" -f 2 +} + +mountroot () +{ + CFG_FILE=/etc/moblin-initramfs.cfg + QUIET="$(grep "quiet" /proc/cmdline)" + + if [ -f ${CFG_FILE} ] + then + . ${CFG_FILE} + else + if [ "$QUIET" == "" ]; then + echo "Did not find config file: ${CFG_FILE}" + fi + sleep 5 + halt + fi + + + CMDLINE=$(cat /proc/cmdline) + + #Process command line options + XBMC_PARAMS="" + for i in ${CMDLINE}; do + case "${i}" in + xbmc\=*) + XBMC_PARAMS=$(get_opt $i) + ;; + esac + done + + AUTOGPU="$( echo $XBMC_PARAMS | grep "autogpu" )" + + if [ "$AUTOGPU" != "" ]; then + # Needs lspci in initramfs, not yet there + if [ "$QUIET" = "" ]; then + echo "found auto" + fi + XBMC_AMD="$(lspci -nn | grep 0300 | grep 1002)" + XBMC_NVIDIA="$(lspci -nn | grep 0300 | grep 10de)" + else + XBMC_NVIDIA="$( echo $XBMC_PARAMS | grep "nvidia" )" + XBMC_AMD="$( echo $XBMC_PARAMS | grep "amd" )" + fi + + BOOTMEDIAMNTPOINT=/bootmediamnt + mkdir -p $BOOTMEDIAMNTPOINT + mkdir -p /squashmnt1 + mkdir -p /squashmnt2 + mkdir -p /persistmnt + + if [ "$ROOT" != "" ]; then + if [ "$QUIET" == "" ]; then + echo "will mount root from ${ROOT}" + fi + + mount -o ro -t iso9660 ${ROOT} $BOOTMEDIAMNTPOINT 2> /dev/null + while [ ! -e $BOOTMEDIAMNTPOINT/rootfs.img ]; do + /bin/sleep 1 + if [ "$QUIET" == "" ]; then + echo "Trying again $ROOT ...." + fi + mount -o ro ${ROOT} -t iso9660 $BOOTMEDIAMNTPOINT 2> /dev/null + done + else + # Find the CD drive + found="no" + while true + do + for device in 'cdrom' 'scd0' 'scd1' 'scd2' 'scd3'; do + if [ "$QUIET" == "" ]; then + echo "Checking device /dev/${device} for installation source..." + fi + if [ -b /dev/${device} ]; then + mount -o ro -t iso9660 /dev/${device} $BOOTMEDIAMNTPOINT 2> /dev/null + if [ -e $BOOTMEDIAMNTPOINT/rootfs.img ] ; then + if [ "$QUIET" == "" ]; then + echo "Found CD Boot Drive at /dev/${device}" + fi + found="yes" + fi + umount $BOOTMEDIAMNTPOINT 2> /dev/null + if [ "$found" = "yes" ]; then + break; + fi + if [ "$QUIET" == "" ]; then + echo "/dev/${device} does not contain a rootfs" + fi + fi + done + if [ "$found" = "yes" ]; then + break; + fi + /bin/sleep 5 + done + if [ "$QUIET" == "" ]; then + echo "will mount root from /dev/${device}" + fi + + mount -o ro -t iso9660 /dev/${device} $BOOTMEDIAMNTPOINT 2> /dev/null + + while [ ! -e $BOOTMEDIAMNTPOINT/rootfs.img ]; do + /bin/sleep 1 + if [ "$QUIET" == "" ]; then + echo "Trying again /dev/${device} ...." + fi + mount -o ro -t iso9660 /dev/${device} $BOOTMEDIAMNTPOINT 2> /dev/null + done + fi + + XBMC_BOOTTORAM="$( echo $XBMC_PARAMS | grep "boottoram" )" + + if [ "$XBMC_BOOTTORAM" != "" ]; then + if [ "$QUIET" == "" ]; then + echo "Copying boot media to RAM ...." + fi + + # TODO calc size from boot media + mkdir /bootmediamntRAM + mount -t tmpfs -o size=500M none /bootmediamntRAM + cp -R $BOOTMEDIAMNTPOINT/* /bootmediamntRAM 2> /dev/null + umount $BOOTMEDIAMNTPOINT + $BOOTMEDIAMNTPOINT=/bootmediamntRAM + fi + + mount -o ro,loop -t squashfs $BOOTMEDIAMNTPOINT/rootfs.img /squashmnt1 + + if [ "$XBMC_NVIDIA" != "" ]; then + if [ -f $BOOTMEDIAMNTPOINT/restrictedDrivers.nvidia.img ]; then + if [ "$QUIET" = "" ]; then + echo "Mounting NVIDIA drivers..." + fi + mount -o ro,loop,noatime,nodiratime $BOOTMEDIAMNTPOINT/restrictedDrivers.nvidia.img /squashmnt2 + fi + else + if [ "$XBMC_AMD" != "" ]; then + if [ -f $BOOTMEDIAMNTPOINT/restrictedDrivers.amd.img ]; then + if [ "$QUIET" = "" ]; then + echo "Mounting AMD drivers..." + fi + mount -o ro,loop,noatime,nodiratime $BOOTMEDIAMNTPOINT/restrictedDrivers.amd.img /squashmnt2 + fi + else + mount -t tmpfs -o noatime,nodiratime none /squashmnt2 + + if [ "$QUIET" = "" ]; then + echo "Defaulting to Xorg autodetect..." + fi + fi + fi + + mount -t tmpfs -o noatime,nodiratime none /persistmnt + + mount -t unionfs -o dirs=/persistmnt=rw:/squashmnt2=ro:/squashmnt1=ro none ${rootmnt} + + # Correct the permissions of /: + chmod 755 "${rootmnt}" + + # Make sure the individual ro and rw mounts are accessible from within the root + # once the union is assumed as /. This makes it possible to access the + # component filesystems individually. + if [ ! -e "${rootmnt}/.bootMedia" ]; then + mkdir "${rootmnt}/.bootMedia" + fi + #mkdir "${rootmnt}/.ro1" "${rootmnt}/.ro2" "${rootmnt}/.rw" + + mount --bind $BOOTMEDIAMNTPOINT "${rootmnt}/.bootMedia" + #mount --bind /squashmnt1 "${rootmnt}/.ro1" + #mount --bind /squashmnt2 "${rootmnt}/.ro2" + #mount --bind /persistmnt "${rootmnt}/.rw" + + if [ -f $BOOTMEDIAMNTPOINT/config/fstab ]; then + cp $BOOTMEDIAMNTPOINT/config/fstab ${rootmnt}/etc/fstab +# rm $BOOTMEDIAMNTPOINT/config/fstab + fi + if [ -f $BOOTMEDIAMNTPOINT/config/shadow ]; then + cp $BOOTMEDIAMNTPOINT/config/shadow ${rootmnt}/etc +# rm $BOOTMEDIAMNTPOINT/config/fstab + chmod 640 ${rootmnt}/etc/shadow + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/rc.local ]; then + cp $BOOTMEDIAMNTPOINT/config/rc.local ${rootmnt}/etc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/xorg.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/xorg.conf ${rootmnt}/etc/X11 + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/lircd.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/lircd.conf ${rootmnt}/etc/lirc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/hardware.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/hardware.conf ${rootmnt}/etc/lirc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/interfaces ]; then + cp $BOOTMEDIAMNTPOINT/config/interfaces ${rootmnt}/etc/network + fi +} diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/disk b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/disk new file mode 100755 index 0000000000..35ed6f1600 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/disk @@ -0,0 +1,233 @@ +#!/bin/bash +# Fixed Disk filesystem mounting -*- shell-script -*- + +#Function for parsing command line options with "=" in them +# get_opt("init=/sbin/init") will return "/sbin/init" +get_opt() { + echo "$@" | cut -d "=" -f 2 +} + +mountroot () +{ + CFG_FILE=/etc/moblin-initramfs.cfg + QUIET="$(grep "quiet" /proc/cmdline)" + + if [ -f ${CFG_FILE} ] + then + . ${CFG_FILE} + else + if [ "$QUIET" == "" ]; then + echo "Did not find config file: ${CFG_FILE}" + fi + sleep 5 + halt + fi + + + CMDLINE=$(cat /proc/cmdline) + + #Process command line options + XBMC_PARAMS="" + for i in ${CMDLINE}; do + case "${i}" in + xbmc\=*) + XBMC_PARAMS=$(get_opt $i) + ;; + esac + done + + AUTOGPU="$( echo $XBMC_PARAMS | grep "autogpu" )" + + if [ "$AUTOGPU" != "" ]; then + # Needs lspci in initramfs, not yet there + if [ "$QUIET" = "" ]; then + echo "found auto" + fi + XBMC_AMD="$(lspci -nn | grep 0300 | grep 1002)" + XBMC_NVIDIA="$(lspci -nn | grep 0300 | grep 10de)" + else + XBMC_NVIDIA="$( echo $XBMC_PARAMS | grep "nvidia" )" + XBMC_AMD="$( echo $XBMC_PARAMS | grep "amd" )" + fi + + BOOTMEDIAMNTPOINT=/bootmediamnt + mkdir -p $BOOTMEDIAMNTPOINT + mkdir -p /squashmnt1 + mkdir -p /squashmnt2 + mkdir -p /persistmnt + + if [ "$ROOT" != "" ]; then + if [ "$QUIET" == "" ]; then + echo "will mount root from ${ROOT}" + fi + + mount -t vfat -o rw,umask=000 $ROOT $BOOTMEDIAMNTPOINT 2> /dev/null + while [ ! -e $BOOTMEDIAMNTPOINT/rootfs.img ]; do + /bin/sleep 1 + if [ "$QUIET" == "" ]; then + echo "Trying again $ROOT ...." + fi + mount -t vfat -o rw,umask=000 $ROOT $BOOTMEDIAMNTPOINT 2> /dev/null + done + else + # Find the disk drive + found="no" + while true + do + for device in 'sda' 'sdb' 'sdc' 'sdd' 'sde' 'sdf' 'sdg'; do + if [ "$QUIET" == "" ]; then + echo "checking device /dev/${device} for installation source..." + fi + if [ -b /dev/${device} ]; then + if [ -e /sys/block/${device}/removable ]; then + if [ "$(cat /sys/block/${device}/removable)" = "0" ]; then + if [ "$QUIET" == "" ]; then + echo "Found disk drive at /dev/${device}" + fi + mount -t vfat -o rw,umask=0 /dev/${device}1 $BOOTMEDIAMNTPOINT 2> /dev/null + if [ -f $BOOTMEDIAMNTPOINT/rootfs.img ] ; then + if [ "$QUIET" == "" ]; then + echo "Found Boot drive at /dev/${device}1" + fi + found="yes" + fi + umount $BOOTMEDIAMNTPOINT 2> /dev/null + if [ "$found" = "yes" ]; then + break; + fi + if [ "$QUIET" == "" ]; then + echo "/dev/${device}1 does not contain a rootfs" + fi + fi + fi + fi + done + if [ "$found" = "yes" ]; then + break; + fi + /bin/sleep 5 + done + if [ "$QUIET" == "" ]; then + echo "will mount root from /dev/${device}1" + fi + + mount -t vfat -o rw,umask=000 /dev/${device}1 $BOOTMEDIAMNTPOINT 2> /dev/null + + while [ ! -e $BOOTMEDIAMNTPOINT/rootfs.img ]; do + /bin/sleep 1 + if [ "$QUIET" == "" ]; then + echo "Trying again /dev/${device} ...." + fi + mount -t vfat -o rw,umask=000 /dev/${device}1 $BOOTMEDIAMNTPOINT 2> /dev/null + done + fi + + XBMC_BOOTTORAM="$( echo $XBMC_PARAMS | grep "boottoram" )" + + if [ "$XBMC_BOOTTORAM" != "" ]; then + if [ "$QUIET" == "" ]; then + echo "Copying boot media to RAM ...." + fi + + # TODO calc size from boot media + mkdir /bootmediamntRAM + mount -t tmpfs -o size=500M none /bootmediamntRAM + cp -R $BOOTMEDIAMNTPOINT/* /bootmediamntRAM 2> /dev/null + umount $BOOTMEDIAMNTPOINT + $BOOTMEDIAMNTPOINT=/bootmediamntRAM + fi + + mount -o ro,loop -t squashfs $BOOTMEDIAMNTPOINT/rootfs.img /squashmnt1 + + if [ "$XBMC_NVIDIA" != "" ]; then + if [ -f $BOOTMEDIAMNTPOINT/restrictedDrivers.nvidia.img ]; then + if [ "$QUIET" = "" ]; then + echo "Mounting NVIDIA drivers..." + fi + mount -o ro,loop,noatime,nodiratime $BOOTMEDIAMNTPOINT/restrictedDrivers.nvidia.img /squashmnt2 + fi + else + if [ "$XBMC_AMD" != "" ]; then + if [ -f $BOOTMEDIAMNTPOINT/restrictedDrivers.amd.img ]; then + if [ "$QUIET" = "" ]; then + echo "Mounting AMD drivers..." + fi + mount -o ro,loop,noatime,nodiratime $BOOTMEDIAMNTPOINT/restrictedDrivers.amd.img /squashmnt2 + fi + else + mount -t tmpfs -o noatime,nodiratime none /squashmnt2 + + if [ "$QUIET" = "" ]; then + echo "Defaulting to Xorg autodetect..." + fi + fi + fi + + if [ -f $BOOTMEDIAMNTPOINT/ext3fs.img ]; then + mount -o rw,loop,noatime,nodiratime $BOOTMEDIAMNTPOINT/ext3fs.img /persistmnt + else + mount -t tmpfs -o noatime,nodiratime none /persistmnt + fi + + mount -t unionfs -o dirs=/persistmnt=rw:/squashmnt2=ro:/squashmnt1=ro none ${rootmnt} + + # Correct the permissions of /: + chmod 755 "${rootmnt}" + + # Make sure the individual ro and rw mounts are accessible from within the root + # once the union is assumed as /. This makes it possible to access the + # component filesystems individually. + if [ ! -e "${rootmnt}/.bootMedia" ]; then + mkdir "${rootmnt}/.bootMedia" + fi + #mkdir "${rootmnt}/.ro1" "${rootmnt}/.ro2" "${rootmnt}/.rw" + + mount --bind $BOOTMEDIAMNTPOINT "${rootmnt}/.bootMedia" + #mount --bind /squashmnt1 "${rootmnt}/.ro1" + #mount --bind /squashmnt2 "${rootmnt}/.ro2" + #mount --bind /persistmnt "${rootmnt}/.rw" + + if [ -f $BOOTMEDIAMNTPOINT/config/fstab ]; then + cp $BOOTMEDIAMNTPOINT/config/fstab ${rootmnt}/etc/fstab + rm $BOOTMEDIAMNTPOINT/config/fstab + fi + + if [ -f $BOOTMEDIAMNTPOINT/ext3fs.img ]; then + XBMC_TEMPFS="$(echo $XBMC_PARAMS | grep "tempfs" )" + if [ "$XBMC_TEMPFS" != "" ]; then + ALREADY_DONE="$(cat ${rootmnt}/etc/fstab | grep "tmpfs" )" + if [ "$ALREADY_DONE" = "" ]; then + echo "tmpfs /var/log/apt tmpfs defaults 0 0" >> ${rootmnt}/etc/fstab + echo "tmpfs /var/log tmpfs defaults 0 0" >> ${rootmnt}/etc/fstab + echo "tmpfs /tmp tmpfs defaults 0 0" >> ${rootmnt}/etc/fstab + echo "tmpfs /var/tmp tmpfs defaults 0 0" >> ${rootmnt}/etc/fstab + fi + fi + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/shadow ]; then + cp $BOOTMEDIAMNTPOINT/config/shadow ${rootmnt}/etc + rm $BOOTMEDIAMNTPOINT/config/fstab + chmod 640 ${rootmnt}/etc/shadow + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/rc.local ]; then + cp $BOOTMEDIAMNTPOINT/config/rc.local ${rootmnt}/etc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/xorg.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/xorg.conf ${rootmnt}/etc/X11 + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/lircd.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/lircd.conf ${rootmnt}/etc/lirc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/hardware.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/hardware.conf ${rootmnt}/etc/lirc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/interfaces ]; then + cp $BOOTMEDIAMNTPOINT/config/interfaces ${rootmnt}/etc/network + fi +} diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/hooks/mobile b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/hooks/mobile new file mode 100755 index 0000000000..7091bcce3a --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/hooks/mobile @@ -0,0 +1,33 @@ +#!/bin/sh + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +# get pre-requisites +prereqs) + prereqs + exit 0 + ;; +esac + +# These paths are inside the target filesystem +. /usr/share/initramfs-tools/hook-functions +# These source files are put into the target's /etc/initramfs-tools/ by +# InstallImage.py + +# If we have a generated config file, copy it +CFG_FILE=/etc/initramfs-tools/moblin-initramfs.cfg +if [ -f ${CFG_FILE} ] +then + cp -f ${CFG_FILE} ${DESTDIR}/etc/ +fi + +cp -f /etc/initramfs-tools/usplash.conf ${DESTDIR}/etc/usplash.conf +copy_exec /etc/initramfs-tools/usb /scripts/usb +copy_exec /etc/initramfs-tools/disk /scripts/disk +copy_exec /etc/initramfs-tools/cd /scripts/cd diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/initramfs.conf b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/initramfs.conf new file mode 100644 index 0000000000..b0d1dc018c --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/initramfs.conf @@ -0,0 +1,54 @@ +# +# initramfs.conf +# Configuration file for mkinitramfs(8). See initramfs.conf(5). +# + +# +# MODULES: [ most | netboot | dep | list ] +# +# most - Add all framebuffer, acpi, filesystem, and harddrive drivers. +# +# dep - Try and guess which modules to load. +# +# netboot - Add the base modules, network modules, but skip block devices. +# +# list - Only include modules from the 'additional modules' list +# + +MODULES=most + +# BUSYBOX: [ y | n ] +# +# Use busybox if available. +# + +BUSYBOX=y + +# +# NFS Section of the config. +# + +# +# BOOT: [ local | nfs ] +# +# local - Boot off of local media (harddrive, USB stick). +# +# nfs - Boot using an NFS drive as the root of the drive. +# + +BOOT=local + +# +# DEVICE: ... +# +# Specify the network interface, like eth0 +# + +DEVICE=eth0 + +# +# NFSROOT: [ auto | HOST:MOUNT ] +# + +NFSROOT=auto + diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/modules b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/modules new file mode 100644 index 0000000000..a28aa1a052 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/modules @@ -0,0 +1,32 @@ +usbcore +asix +nfs +hid +usbhid +ehci-hcd +uhci-hcd +ide-core +scsi_mod +sd_mod +libusual +usb-storage +unionfs +squashfs +fat +vfat +nls_cp437 +nls_iso8859-1 +loop +mbcache +jbd +ext2 +ext3 +fbcon +cdrom +isofs +sg +ata_generic +#sr_mod +#sd_mod +libata + diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/nand b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/nand new file mode 100755 index 0000000000..59d785f159 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/nand @@ -0,0 +1,8 @@ +#!/bin/sh +# nand filesystem mounting -*- shell-script -*- +# current is only the hack shell inside the initrd + +mountroot () +{ + /bin/bash +} diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/usb b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/usb new file mode 100755 index 0000000000..e12e608479 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/usb @@ -0,0 +1,233 @@ +#!/bin/bash +# Live USB filesystem mounting -*- shell-script -*- + +#Function for parsing command line options with "=" in them +# get_opt("init=/sbin/init") will return "/sbin/init" +get_opt() { + echo "$@" | cut -d "=" -f 2 +} + +mountroot () +{ + CFG_FILE=/etc/moblin-initramfs.cfg + QUIET="$(grep "quiet" /proc/cmdline)" + + if [ -f ${CFG_FILE} ] + then + . ${CFG_FILE} + else + if [ "$QUIET" == "" ]; then + echo "Did not find config file: ${CFG_FILE}" + fi + sleep 5 + halt + fi + + + CMDLINE=$(cat /proc/cmdline) + + #Process command line options + XBMC_PARAMS="" + for i in ${CMDLINE}; do + case "${i}" in + xbmc\=*) + XBMC_PARAMS=$(get_opt $i) + ;; + esac + done + + AUTOGPU="$( echo $XBMC_PARAMS | grep "autogpu" )" + + if [ "$AUTOGPU" != "" ]; then + # Needs lspci in initramfs, not yet there + if [ "$QUIET" = "" ]; then + echo "found auto" + fi + XBMC_AMD="$(lspci -nn | grep 0300 | grep 1002)" + XBMC_NVIDIA="$(lspci -nn | grep 0300 | grep 10de)" + else + XBMC_NVIDIA="$( echo $XBMC_PARAMS | grep "nvidia" )" + XBMC_AMD="$( echo $XBMC_PARAMS | grep "amd" )" + fi + + BOOTMEDIAMNTPOINT=/bootmediamnt + mkdir -p $BOOTMEDIAMNTPOINT + mkdir -p /squashmnt1 + mkdir -p /squashmnt2 + mkdir -p /persistmnt + + if [ "$ROOT" != "" ]; then + if [ "$QUIET" == "" ]; then + echo "will mount root from ${ROOT}" + fi + + mount -t vfat -o rw,umask=000 $ROOT $BOOTMEDIAMNTPOINT 2> /dev/null + while [ ! -e $BOOTMEDIAMNTPOINT/rootfs.img ]; do + /bin/sleep 1 + if [ "$QUIET" == "" ]; then + echo "Trying again $ROOT ...." + fi + mount -t vfat -o rw,umask=000 $ROOT $BOOTMEDIAMNTPOINT 2> /dev/null + done + else + # Find the USB flash drive + found="no" + while true + do + for device in 'sda' 'sdb' 'sdc' 'sdd' 'sde' 'sdf' 'sdg'; do + if [ "$QUIET" == "" ]; then + echo "checking device /dev/${device} for installation source..." + fi + if [ -b /dev/${device} ]; then + if [ -e /sys/block/${device}/removable ]; then + if [ "$(cat /sys/block/${device}/removable)" = "1" ]; then + if [ "$QUIET" == "" ]; then + echo "Found USB flash drive at /dev/${device}" + fi + mount -t vfat -o rw,umask=0 /dev/${device}1 $BOOTMEDIAMNTPOINT 2> /dev/null + if [ -f $BOOTMEDIAMNTPOINT/rootfs.img ] ; then + if [ "$QUIET" == "" ]; then + echo "Found Boot drive at /dev/${device}1" + fi + found="yes" + fi + umount $BOOTMEDIAMNTPOINT 2> /dev/null + if [ "$found" = "yes" ]; then + break; + fi + if [ "$QUIET" == "" ]; then + echo "/dev/${device}1 does not contain a rootfs" + fi + fi + fi + fi + done + if [ "$found" = "yes" ]; then + break; + fi + /bin/sleep 5 + done + if [ "$QUIET" == "" ]; then + echo "will mount root from /dev/${device}1" + fi + + mount -t vfat -o rw,umask=000 /dev/${device}1 $BOOTMEDIAMNTPOINT 2> /dev/null + + while [ ! -e $BOOTMEDIAMNTPOINT/rootfs.img ]; do + /bin/sleep 1 + if [ "$QUIET" == "" ]; then + echo "Trying again /dev/${device} ...." + fi + mount -t vfat -o rw,umask=000 /dev/${device}1 $BOOTMEDIAMNTPOINT 2> /dev/null + done + fi + + XBMC_BOOTTORAM="$( echo $XBMC_PARAMS | grep "boottoram" )" + + if [ "$XBMC_BOOTTORAM" != "" ]; then + if [ "$QUIET" == "" ]; then + echo "Copying boot media to RAM ...." + fi + + # TODO calc size from boot media + mkdir /bootmediamntRAM + mount -t tmpfs -o size=500M none /bootmediamntRAM + cp -R $BOOTMEDIAMNTPOINT/* /bootmediamntRAM 2> /dev/null + umount $BOOTMEDIAMNTPOINT + $BOOTMEDIAMNTPOINT=/bootmediamntRAM + fi + + mount -o ro,loop -t squashfs $BOOTMEDIAMNTPOINT/rootfs.img /squashmnt1 + + if [ "$XBMC_NVIDIA" != "" ]; then + if [ -f $BOOTMEDIAMNTPOINT/restrictedDrivers.nvidia.img ]; then + if [ "$QUIET" = "" ]; then + echo "Mounting NVIDIA drivers..." + fi + mount -o ro,loop,noatime,nodiratime $BOOTMEDIAMNTPOINT/restrictedDrivers.nvidia.img /squashmnt2 + fi + else + if [ "$XBMC_AMD" != "" ]; then + if [ -f $BOOTMEDIAMNTPOINT/restrictedDrivers.amd.img ]; then + if [ "$QUIET" = "" ]; then + echo "Mounting AMD drivers..." + fi + mount -o ro,loop,noatime,nodiratime $BOOTMEDIAMNTPOINT/restrictedDrivers.amd.img /squashmnt2 + fi + else + mount -t tmpfs -o noatime,nodiratime none /squashmnt2 + + if [ "$QUIET" = "" ]; then + echo "Defaulting to Xorg autodetect..." + fi + fi + fi + + if [ -f $BOOTMEDIAMNTPOINT/ext3fs.img ]; then + mount -o rw,loop,noatime,nodiratime $BOOTMEDIAMNTPOINT/ext3fs.img /persistmnt + else + mount -t tmpfs -o noatime,nodiratime none /persistmnt + fi + + mount -t unionfs -o dirs=/persistmnt=rw:/squashmnt2=ro:/squashmnt1=ro none ${rootmnt} + + # Correct the permissions of /: + chmod 755 "${rootmnt}" + + # Make sure the individual ro and rw mounts are accessible from within the root + # once the union is assumed as /. This makes it possible to access the + # component filesystems individually. + if [ ! -e "${rootmnt}/.bootMedia" ]; then + mkdir "${rootmnt}/.bootMedia" + fi + #mkdir "${rootmnt}/.ro1" "${rootmnt}/.ro2" "${rootmnt}/.rw" + + mount --bind $BOOTMEDIAMNTPOINT "${rootmnt}/.bootMedia" + #mount --bind /squashmnt1 "${rootmnt}/.ro1" + #mount --bind /squashmnt2 "${rootmnt}/.ro2" + #mount --bind /persistmnt "${rootmnt}/.rw" + + if [ -f $BOOTMEDIAMNTPOINT/config/fstab ]; then + cp $BOOTMEDIAMNTPOINT/config/fstab ${rootmnt}/etc/fstab + rm $BOOTMEDIAMNTPOINT/config/fstab + fi + + if [ -f $BOOTMEDIAMNTPOINT/ext3fs.img ]; then + XBMC_TEMPFS="$(echo $XBMC_PARAMS | grep "tempfs" )" + if [ "$XBMC_TEMPFS" != "" ]; then + ALREADY_DONE="$(cat ${rootmnt}/etc/fstab | grep "tmpfs" )" + if [ "$ALREADY_DONE" = "" ]; then + echo "tmpfs /var/log/apt tmpfs defaults 0 0" >> ${rootmnt}/etc/fstab + echo "tmpfs /var/log tmpfs defaults 0 0" >> ${rootmnt}/etc/fstab + echo "tmpfs /tmp tmpfs defaults 0 0" >> ${rootmnt}/etc/fstab + echo "tmpfs /var/tmp tmpfs defaults 0 0" >> ${rootmnt}/etc/fstab + fi + fi + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/shadow ]; then + cp $BOOTMEDIAMNTPOINT/config/shadow ${rootmnt}/etc + rm $BOOTMEDIAMNTPOINT/config/shadow + chmod 640 ${rootmnt}/etc/shadow + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/rc.local ]; then + cp $BOOTMEDIAMNTPOINT/config/rc.local ${rootmnt}/etc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/xorg.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/xorg.conf ${rootmnt}/etc/X11 + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/lircd.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/lircd.conf ${rootmnt}/etc/lirc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/hardware.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/hardware.conf ${rootmnt}/etc/lirc + fi + + if [ -f $BOOTMEDIAMNTPOINT/config/interfaces ]; then + cp $BOOTMEDIAMNTPOINT/config/interfaces ${rootmnt}/etc/network + fi +} diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/usplash.conf b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/usplash.conf new file mode 100644 index 0000000000..e4e25a1ed7 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/initramfs/usplash.conf @@ -0,0 +1,3 @@ +# Usplash configuration file +xres=1024 +yres=768 diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/install.sh b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/install.sh new file mode 100755 index 0000000000..949835595c --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/install.sh @@ -0,0 +1,271 @@ +#!/bin/bash + +# This is the script that will be placed onto the USB flash drive, that will +# run on bootup to install the software onto the device. + +# I want us to error out if we use an undefined variable, so we will catch errors. +set -u + +# Read in our config file, if it exists +if [ -f /install.cfg ] +then + echo "Sourcing ./install.cfg" + . /install.cfg +else + echo "ERROR: ./install.cfg not found!" + echo "In script: $0 $*" + sleep 10 + halt +fi + +#################### usplash functions start #################################### +SPLASHWRITE=0 +# Determine if we have usplash_write available +type usplash_write > /dev/null 2>&1 && SPLASHWRITE=1 + +# Disable usplash, since we want text mode +SPLASHWRITE=0 + +BOOTDEVICE=$1 + +# show the progress at status bar. +# $1 = 0-100 +splash_progress(){ + splash_write "PROGRESS $1" + return 0 +} +# display the text no matter whether verbose is set or not +splash_display(){ + echo "$@" + splash_write "TEXT-URGENT $@" + return 0 +} +# set the splash delay time +splash_delay(){ + splash_write "TIMEOUT $1" + return 0 +} +# call the usplash_write command, if enabled +splash_write(){ + if [ "${SPLASHWRITE}" -eq 1 ] + then + usplash_write "$@" + else: + echo "ussplash_write: $@" + fi +} +####################### usplash functions end ############################### + +splash_delay 200 +splash_display 'INSTALL..........' + +pre_scsi_disk_number=$( ls /sys/class/scsi_disk | wc -l) +found=no +# Find the install disk +while true; do + for device in 'hda' 'hdb' 'sda' 'sdb' + do + echo "checking device: /dev/${device} for installation target" + if [ -e /sys/block/${device}/removable ]; then + if [ "$(cat /sys/block/${device}/removable)" = "0" ]; then + if cat /proc/mounts | grep /dev/${device} + then + continue + else + found="yes" + splash_display "found harddisk at /dev/${device}" + break + fi + fi + fi + done + if [ "$found" = "yes" ]; then + break; + fi + /bin/sleep 5 + echo "Did not find an installation target device" +done +echo "will install to /dev/${device}" + +blocks=`fdisk -s /dev/${device}` +cylinders=$((blocks*2/63/255)) + +splash_display "Deleting Partition Table on /dev/${device} ..." +splash_delay 200 +dd if=/dev/zero of=/dev/${device} bs=512 count=2 +sync +splash_progress 5 +splash_delay 10 + +splash_display "Creating New Partiton Table on /dev/${device} ..." +splash_delay 200 + +fdisk /dev/${device} <<EOF +n +p +1 + +$((boot_partition_size*1000/8192)) +n +p +2 + +$((cylinders-((swap_partition_size+fat32_partition_size)*1000/8192))) +a +1 +w +EOF + +if [ $swap_partition_size -ne 0 ] +then + fdisk /dev/${device} <<EOF +n +p +3 + +$((cylinders-(fat32_partition_size*1000/8192))) +t +3 +82 +w +EOF + if [ $fat32_partition_size -gt 0 ] + then + fdisk /dev/${device} <<EOF +n +p +4 + + +t +4 +c +w +EOF + fi +else if [ $fat32_partition_size -gt 0 ] + then + fdisk /dev/${device} <<EOF +n +p +3 + + +t +3 +c +w +EOF + fi +fi + +sync +splash_progress 10 +splash_delay 10 + +splash_display "Formatting /dev/${device}1 w/ ext3..." +splash_delay 200 +mkfs.ext3 /dev/${device}1 +sync +splash_progress 20 +splash_delay 10 + +splash_display "Formatting /dev/${device}2 w/ ext3..." +splash_delay 200 +mkfs.ext3 /dev/${device}2 +sync +splash_progress 60 +splash_delay 10 + +if [ $swap_partition_size -ne 0 ] +then + splash_display "Formatting /dev/${device}3 w/ swap..." + splash_delay 1000 + mkswap /dev/${device}3 + if [ $fat32_partition_size -ne 0 ] + then + splash_display "Formatting /dev/${device}4 w/ vfat..." + splash_delay 1000 + mkfs.vfat /dev/${device}4 + fi +else if [ $fat32_partition_size -ne 0 ] + then + splash_display "Formatting /dev/${device}3 w/ vfat..." + splash_delay 1000 + mkfs.vfat /dev/${device}3 + fi +fi +sync +splash_progress 65 +splash_delay 10 + +splash_display 'Mounting partitions...' +splash_delay 200 +mkdir /tmp/boot +mount -o loop -t squashfs /tmp/install/bootfs.img /tmp/boot + +mount /dev/${device}2 /mnt +mkdir /mnt/boot +mount /dev/${device}1 /mnt/boot +splash_progress 70 +splash_delay 10 + +splash_display 'Copying system files onto hard disk drive...' +splash_delay 200 +cp -av /tmp/boot /mnt + +if [ "${use_squashfs}" -eq 1 ] +then + echo "Copying squashfs filesystem into place..." + cp -v /tmp/install/rootfs.img /mnt/boot +else + echo "Setting up NON squashfs filesystem..." + mkdir /tmp/root + mount -o loop -t squashfs /tmp/install/rootfs.img /tmp/root + splash_display 'Copying system ROOT onto hard disk drive...' + cp -av /tmp/root/. /mnt +fi +/usr/sbin/grub-install --root-directory=/mnt /dev/${device} +splash_progress 90 +splash_delay 10 + +splash_display 'Unmounting partitions...' +splash_delay 200 + +umount /mnt/boot +umount /mnt +umount /tmp/boot +umount /tmp/install + +splash_progress 95 +splash_delay 10 +sleep 1 +splash_delay 6000 +splash_display "Install Successfully" +# need to call reboot --help and let file system cache hold it, since we will +# unplug USB disk soon, and after that, reboot command will not be accessible. +# The reason why reboot still works sometimes without this is the whole +# "rootfs.img" is cached when it is copied to HD. But when rootfs.img become +# bigger and bigger the whole "rootfs.img" will not be able to fully cached (we +# have found this issue when creating big installation) +reboot --help > /dev/null 2>&1 + + +case $BOOTDEVICE in +usb) + splash_display "Unplug USB Key, System Will Reboot Automatically" + while [ $pre_scsi_disk_number = $(ls /sys/class/scsi_disk | wc -l) ] + do + sleep 1 + done + ;; +cd) + splash_display "Sysstem Will Reboot after 5 seconds" + sleep 5 + ;; +esac + +splash_progress 100 +splash_delay 1 + +reboot -f diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/nand.sh b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/nand.sh new file mode 100755 index 0000000000..6e941794f6 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/nand.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# $1 is cmdline path +# $2 is bootstub path +# $3 is bzImage path +# $4 is initrd path +# $5 is rootfs path +# $6 is nand image size in MB +# $7 is boot image (content of logical partition1, DEBUG for ESL) +# $8 is output nand image (logical partition1 +logical partition2) + +if [ $# -lt 8 ]; then + echo "usage: nand.sh cmdline_path bootstub_path bzImage_path initrd_path rootfs_path img_size mem_size boot_path img_path" + exit 1 +fi + +if [ ! -e "$1" ]; then + echo "cmdline file not exist!" + exit 1 +fi + +if [ ! -e "$2" ]; then + echo "bootstub file not exist!" + exit 1 +fi + +if [ ! -e "$3" ]; then + echo "no kernel bzImage file!" + exit 1 +fi + +if [ ! -e "$4" ]; then + echo "no initrd file!" + exit 1 +fi + +if [ ! -d "$5" ]; then + echo "no rootfs path!" + exit 1 +fi + +# convert a decimal number to the sequence that printf could recognize to output binary integer (not ASCII) +binstring () +{ + h1=$(($1%256)) + h2=$((($1/256)%256)) + h3=$((($1/256/256)%256)) + h4=$((($1/256/256/256)%256)) + binstr=`printf "\x5cx%02x\x5cx%02x\x5cx%02x\x5cx%02x" $h1 $h2 $h3 $h4` +} + +# add cmdline to the first part of boot image +cat $1 /dev/zero | dd of=$7 bs=4096 count=1 + +# append bootstub +cat $2 /dev/zero | dd of=$7 bs=4096 count=1 seek=1 + +# append bzImage and initrd +cat $3 $4 | dd of=$7 bs=4096 seek=2 + +# fill bzImage_size and initrd_size +binstring `stat -c %s $3` +printf $binstr | dd of=$7 bs=1 seek=256 conv=notrunc +binstring `stat -c %s $4` +printf $binstr | dd of=$7 bs=1 seek=260 conv=notrunc + +# quick test by exiting here, only get *.bin.boot file for ESL +echo 'I will exit here to only produce [name].bin.boot file for ESL testing' +exit 0 + +# prepare the final image contains two logical partitions +HEADERS=4 +SECTORS=16 + +dd if=/dev/zero of=$8 bs=$((1024*1024)) count=$6 +size=`stat -c %s $7` +units=${HEADERS}*${SECTORS}*512 + +# partition1_cylinders actually contain the partition table's 1 track of sectors +partition1_cylinders=$(((size + units-1 + SECTORS*512)/units)) +echo "logical partition1 is $partition1_cylinders" +/sbin/fdisk -C $(($6*1024*1024/units)) -H ${HEADERS} -S ${SECTORS} $8 <<EOF +n +p +1 + +$partition1_cylinders +n +p +2 + + +w +EOF + +# ok, is time to slice the disk to pieces :-) +# first, it the logical partition table +dd if=$8 bs=512 count=${SECTORS} of=$8-0 +# then the logical partition1 +dd if=$8 bs=512 count=$((partition1_cylinders*HEADERS*SECTORS-SECTORS)) skip=${SECTORS} of=$8-1 +# then all the rest are for partition2 +dd if=$8 bs=512 skip=$((partition1_cylinders*HEADERS*SECTORS)) of=$8-2 + +# prepare the logical partition1 +dd if=$7 of=$8-1 bs=4096 conv=notrunc +# prepare the logical partition2, format it to ext3 and copy rootfs onto it +/sbin/mkfs -t ext3 $8-2 <<EOF +y +EOF +sudo mkdir -p /tmp/$(basename $8)-2.mnt +sudo mount -o loop $8-2 /tmp/$(basename $8)-2.mnt +echo "cp -a $5/* /tmp/$(basename $8)-2.mnt" +sudo cp -av $5/* /tmp/$(basename $8)-2.mnt +sudo umount $8-2 +sudo rm -rf /tmp/$(basename $8)-2.mnt + +# ok, is time to combine the slices +cat $8-0 $8-1 $8-2 | dd of=$8 bs=4096 +rm -rf $8-0 $8-1 $8-2 + +# done +echo "done with creating NAND image : whole image file (boot partition + rootfs partition)is $8, the boot image file is $7 (for ESL)" diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/sources/ubuntu.com.list b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/sources/ubuntu.com.list new file mode 100644 index 0000000000..ecc8efd998 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/sources/ubuntu.com.list @@ -0,0 +1,10 @@ +deb http://archive.ubuntu.com/ubuntu/ jaunty main restricted universe multiverse + +deb http://archive.canonical.com/ubuntu jaunty partner + +deb http://security.ubuntu.com/ubuntu/ jaunty-security universe main multiverse restricted + +deb http://archive.ubuntu.com/ubuntu/ jaunty-updates universe main multiverse restricted +deb http://archive.ubuntu.com/ubuntu/ jaunty-backports universe main multiverse restricted + + diff --git a/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/sources/xbmc.org.list b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/sources/xbmc.org.list new file mode 100644 index 0000000000..83e6a2a1c9 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/i386-jaunty-xbmc/sources/xbmc.org.list @@ -0,0 +1,4 @@ +deb http://ppa.launchpad.net/team-xbmc-svn/ppa/ubuntu/ jaunty main +# deb http://ppa.launchpad.net/xbmc-addons/ppa/ubuntu/ jaunty main + + diff --git a/tools/XBMCLive/Creator/platforms/platforms.cfg b/tools/XBMCLive/Creator/platforms/platforms.cfg new file mode 100644 index 0000000000..2008646712 --- /dev/null +++ b/tools/XBMCLive/Creator/platforms/platforms.cfg @@ -0,0 +1,4 @@ +[i386-jaunty-xbmc] +description = Generic i386 platform using Jaunty +package_manager = apt +target_os = ubuntu diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/COPYING b/tools/XBMCLive/USplashThemes/pulsating-logo/COPYING new file mode 100644 index 0000000000..10926e87f1 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 3 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, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. + diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/Makefile b/tools/XBMCLive/USplashThemes/pulsating-logo/Makefile new file mode 100644 index 0000000000..45a976db46 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/Makefile @@ -0,0 +1,29 @@ +CC=gcc +CFLAGS=-g -Wall -fPIC +LDFLAGS= +INCLUDES= +COMPILE = $(CC) $(INCLUDES) $(CFLAGS) +LINK = $(CC) $(CFLAGS) $(LDFLAGS) + +xbmc-splash.so: xbmc_1920_1200.png.c.o xbmc_1920_1080.png.c.o xbmc_1680_1050.png.c.o xbmc_1440_900.png.c.o xbmc_1280_1024.png.c.o xbmc_1366_768.png.c.o xbmc_1280_720.png.c.o xbmc_1024_768.png.c.o xbmc_800_600.png.c.o xbmc_640_480.png.c.o xbmc_spinner.png.c.o xbmc-splash.c.o helvB10.bdf.c.o + $(COMPILE) -shared -o $@ $^ + +%.c.o: %.c + $(COMPILE) -o $@ -c $< + +%.png.c: %.png + pngtousplash $< > $@ + +%.bdf.c: %.bdf + bdftousplash $< > $@ + +clean: + rm -f *.png.c *.bdf.c *.c.o *.so + +install: + cp xbmc-splash.so /usr/lib/usplash + rm /etc/alternatives/usplash-artwork.so + ln -s /usr/lib/usplash/xbmc-splash.so /etc/alternatives/usplash-artwork.so + dpkg-reconfigure usplash +test: + usplash -c diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/README b/tools/XBMCLive/USplashThemes/pulsating-logo/README new file mode 100644 index 0000000000..56ccd6a6bb --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/README @@ -0,0 +1,43 @@ +XBMC Splash - Black +==================== + +This is my 3rd attempt at a decent USplash theme for my linux XBMC HTPC (and possibly yours too :). + +It cotains several resolutions: +640x480 (Currently not usable) +800x600 +1024x768 +1280x720 +1366x768 +1280x1024 +1440x900 +1920x1080 +1920x1200 + +Those might work depending on the use (and support for your vid card) of the UVESAFB kernel module. +On my system (Radeon 3850 and 17" LCD) I was able to use 1024x768 and 1280x1024. + + +Build Instructions +================================================== +For Ubuntu, you will need the following packages installed: +build-essential, libusplash-dev, usplash-theme-ubuntu. + +As it updates the initrd image, you'll need to work as root (or sudo). + +1. extract the package. +2. make (or make -j2 -for a faster compile) +3. backup your current ubuntu usplash: sudo cp /usr/lib/usplash/usplash-theme-ubuntu.so ~/ +4. replace it with your brand new xbmc usplash: sudo cp ./xbmc-splash.so /usr/lib/usplash/usplash-theme-ubuntu.so +5. update the initrd image: sudo update-initramfs -u +6. reboot +7. enjoy. + + +Feel free to visit my blog for some more XBMC related Usplashes: http://du-duke.blogspot.com + +Thank yous +================================================== +For anyone who has ever tackled this damned USplash :) +For all the themes at gnome-looks +kilo323@yahoo.com for the spinner code. diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/helvB10.bdf b/tools/XBMCLive/USplashThemes/pulsating-logo/helvB10.bdf new file mode 100644 index 0000000000..fe548f547e --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/helvB10.bdf @@ -0,0 +1,3305 @@ +STARTFONT 2.1 +FONT -Adobe-Helvetica-Bold-R-Normal--10-100-75-75-P-60-ISO8859-1 +SIZE 10 75 75 +FONTBOUNDINGBOX 11 13 -1 -2 +COMMENT $XConsortium: helvB10.bdf,v 1.13 95/01/26 18:01:30 gildea Exp $ +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 28 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 10 +POINT_SIZE 100 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 60 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +CAP_HEIGHT 8 +X_HEIGHT 6 +FONT_ASCENT 10 +FONT_DESCENT 2 +FACE_NAME "Helvetica Bold" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold" +_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991" +DEFAULT_CHAR 32 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD" +FULL_NAME "Helvetica Bold" +ENDPROPERTIES +CHARS 229 +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 8 1 0 +BITMAP +C0 +C0 +C0 +C0 +80 +80 +00 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 5 0 +BBX 3 3 1 5 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +50 +50 +FC +50 +F8 +A0 +A0 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 -1 +BITMAP +20 +70 +A8 +E0 +70 +38 +A8 +70 +20 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +62 +B4 +68 +10 +10 +2C +56 +8C +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +70 +D8 +D8 +70 +DE +CC +DC +76 +ENDCHAR +STARTCHAR quoteright +ENCODING 39 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 5 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +20 +60 +40 +C0 +C0 +C0 +C0 +40 +60 +20 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +80 +C0 +40 +60 +60 +60 +60 +40 +C0 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +A0 +40 +A0 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +30 +30 +FC +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 4 0 -2 +BITMAP +40 +40 +40 +80 +ENDCHAR +STARTCHAR minus +ENCODING 45 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 2 1 0 +BITMAP +80 +80 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +10 +10 +20 +20 +40 +40 +80 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 4 8 0 0 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +30 +18 +18 +D8 +70 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 8 0 0 +BITMAP +18 +38 +58 +58 +98 +FC +18 +18 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F0 +18 +98 +D8 +70 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +C0 +F0 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +18 +18 +30 +30 +30 +60 +60 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +70 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +D8 +78 +18 +D8 +70 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 1 6 1 0 +BITMAP +80 +80 +00 +00 +80 +80 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 8 0 -2 +BITMAP +40 +40 +00 +00 +40 +40 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 4 5 0 1 +BITMAP +30 +60 +C0 +60 +30 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 5 3 0 2 +BITMAP +F8 +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 4 5 0 1 +BITMAP +C0 +60 +30 +60 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +30 +60 +60 +00 +60 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 11 0 +BBX 10 9 0 -2 +BITMAP +1F00 +6080 +4D40 +9240 +A240 +A480 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +F8 +CC +CC +CC +F8 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3C +66 +C2 +C0 +C0 +C2 +66 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F0 +D8 +CC +CC +CC +CC +D8 +F0 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3C +66 +C2 +C0 +CE +C6 +66 +3A +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +CC +CC +CC +FC +CC +CC +CC +CC +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +18 +18 +18 +18 +18 +18 +D8 +70 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +CC +D8 +F0 +E0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +CC +F8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 9 0 -1 +BITMAP +38 +6C +C6 +C6 +C6 +D6 +6C +3C +02 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +CC +F8 +CC +CC +CC +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +78 +CC +E0 +78 +1C +8C +CC +78 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +C6 +6C +6C +6C +38 +38 +10 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 10 8 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +6D80 +6D80 +7F80 +3300 +2100 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +C6 +6C +38 +38 +6C +C6 +C6 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +C3 +C3 +66 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +0C +18 +30 +70 +60 +C0 +FC +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +E0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +E0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +80 +80 +40 +40 +20 +20 +10 +10 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +E0 +60 +60 +60 +60 +60 +60 +60 +60 +E0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 5 4 0 4 +BITMAP +20 +70 +D8 +88 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 1 0 -2 +BITMAP +FC +ENDCHAR +STARTCHAR quoteleft +ENCODING 96 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 5 +BITMAP +40 +80 +C0 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 6 0 0 +BITMAP +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +F0 +D8 +C8 +C8 +D8 +F0 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 5 0 +BBX 4 6 0 0 +BITMAP +70 +D0 +C0 +C0 +D0 +70 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +18 +18 +78 +D8 +98 +98 +D8 +78 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +70 +C0 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +68 +D8 +98 +98 +D8 +78 +18 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +F0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 10 0 -2 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +80 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 8 0 0 +BITMAP +C0 +C0 +D8 +F0 +E0 +F0 +D8 +CC +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 9 0 +BBX 8 6 0 0 +BITMAP +B6 +DB +DB +DB +DB +DB +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +B0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +B0 +D8 +C8 +C8 +D8 +F0 +C0 +C0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +68 +D8 +98 +98 +D8 +78 +18 +18 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 4 0 +BBX 4 6 0 0 +BITMAP +B0 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +70 +18 +D8 +70 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +C0 +E0 +C0 +C0 +C0 +C0 +60 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +D8 +D8 +D8 +50 +70 +20 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 6 0 0 +BITMAP +D6 +D6 +D6 +6C +6C +6C +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 6 0 0 +BITMAP +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +F8 +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 10 0 -2 +BITMAP +30 +60 +60 +60 +C0 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 3 0 +BBX 1 10 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 10 0 -2 +BITMAP +C0 +60 +60 +60 +30 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 2 0 2 +BITMAP +6C +D8 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 8 1 -2 +BITMAP +C0 +00 +40 +40 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 -1 +BITMAP +10 +70 +D8 +A0 +A0 +D8 +70 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +38 +68 +60 +F0 +60 +60 +68 +D8 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 1 +BITMAP +D8 +70 +D8 +D8 +70 +D8 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +84 +CC +48 +78 +FC +30 +FC +30 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 3 0 +BBX 1 10 1 -2 +BITMAP +80 +80 +80 +80 +00 +00 +80 +80 +80 +80 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 10 0 -2 +BITMAP +70 +C8 +E0 +70 +98 +C8 +70 +38 +98 +70 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 7 +BITMAP +A0 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +42 +99 +A5 +A1 +9D +42 +3C +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 5 0 +BBX 3 5 1 3 +BITMAP +E0 +20 +A0 +00 +E0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 3 0 1 +BITMAP +6C +D8 +6C +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +F8 +08 +08 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +42 +BD +A5 +B9 +A5 +42 +3C +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 7 +BITMAP +E0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 4 0 +BBX 3 3 1 4 +BITMAP +60 +A0 +C0 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +30 +30 +FC +30 +30 +00 +FC +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 3 +BITMAP +60 +A0 +40 +E0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 3 +BITMAP +E0 +40 +20 +C0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 7 +BITMAP +40 +80 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +D8 +D8 +D8 +D8 +D8 +E8 +C0 +C0 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 10 0 -2 +BITMAP +7C +E8 +E8 +E8 +68 +28 +28 +28 +28 +28 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 1 0 3 +BITMAP +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 -2 +BITMAP +40 +C0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 4 0 3 +BITMAP +40 +C0 +40 +40 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 5 0 +BBX 3 5 1 3 +BITMAP +E0 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 3 0 1 +BITMAP +D8 +6C +D8 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +42 +C4 +48 +48 +12 +26 +2F +42 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 7 8 0 0 +BITMAP +42 +C4 +48 +48 +16 +2A +24 +4E +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +E2 +44 +28 +C8 +12 +26 +2F +42 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +30 +00 +30 +30 +60 +C0 +D8 +70 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +08 +10 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +10 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +3F80 +3C00 +6C00 +6F80 +6C00 +FC00 +CC00 +CF80 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 10 0 -2 +BITMAP +3C +66 +C2 +C0 +C0 +C2 +66 +3C +10 +30 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +40 +20 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +10 +20 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +20 +50 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +50 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 0 +BITMAP +80 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 0 +BITMAP +40 +80 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 0 +BITMAP +40 +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F0 +D8 +CC +EC +CC +CC +D8 +F0 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +C6 +C6 +E6 +D6 +D6 +CE +CE +C6 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +04 +08 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +CC +78 +30 +78 +CC +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3A +6C +CE +D6 +D6 +E6 +6C +B8 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +20 +10 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +08 +10 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +10 +28 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +28 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 11 0 0 +BITMAP +04 +08 +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +C0 +F8 +CC +CC +CC +F8 +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +C8 +C8 +D0 +C8 +C8 +C8 +D0 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +40 +20 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +08 +10 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +30 +68 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +28 +50 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +50 +50 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +20 +50 +20 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 9 0 +BBX 8 6 0 0 +BITMAP +7E +9B +7F +D8 +DB +6E +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 5 0 +BBX 4 8 0 -2 +BITMAP +70 +D0 +C0 +C0 +D0 +70 +20 +60 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +80 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +20 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 -1 0 +BITMAP +40 +A0 +00 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +A0 +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +60 +A0 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +28 +50 +00 +B0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +A0 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +30 +00 +FC +00 +30 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 6 6 0 0 +BITMAP +74 +D8 +F8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 11 0 -2 +BITMAP +10 +20 +00 +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 10 0 -2 +BITMAP +C0 +C0 +F0 +D8 +C8 +C8 +D8 +F0 +C0 +C0 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 11 0 -2 +BITMAP +50 +50 +00 +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR Lslash +ENCODING -1 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 6 8 -1 0 +BITMAP +60 +60 +60 +70 +E0 +60 +60 +7C +ENDCHAR +STARTCHAR OE +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +3F80 +6C00 +CC00 +CF80 +CC00 +CC00 +6C00 +3F80 +ENDCHAR +STARTCHAR Scaron +ENCODING -1 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +28 +10 +00 +78 +CC +70 +3C +CC +78 +ENDCHAR +STARTCHAR Ydieresis +ENCODING -1 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 8 0 0 +BITMAP +14 +00 +C3 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Zcaron +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +28 +10 +00 +FC +18 +30 +60 +C0 +FC +ENDCHAR +STARTCHAR breve +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 6 +BITMAP +90 +60 +ENDCHAR +STARTCHAR bullet +ENCODING -1 +SWIDTH 350 0 +DWIDTH 4 0 +BBX 2 2 1 2 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR caron +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +A0 +40 +ENDCHAR +STARTCHAR circumflex +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +40 +A0 +ENDCHAR +STARTCHAR dagger +ENCODING -1 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -2 +BITMAP +30 +30 +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR daggerdbl +ENCODING -1 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -2 +BITMAP +30 +30 +FC +30 +30 +30 +FC +30 +30 +30 +ENDCHAR +STARTCHAR dotaccent +ENCODING -1 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 1 1 0 7 +BITMAP +80 +ENDCHAR +STARTCHAR dotlessi +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 6 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR ellipsis +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 8 1 1 0 +BITMAP +DB +ENDCHAR +STARTCHAR emdash +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 10 1 0 3 +BITMAP +FFC0 +ENDCHAR +STARTCHAR endash +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 1 0 3 +BITMAP +FC +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 8 -1 0 +BITMAP +36 +60 +F6 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 8 -1 0 +BITMAP +36 +66 +F6 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR florin +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 -2 +BITMAP +38 +60 +F8 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR fraction +ENCODING -1 +SWIDTH 167 0 +DWIDTH 4 0 +BBX 5 7 -1 0 +BITMAP +08 +10 +10 +20 +40 +40 +80 +ENDCHAR +STARTCHAR grave +ENCODING -1 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 6 +BITMAP +80 +40 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 3 1 1 +BITMAP +60 +C0 +60 +ENDCHAR +STARTCHAR guilsinglright +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 3 1 1 +BITMAP +C0 +60 +C0 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 2 0 6 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR lslash +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 8 -1 0 +BITMAP +60 +60 +60 +70 +E0 +60 +60 +60 +ENDCHAR +STARTCHAR oe +ENCODING -1 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 9 6 0 0 +BITMAP +7700 +CD80 +CF80 +CC00 +CD80 +7700 +ENDCHAR +STARTCHAR ogonek +ENCODING -1 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 -2 +BITMAP +80 +C0 +ENDCHAR +STARTCHAR perthousand +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +6200 +B400 +6800 +1000 +2D80 +56C0 +8D80 +ENDCHAR +STARTCHAR quotedblbase +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 -2 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotedblleft +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +48 +90 +D8 +ENDCHAR +STARTCHAR quotedblright +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 -2 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR quotesingle +ENCODING -1 +SWIDTH 238 0 +DWIDTH 3 0 +BBX 1 3 1 5 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR ring +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +40 +A0 +40 +ENDCHAR +STARTCHAR scaron +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +20 +00 +70 +D8 +70 +18 +D8 +70 +ENDCHAR +STARTCHAR tilde +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 6 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR trademark +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 4 1 3 +BITMAP +E880 +4D80 +4A80 +4A80 +ENDCHAR +STARTCHAR zcaron +ENCODING -1 +SWIDTH 500 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +50 +20 +00 +F8 +18 +30 +60 +C0 +F8 +ENDCHAR +ENDFONT diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc-splash.c b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc-splash.c new file mode 100644 index 0000000000..0253fabde2 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc-splash.c @@ -0,0 +1,498 @@ +#include <usplash-theme.h> +#include <usplash_backend.h> + +/********************************************************************************** + This is a USplash based theme for the awsome XBMC Media Center for linux. + Graphics were composed mainly of the official XBMC logos. + + Visit my blog at: + http://du-duke.blogspot.com/ + for some more usplash, xbmc stuff. + + some code snippets were taken from: + http://gnome-look.org/content/show.php/MacX+Usplash+Theme?content=73611 + + =================================================================================== + 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 3 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, see <http://www.gnu.org/licenses/>. + ================================================================================== + +**********************************************************************************/ + +extern struct usplash_pixmap pixmap_xbmc_1920_1200; +extern struct usplash_pixmap pixmap_xbmc_1920_1080; +extern struct usplash_pixmap pixmap_xbmc_1680_1050; +extern struct usplash_pixmap pixmap_xbmc_1440_900; +extern struct usplash_pixmap pixmap_xbmc_1280_1024; +extern struct usplash_pixmap pixmap_xbmc_1366_768; +extern struct usplash_pixmap pixmap_xbmc_1280_720; +extern struct usplash_pixmap pixmap_xbmc_1024_768; +extern struct usplash_pixmap pixmap_xbmc_800_600; +extern struct usplash_pixmap pixmap_xbmc_640_480; + +extern struct usplash_pixmap pixmap_xbmc_spinner; +extern struct usplash_font font_helvB10; + +void t_init(struct usplash_theme* theme); +void t_clear_progressbar(struct usplash_theme* theme); +void t_draw_progressbar(struct usplash_theme* theme, int percentage); +void t_animate_step(struct usplash_theme* theme, int pulsating); +void spinner(struct usplash_theme* theme); + +struct usplash_theme usplash_theme; +struct usplash_theme usplash_theme_1920_1080; +struct usplash_theme usplash_theme_1680_1050; +struct usplash_theme usplash_theme_1440_900; +struct usplash_theme usplash_theme_1280_1024; +struct usplash_theme usplash_theme_1366_768; +struct usplash_theme usplash_theme_1280_720; +struct usplash_theme usplash_theme_1024_768; +struct usplash_theme usplash_theme_800_600; +struct usplash_theme usplash_theme_640_480; + +static int spinner_x, spinner_y, spinner_part_width, spinner_height; +static int current_count = 0; +static int current_step = 0; +static int spinner_num_steps = 12; + +// spinner_speed can be between 1 and 25 +// there are 12 images in the spinner, so a value of 2 will make +// it spin around approx. once per second +static int spinner_speed = 2; + +/** ----------------------------------------------------------------------- **/ + +struct usplash_theme usplash_theme = { + .version = THEME_VERSION, + .next = &usplash_theme_1920_1080, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1920_1200, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1920_1080 = { + .version = THEME_VERSION, + .next = &usplash_theme_1680_1050, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1920_1080, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0xB9, + .text_failure = 0xB9, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1680_1050 = { + .version = THEME_VERSION, + .next = &usplash_theme_1440_900, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1680_1050, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1440_900 = { + .version = THEME_VERSION, + .next = &usplash_theme_1280_1024, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1440_900, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1280_1024 = { + .version = THEME_VERSION, + .next = &usplash_theme_1366_768, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1280_1024, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0xB9, + .text_failure = 0xB9, + + /* Text box position and size in pixels */ + .text_x = 400, + .text_y = 800, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1366_768 = { + .version = THEME_VERSION, + .next = &usplash_theme_1280_720, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1366_768, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1280_720 = { + .version = THEME_VERSION, + .next = &usplash_theme_1024_768, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1280_720, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1024_768 = { + .version = THEME_VERSION, + .next = &usplash_theme_800_600, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1024_768, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_800_600 = { + .version = THEME_VERSION, + .next = &usplash_theme_640_480, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_800_600, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_640_480 = { + .version = THEME_VERSION, + .next = NULL, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_640_480, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +/** ---------------------------------------------------------- **/ + +/* init usplash */ +void t_init(struct usplash_theme *theme) { + // determine spinner position and dimensions + spinner_height = pixmap_xbmc_spinner.height; + spinner_part_width = pixmap_xbmc_spinner.width / spinner_num_steps; + spinner_x = (theme->pixmap->width / 2) - (spinner_part_width / 2); + spinner_y = (theme->pixmap->height / 2) - (pixmap_xbmc_spinner.height / 2); + + // set text box dimensions and size + theme->text_width = 600; + theme->text_x = (theme->pixmap->width / 2) - (theme->text_width / 2); + theme->text_y = 50; + theme->text_height = 250; + + // set theme color indexes + theme->background = 0; + theme->progressbar_background = 0; + theme->progressbar_foreground = 30; + theme->text_background = 0; + theme->text_foreground = 185; + theme->text_success = 185; + theme->text_failure = 185; +} + +/****** + * Animation callback - called 25 times per second by Usplash + * + * Param: struct usplash_theme* theme - theme being used + * int pulsating - boolean int + */ +void t_animate_step(struct usplash_theme* theme, int pulsating) { + current_count = current_count + 1; + + // increase test int for slower spinning + if(current_count == spinner_speed) { + spinner(theme); + current_count = 0; + } +} + +/******** + * Animate the spinner + * helper function to aid in animation of spinner + */ +void spinner(struct usplash_theme* theme) { + current_step = current_step + 1; + + int x0 = (spinner_part_width * current_step) - spinner_part_width; + int y0 = 0; + + // if current step > number of images in the spinner, then reset to beginning (at end or circular spinner) + if(current_step >= spinner_num_steps) { + current_step = 0; + } + + // call usplash_put_part for the small or large spinner image + usplash_put_part(spinner_x, spinner_y, spinner_part_width, spinner_height, &pixmap_xbmc_spinner, x0, y0); +} + +/** not used for now **/ +void t_clear_progressbar(struct usplash_theme *theme) { } +void t_draw_progressbar(struct usplash_theme *theme, int percentage) { } diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1024_768.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1024_768.png Binary files differnew file mode 100644 index 0000000000..cb7df903c0 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1024_768.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1280_1024.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1280_1024.png Binary files differnew file mode 100644 index 0000000000..63d8ea234b --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1280_1024.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1280_720.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1280_720.png Binary files differnew file mode 100644 index 0000000000..993cb1a849 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1280_720.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1366_768.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1366_768.png Binary files differnew file mode 100644 index 0000000000..5500d4bcbc --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1366_768.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1440_900.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1440_900.png Binary files differnew file mode 100644 index 0000000000..2a4a164804 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1440_900.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1680_1050.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1680_1050.png Binary files differnew file mode 100644 index 0000000000..4cbd70e6f1 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1680_1050.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1920_1080.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1920_1080.png Binary files differnew file mode 100644 index 0000000000..9ae47186a4 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1920_1080.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1920_1200.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1920_1200.png Binary files differnew file mode 100644 index 0000000000..5b9662cab7 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_1920_1200.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_640_480.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_640_480.png Binary files differnew file mode 100644 index 0000000000..a9fdd216ea --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_640_480.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_800_600.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_800_600.png Binary files differnew file mode 100644 index 0000000000..e35aab2596 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_800_600.png diff --git a/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_spinner.png b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_spinner.png Binary files differnew file mode 100644 index 0000000000..d8aaa92306 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/pulsating-logo/xbmc_spinner.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/COPYING b/tools/XBMCLive/USplashThemes/spinner-black/COPYING new file mode 100644 index 0000000000..10926e87f1 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 3 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, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. + diff --git a/tools/XBMCLive/USplashThemes/spinner-black/Makefile b/tools/XBMCLive/USplashThemes/spinner-black/Makefile new file mode 100644 index 0000000000..45a976db46 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/Makefile @@ -0,0 +1,29 @@ +CC=gcc +CFLAGS=-g -Wall -fPIC +LDFLAGS= +INCLUDES= +COMPILE = $(CC) $(INCLUDES) $(CFLAGS) +LINK = $(CC) $(CFLAGS) $(LDFLAGS) + +xbmc-splash.so: xbmc_1920_1200.png.c.o xbmc_1920_1080.png.c.o xbmc_1680_1050.png.c.o xbmc_1440_900.png.c.o xbmc_1280_1024.png.c.o xbmc_1366_768.png.c.o xbmc_1280_720.png.c.o xbmc_1024_768.png.c.o xbmc_800_600.png.c.o xbmc_640_480.png.c.o xbmc_spinner.png.c.o xbmc-splash.c.o helvB10.bdf.c.o + $(COMPILE) -shared -o $@ $^ + +%.c.o: %.c + $(COMPILE) -o $@ -c $< + +%.png.c: %.png + pngtousplash $< > $@ + +%.bdf.c: %.bdf + bdftousplash $< > $@ + +clean: + rm -f *.png.c *.bdf.c *.c.o *.so + +install: + cp xbmc-splash.so /usr/lib/usplash + rm /etc/alternatives/usplash-artwork.so + ln -s /usr/lib/usplash/xbmc-splash.so /etc/alternatives/usplash-artwork.so + dpkg-reconfigure usplash +test: + usplash -c diff --git a/tools/XBMCLive/USplashThemes/spinner-black/README b/tools/XBMCLive/USplashThemes/spinner-black/README new file mode 100644 index 0000000000..d2d7d46bfe --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/README @@ -0,0 +1,39 @@ +XBMC Splash - Black +==================== + +This is my 3rd attempt at a decent USplash theme for my linux XBMC HTPC (and possibly yours too :). + +It cotains several resolutions: +1024x768 +1280x720 +1366x768 +1280x1024 +1440x900 +1920x1080 +1920x1200 + +Those might work depending on the use (and support for your vid card) of the UVESAFB kernel module. +On my system (Radeon 3850 and 17" LCD) I was able to use 1024x768 and 1280x1024. + + +Build Instructions +================================================== +For Ubuntu, you will need the following packages installed: +build-essential, libusplash-dev. + +As it updates the initrd image, you'll need to work as root (or sudo). + +1. extract the package. +2. make (or make -j2 -for a faster compile) +3. backup your current ubuntu usplash: sudo cp /usr/lib/usplash/usplash-theme-ubuntu.so ~/ +4. replace it with your brand new xbmc usplash: sudo cp ./xbmc-splash.so /usr/lib/usplash/usplash-theme-ubuntu.so +5. update the initrd image: sudo update-initramfs -u +6. reboot +7. enjoy. + + +Thank yous +================================================== +For anyone who has ever tackled this damned USplash :) +For all the themes at gnome-looks +kilo323@yahoo.com for the spinner code. diff --git a/tools/XBMCLive/USplashThemes/spinner-black/helvB10.bdf b/tools/XBMCLive/USplashThemes/spinner-black/helvB10.bdf new file mode 100644 index 0000000000..fe548f547e --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/helvB10.bdf @@ -0,0 +1,3305 @@ +STARTFONT 2.1 +FONT -Adobe-Helvetica-Bold-R-Normal--10-100-75-75-P-60-ISO8859-1 +SIZE 10 75 75 +FONTBOUNDINGBOX 11 13 -1 -2 +COMMENT $XConsortium: helvB10.bdf,v 1.13 95/01/26 18:01:30 gildea Exp $ +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 28 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 10 +POINT_SIZE 100 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 60 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +CAP_HEIGHT 8 +X_HEIGHT 6 +FONT_ASCENT 10 +FONT_DESCENT 2 +FACE_NAME "Helvetica Bold" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold" +_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991" +DEFAULT_CHAR 32 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD" +FULL_NAME "Helvetica Bold" +ENDPROPERTIES +CHARS 229 +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 8 1 0 +BITMAP +C0 +C0 +C0 +C0 +80 +80 +00 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 5 0 +BBX 3 3 1 5 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +50 +50 +FC +50 +F8 +A0 +A0 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 -1 +BITMAP +20 +70 +A8 +E0 +70 +38 +A8 +70 +20 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +62 +B4 +68 +10 +10 +2C +56 +8C +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +70 +D8 +D8 +70 +DE +CC +DC +76 +ENDCHAR +STARTCHAR quoteright +ENCODING 39 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 5 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +20 +60 +40 +C0 +C0 +C0 +C0 +40 +60 +20 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +80 +C0 +40 +60 +60 +60 +60 +40 +C0 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +A0 +40 +A0 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +30 +30 +FC +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 4 0 -2 +BITMAP +40 +40 +40 +80 +ENDCHAR +STARTCHAR minus +ENCODING 45 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 2 1 0 +BITMAP +80 +80 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +10 +10 +20 +20 +40 +40 +80 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 4 8 0 0 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +30 +18 +18 +D8 +70 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 8 0 0 +BITMAP +18 +38 +58 +58 +98 +FC +18 +18 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F0 +18 +98 +D8 +70 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +C0 +F0 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +18 +18 +30 +30 +30 +60 +60 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +70 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +D8 +78 +18 +D8 +70 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 1 6 1 0 +BITMAP +80 +80 +00 +00 +80 +80 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 8 0 -2 +BITMAP +40 +40 +00 +00 +40 +40 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 4 5 0 1 +BITMAP +30 +60 +C0 +60 +30 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 5 3 0 2 +BITMAP +F8 +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 4 5 0 1 +BITMAP +C0 +60 +30 +60 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +30 +60 +60 +00 +60 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 11 0 +BBX 10 9 0 -2 +BITMAP +1F00 +6080 +4D40 +9240 +A240 +A480 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +F8 +CC +CC +CC +F8 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3C +66 +C2 +C0 +C0 +C2 +66 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F0 +D8 +CC +CC +CC +CC +D8 +F0 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3C +66 +C2 +C0 +CE +C6 +66 +3A +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +CC +CC +CC +FC +CC +CC +CC +CC +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +18 +18 +18 +18 +18 +18 +D8 +70 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +CC +D8 +F0 +E0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +CC +F8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 9 0 -1 +BITMAP +38 +6C +C6 +C6 +C6 +D6 +6C +3C +02 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +CC +F8 +CC +CC +CC +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +78 +CC +E0 +78 +1C +8C +CC +78 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +C6 +6C +6C +6C +38 +38 +10 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 10 8 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +6D80 +6D80 +7F80 +3300 +2100 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +C6 +6C +38 +38 +6C +C6 +C6 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +C3 +C3 +66 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +0C +18 +30 +70 +60 +C0 +FC +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +E0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +E0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +80 +80 +40 +40 +20 +20 +10 +10 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +E0 +60 +60 +60 +60 +60 +60 +60 +60 +E0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 5 4 0 4 +BITMAP +20 +70 +D8 +88 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 1 0 -2 +BITMAP +FC +ENDCHAR +STARTCHAR quoteleft +ENCODING 96 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 5 +BITMAP +40 +80 +C0 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 6 0 0 +BITMAP +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +F0 +D8 +C8 +C8 +D8 +F0 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 5 0 +BBX 4 6 0 0 +BITMAP +70 +D0 +C0 +C0 +D0 +70 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +18 +18 +78 +D8 +98 +98 +D8 +78 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +70 +C0 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +68 +D8 +98 +98 +D8 +78 +18 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +F0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 10 0 -2 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +80 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 8 0 0 +BITMAP +C0 +C0 +D8 +F0 +E0 +F0 +D8 +CC +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 9 0 +BBX 8 6 0 0 +BITMAP +B6 +DB +DB +DB +DB +DB +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +B0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +B0 +D8 +C8 +C8 +D8 +F0 +C0 +C0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +68 +D8 +98 +98 +D8 +78 +18 +18 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 4 0 +BBX 4 6 0 0 +BITMAP +B0 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +70 +18 +D8 +70 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +C0 +E0 +C0 +C0 +C0 +C0 +60 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +D8 +D8 +D8 +50 +70 +20 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 6 0 0 +BITMAP +D6 +D6 +D6 +6C +6C +6C +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 6 0 0 +BITMAP +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +F8 +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 10 0 -2 +BITMAP +30 +60 +60 +60 +C0 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 3 0 +BBX 1 10 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 10 0 -2 +BITMAP +C0 +60 +60 +60 +30 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 2 0 2 +BITMAP +6C +D8 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 8 1 -2 +BITMAP +C0 +00 +40 +40 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 -1 +BITMAP +10 +70 +D8 +A0 +A0 +D8 +70 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +38 +68 +60 +F0 +60 +60 +68 +D8 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 1 +BITMAP +D8 +70 +D8 +D8 +70 +D8 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +84 +CC +48 +78 +FC +30 +FC +30 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 3 0 +BBX 1 10 1 -2 +BITMAP +80 +80 +80 +80 +00 +00 +80 +80 +80 +80 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 10 0 -2 +BITMAP +70 +C8 +E0 +70 +98 +C8 +70 +38 +98 +70 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 7 +BITMAP +A0 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +42 +99 +A5 +A1 +9D +42 +3C +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 5 0 +BBX 3 5 1 3 +BITMAP +E0 +20 +A0 +00 +E0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 3 0 1 +BITMAP +6C +D8 +6C +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +F8 +08 +08 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +42 +BD +A5 +B9 +A5 +42 +3C +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 7 +BITMAP +E0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 4 0 +BBX 3 3 1 4 +BITMAP +60 +A0 +C0 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +30 +30 +FC +30 +30 +00 +FC +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 3 +BITMAP +60 +A0 +40 +E0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 3 +BITMAP +E0 +40 +20 +C0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 7 +BITMAP +40 +80 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +D8 +D8 +D8 +D8 +D8 +E8 +C0 +C0 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 10 0 -2 +BITMAP +7C +E8 +E8 +E8 +68 +28 +28 +28 +28 +28 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 1 0 3 +BITMAP +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 -2 +BITMAP +40 +C0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 4 0 3 +BITMAP +40 +C0 +40 +40 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 5 0 +BBX 3 5 1 3 +BITMAP +E0 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 3 0 1 +BITMAP +D8 +6C +D8 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +42 +C4 +48 +48 +12 +26 +2F +42 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 7 8 0 0 +BITMAP +42 +C4 +48 +48 +16 +2A +24 +4E +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +E2 +44 +28 +C8 +12 +26 +2F +42 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +30 +00 +30 +30 +60 +C0 +D8 +70 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +08 +10 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +10 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +3F80 +3C00 +6C00 +6F80 +6C00 +FC00 +CC00 +CF80 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 10 0 -2 +BITMAP +3C +66 +C2 +C0 +C0 +C2 +66 +3C +10 +30 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +40 +20 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +10 +20 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +20 +50 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +50 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 0 +BITMAP +80 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 0 +BITMAP +40 +80 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 0 +BITMAP +40 +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F0 +D8 +CC +EC +CC +CC +D8 +F0 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +C6 +C6 +E6 +D6 +D6 +CE +CE +C6 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +04 +08 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +CC +78 +30 +78 +CC +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3A +6C +CE +D6 +D6 +E6 +6C +B8 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +20 +10 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +08 +10 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +10 +28 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +28 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 11 0 0 +BITMAP +04 +08 +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +C0 +F8 +CC +CC +CC +F8 +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +C8 +C8 +D0 +C8 +C8 +C8 +D0 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +40 +20 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +08 +10 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +30 +68 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +28 +50 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +50 +50 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +20 +50 +20 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 9 0 +BBX 8 6 0 0 +BITMAP +7E +9B +7F +D8 +DB +6E +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 5 0 +BBX 4 8 0 -2 +BITMAP +70 +D0 +C0 +C0 +D0 +70 +20 +60 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +80 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +20 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 -1 0 +BITMAP +40 +A0 +00 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +A0 +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +60 +A0 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +28 +50 +00 +B0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +A0 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +30 +00 +FC +00 +30 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 6 6 0 0 +BITMAP +74 +D8 +F8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 11 0 -2 +BITMAP +10 +20 +00 +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 10 0 -2 +BITMAP +C0 +C0 +F0 +D8 +C8 +C8 +D8 +F0 +C0 +C0 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 11 0 -2 +BITMAP +50 +50 +00 +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR Lslash +ENCODING -1 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 6 8 -1 0 +BITMAP +60 +60 +60 +70 +E0 +60 +60 +7C +ENDCHAR +STARTCHAR OE +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +3F80 +6C00 +CC00 +CF80 +CC00 +CC00 +6C00 +3F80 +ENDCHAR +STARTCHAR Scaron +ENCODING -1 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +28 +10 +00 +78 +CC +70 +3C +CC +78 +ENDCHAR +STARTCHAR Ydieresis +ENCODING -1 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 8 0 0 +BITMAP +14 +00 +C3 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Zcaron +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +28 +10 +00 +FC +18 +30 +60 +C0 +FC +ENDCHAR +STARTCHAR breve +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 6 +BITMAP +90 +60 +ENDCHAR +STARTCHAR bullet +ENCODING -1 +SWIDTH 350 0 +DWIDTH 4 0 +BBX 2 2 1 2 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR caron +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +A0 +40 +ENDCHAR +STARTCHAR circumflex +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +40 +A0 +ENDCHAR +STARTCHAR dagger +ENCODING -1 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -2 +BITMAP +30 +30 +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR daggerdbl +ENCODING -1 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -2 +BITMAP +30 +30 +FC +30 +30 +30 +FC +30 +30 +30 +ENDCHAR +STARTCHAR dotaccent +ENCODING -1 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 1 1 0 7 +BITMAP +80 +ENDCHAR +STARTCHAR dotlessi +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 6 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR ellipsis +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 8 1 1 0 +BITMAP +DB +ENDCHAR +STARTCHAR emdash +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 10 1 0 3 +BITMAP +FFC0 +ENDCHAR +STARTCHAR endash +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 1 0 3 +BITMAP +FC +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 8 -1 0 +BITMAP +36 +60 +F6 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 8 -1 0 +BITMAP +36 +66 +F6 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR florin +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 -2 +BITMAP +38 +60 +F8 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR fraction +ENCODING -1 +SWIDTH 167 0 +DWIDTH 4 0 +BBX 5 7 -1 0 +BITMAP +08 +10 +10 +20 +40 +40 +80 +ENDCHAR +STARTCHAR grave +ENCODING -1 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 6 +BITMAP +80 +40 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 3 1 1 +BITMAP +60 +C0 +60 +ENDCHAR +STARTCHAR guilsinglright +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 3 1 1 +BITMAP +C0 +60 +C0 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 2 0 6 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR lslash +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 8 -1 0 +BITMAP +60 +60 +60 +70 +E0 +60 +60 +60 +ENDCHAR +STARTCHAR oe +ENCODING -1 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 9 6 0 0 +BITMAP +7700 +CD80 +CF80 +CC00 +CD80 +7700 +ENDCHAR +STARTCHAR ogonek +ENCODING -1 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 -2 +BITMAP +80 +C0 +ENDCHAR +STARTCHAR perthousand +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +6200 +B400 +6800 +1000 +2D80 +56C0 +8D80 +ENDCHAR +STARTCHAR quotedblbase +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 -2 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotedblleft +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +48 +90 +D8 +ENDCHAR +STARTCHAR quotedblright +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 -2 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR quotesingle +ENCODING -1 +SWIDTH 238 0 +DWIDTH 3 0 +BBX 1 3 1 5 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR ring +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +40 +A0 +40 +ENDCHAR +STARTCHAR scaron +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +20 +00 +70 +D8 +70 +18 +D8 +70 +ENDCHAR +STARTCHAR tilde +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 6 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR trademark +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 4 1 3 +BITMAP +E880 +4D80 +4A80 +4A80 +ENDCHAR +STARTCHAR zcaron +ENCODING -1 +SWIDTH 500 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +50 +20 +00 +F8 +18 +30 +60 +C0 +F8 +ENDCHAR +ENDFONT diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc-splash.c b/tools/XBMCLive/USplashThemes/spinner-black/xbmc-splash.c new file mode 100644 index 0000000000..214fe98a42 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc-splash.c @@ -0,0 +1,498 @@ +#include <usplash-theme.h> +#include <usplash_backend.h> + +/********************************************************************************** + This is a USplash based theme for the awsome XBMC Media Center for linux. + Graphics were composed mainly of the official XBMC logos. + + Visit my blog at: + http://du-duke.blogspot.com/ + for some more usplash, xbmc stuff. + + some code snippets were taken from: + http://gnome-look.org/content/show.php/MacX+Usplash+Theme?content=73611 + + =================================================================================== + 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 3 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, see <http://www.gnu.org/licenses/>. + ================================================================================== + +**********************************************************************************/ + +extern struct usplash_pixmap pixmap_xbmc_1920_1200; +extern struct usplash_pixmap pixmap_xbmc_1920_1080; +extern struct usplash_pixmap pixmap_xbmc_1680_1050; +extern struct usplash_pixmap pixmap_xbmc_1440_900; +extern struct usplash_pixmap pixmap_xbmc_1280_1024; +extern struct usplash_pixmap pixmap_xbmc_1366_768; +extern struct usplash_pixmap pixmap_xbmc_1280_720; +extern struct usplash_pixmap pixmap_xbmc_1024_768; +extern struct usplash_pixmap pixmap_xbmc_800_600; +extern struct usplash_pixmap pixmap_xbmc_640_480; + +extern struct usplash_pixmap pixmap_xbmc_spinner; +extern struct usplash_font font_helvB10; + +void t_init(struct usplash_theme* theme); +void t_clear_progressbar(struct usplash_theme* theme); +void t_draw_progressbar(struct usplash_theme* theme, int percentage); +void t_animate_step(struct usplash_theme* theme, int pulsating); +void spinner(struct usplash_theme* theme); + +struct usplash_theme usplash_theme; +struct usplash_theme usplash_theme_1920_1080; +struct usplash_theme usplash_theme_1680_1050; +struct usplash_theme usplash_theme_1440_900; +struct usplash_theme usplash_theme_1280_1024; +struct usplash_theme usplash_theme_1366_768; +struct usplash_theme usplash_theme_1280_720; +struct usplash_theme usplash_theme_1024_768; +struct usplash_theme usplash_theme_800_600; +struct usplash_theme usplash_theme_640_480; + +static int spinner_x, spinner_y, spinner_part_width, spinner_height; +static int current_count = 0; +static int current_step = 0; +static int spinner_num_steps = 12; + +// spinner_speed can be between 1 and 25 +// there are 12 images in the spinner, so a value of 2 will make +// it spin around approx. once per second +static int spinner_speed = 2; + +/** ----------------------------------------------------------------------- **/ + +struct usplash_theme usplash_theme = { + .version = THEME_VERSION, + .next = &usplash_theme_1920_1080, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1920_1200, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1920_1080 = { + .version = THEME_VERSION, + .next = &usplash_theme_1680_1050, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1920_1080, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1680_1050 = { + .version = THEME_VERSION, + .next = &usplash_theme_1440_900, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1680_1050, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1440_900 = { + .version = THEME_VERSION, + .next = &usplash_theme_1280_1024, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1440_900, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1280_1024 = { + .version = THEME_VERSION, + .next = &usplash_theme_1366_768, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1280_1024, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1366_768 = { + .version = THEME_VERSION, + .next = &usplash_theme_1280_720, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1366_768, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1280_720 = { + .version = THEME_VERSION, + .next = &usplash_theme_1024_768, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1280_720, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1024_768 = { + .version = THEME_VERSION, + .next = &usplash_theme_800_600, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1024_768, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_800_600 = { + .version = THEME_VERSION, + .next = &usplash_theme_640_480, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_800_600, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_640_480 = { + .version = THEME_VERSION, + .next = NULL, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_640_480, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +/** ---------------------------------------------------------- **/ + +/* init usplash */ +void t_init(struct usplash_theme *theme) { + // determine spinner position and dimensions + spinner_height = pixmap_xbmc_spinner.height; + spinner_part_width = pixmap_xbmc_spinner.width / spinner_num_steps; + spinner_x = (theme->pixmap->width / 2) - (spinner_part_width / 2); + spinner_y = (theme->pixmap->height / 2) + (((theme->pixmap->height / 2) / 4) / 2) - (pixmap_xbmc_spinner.height / 2); + + // set text box dimensions and size + theme->text_width = 600; + theme->text_x = (theme->pixmap->width / 2) - (theme->text_width / 2); + theme->text_y = 50; + theme->text_height = 250; + + // set theme color indexes + theme->background = 0; + theme->progressbar_background = 0; + theme->progressbar_foreground = 30; + theme->text_background = 0; + theme->text_foreground = 1; + theme->text_success = 35; + theme->text_failure = 36; +} + +/****** + * Animation callback - called 25 times per second by Usplash + * + * Param: struct usplash_theme* theme - theme being used + * int pulsating - boolean int + */ +void t_animate_step(struct usplash_theme* theme, int pulsating) { + current_count = current_count + 1; + + // increase test int for slower spinning + if(current_count == spinner_speed) { + spinner(theme); + current_count = 0; + } +} + +/******** + * Animate the spinner + * helper function to aid in animation of spinner + */ +void spinner(struct usplash_theme* theme) { + current_step = current_step + 1; + + int x0 = (spinner_part_width * current_step) - spinner_part_width; + int y0 = 0; + + // if current step > number of images in the spinner, then reset to beginning (at end or circular spinner) + if(current_step >= spinner_num_steps) { + current_step = 0; + } + + // call usplash_put_part for the small or large spinner image + usplash_put_part(spinner_x, spinner_y, spinner_part_width, spinner_height, &pixmap_xbmc_spinner, x0, y0); +} + +/** not used for now **/ +void t_clear_progressbar(struct usplash_theme *theme) { } +void t_draw_progressbar(struct usplash_theme *theme, int percentage) { } diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1024_768.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1024_768.png Binary files differnew file mode 100644 index 0000000000..5fb89f36e7 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1024_768.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1280_1024.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1280_1024.png Binary files differnew file mode 100644 index 0000000000..4d58864036 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1280_1024.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1280_720.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1280_720.png Binary files differnew file mode 100644 index 0000000000..f1a381a380 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1280_720.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1366_768.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1366_768.png Binary files differnew file mode 100644 index 0000000000..06a8e6fd9d --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1366_768.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1440_900.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1440_900.png Binary files differnew file mode 100644 index 0000000000..76ec205bce --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1440_900.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1680_1050.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1680_1050.png Binary files differnew file mode 100644 index 0000000000..00c8dd8ca0 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1680_1050.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1920_1080.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1920_1080.png Binary files differnew file mode 100644 index 0000000000..2e57c57010 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1920_1080.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1920_1200.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1920_1200.png Binary files differnew file mode 100644 index 0000000000..2a89b3024a --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_1920_1200.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_640_480.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_640_480.png Binary files differnew file mode 100644 index 0000000000..7d68a1916a --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_640_480.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_800_600.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_800_600.png Binary files differnew file mode 100644 index 0000000000..15f119cb80 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_800_600.png diff --git a/tools/XBMCLive/USplashThemes/spinner-black/xbmc_spinner.png b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_spinner.png Binary files differnew file mode 100644 index 0000000000..c3a491e493 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-black/xbmc_spinner.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/COPYING b/tools/XBMCLive/USplashThemes/spinner-blue/COPYING new file mode 100644 index 0000000000..10926e87f1 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 3 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, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. + diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/Makefile b/tools/XBMCLive/USplashThemes/spinner-blue/Makefile new file mode 100644 index 0000000000..45a976db46 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/Makefile @@ -0,0 +1,29 @@ +CC=gcc +CFLAGS=-g -Wall -fPIC +LDFLAGS= +INCLUDES= +COMPILE = $(CC) $(INCLUDES) $(CFLAGS) +LINK = $(CC) $(CFLAGS) $(LDFLAGS) + +xbmc-splash.so: xbmc_1920_1200.png.c.o xbmc_1920_1080.png.c.o xbmc_1680_1050.png.c.o xbmc_1440_900.png.c.o xbmc_1280_1024.png.c.o xbmc_1366_768.png.c.o xbmc_1280_720.png.c.o xbmc_1024_768.png.c.o xbmc_800_600.png.c.o xbmc_640_480.png.c.o xbmc_spinner.png.c.o xbmc-splash.c.o helvB10.bdf.c.o + $(COMPILE) -shared -o $@ $^ + +%.c.o: %.c + $(COMPILE) -o $@ -c $< + +%.png.c: %.png + pngtousplash $< > $@ + +%.bdf.c: %.bdf + bdftousplash $< > $@ + +clean: + rm -f *.png.c *.bdf.c *.c.o *.so + +install: + cp xbmc-splash.so /usr/lib/usplash + rm /etc/alternatives/usplash-artwork.so + ln -s /usr/lib/usplash/xbmc-splash.so /etc/alternatives/usplash-artwork.so + dpkg-reconfigure usplash +test: + usplash -c diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/README b/tools/XBMCLive/USplashThemes/spinner-blue/README new file mode 100644 index 0000000000..d2d7d46bfe --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/README @@ -0,0 +1,39 @@ +XBMC Splash - Black +==================== + +This is my 3rd attempt at a decent USplash theme for my linux XBMC HTPC (and possibly yours too :). + +It cotains several resolutions: +1024x768 +1280x720 +1366x768 +1280x1024 +1440x900 +1920x1080 +1920x1200 + +Those might work depending on the use (and support for your vid card) of the UVESAFB kernel module. +On my system (Radeon 3850 and 17" LCD) I was able to use 1024x768 and 1280x1024. + + +Build Instructions +================================================== +For Ubuntu, you will need the following packages installed: +build-essential, libusplash-dev. + +As it updates the initrd image, you'll need to work as root (or sudo). + +1. extract the package. +2. make (or make -j2 -for a faster compile) +3. backup your current ubuntu usplash: sudo cp /usr/lib/usplash/usplash-theme-ubuntu.so ~/ +4. replace it with your brand new xbmc usplash: sudo cp ./xbmc-splash.so /usr/lib/usplash/usplash-theme-ubuntu.so +5. update the initrd image: sudo update-initramfs -u +6. reboot +7. enjoy. + + +Thank yous +================================================== +For anyone who has ever tackled this damned USplash :) +For all the themes at gnome-looks +kilo323@yahoo.com for the spinner code. diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-16on10-origcolor.xcf b/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-16on10-origcolor.xcf Binary files differnew file mode 100644 index 0000000000..88f27353a6 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-16on10-origcolor.xcf diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-16on9-origcolor.xcf b/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-16on9-origcolor.xcf Binary files differnew file mode 100644 index 0000000000..4a7726d138 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-16on9-origcolor.xcf diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-4on3-origcolor.xcf b/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-4on3-origcolor.xcf Binary files differnew file mode 100644 index 0000000000..e677f77507 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-4on3-origcolor.xcf diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-5on4-origcolor.xcf b/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-5on4-origcolor.xcf Binary files differnew file mode 100644 index 0000000000..3df8587f5e --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/XBMC-USPLASH-WIDE-5on4-origcolor.xcf diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/helvB10.bdf b/tools/XBMCLive/USplashThemes/spinner-blue/helvB10.bdf new file mode 100644 index 0000000000..fe548f547e --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/helvB10.bdf @@ -0,0 +1,3305 @@ +STARTFONT 2.1 +FONT -Adobe-Helvetica-Bold-R-Normal--10-100-75-75-P-60-ISO8859-1 +SIZE 10 75 75 +FONTBOUNDINGBOX 11 13 -1 -2 +COMMENT $XConsortium: helvB10.bdf,v 1.13 95/01/26 18:01:30 gildea Exp $ +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 28 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 10 +POINT_SIZE 100 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 60 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +CAP_HEIGHT 8 +X_HEIGHT 6 +FONT_ASCENT 10 +FONT_DESCENT 2 +FACE_NAME "Helvetica Bold" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold" +_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991" +DEFAULT_CHAR 32 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD" +FULL_NAME "Helvetica Bold" +ENDPROPERTIES +CHARS 229 +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 8 1 0 +BITMAP +C0 +C0 +C0 +C0 +80 +80 +00 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 5 0 +BBX 3 3 1 5 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +50 +50 +FC +50 +F8 +A0 +A0 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 -1 +BITMAP +20 +70 +A8 +E0 +70 +38 +A8 +70 +20 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +62 +B4 +68 +10 +10 +2C +56 +8C +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +70 +D8 +D8 +70 +DE +CC +DC +76 +ENDCHAR +STARTCHAR quoteright +ENCODING 39 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 5 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +20 +60 +40 +C0 +C0 +C0 +C0 +40 +60 +20 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +80 +C0 +40 +60 +60 +60 +60 +40 +C0 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +A0 +40 +A0 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +30 +30 +FC +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 4 0 -2 +BITMAP +40 +40 +40 +80 +ENDCHAR +STARTCHAR minus +ENCODING 45 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 2 1 0 +BITMAP +80 +80 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +10 +10 +20 +20 +40 +40 +80 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 4 8 0 0 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +30 +18 +18 +D8 +70 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 8 0 0 +BITMAP +18 +38 +58 +58 +98 +FC +18 +18 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F0 +18 +98 +D8 +70 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +C0 +F0 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +18 +18 +30 +30 +30 +60 +60 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +70 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +D8 +78 +18 +D8 +70 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 1 6 1 0 +BITMAP +80 +80 +00 +00 +80 +80 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 8 0 -2 +BITMAP +40 +40 +00 +00 +40 +40 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 4 5 0 1 +BITMAP +30 +60 +C0 +60 +30 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 5 3 0 2 +BITMAP +F8 +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 4 5 0 1 +BITMAP +C0 +60 +30 +60 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +30 +60 +60 +00 +60 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 11 0 +BBX 10 9 0 -2 +BITMAP +1F00 +6080 +4D40 +9240 +A240 +A480 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +F8 +CC +CC +CC +F8 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3C +66 +C2 +C0 +C0 +C2 +66 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F0 +D8 +CC +CC +CC +CC +D8 +F0 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3C +66 +C2 +C0 +CE +C6 +66 +3A +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +CC +CC +CC +FC +CC +CC +CC +CC +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +18 +18 +18 +18 +18 +18 +D8 +70 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +CC +D8 +F0 +E0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +CC +F8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 9 0 -1 +BITMAP +38 +6C +C6 +C6 +C6 +D6 +6C +3C +02 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +CC +F8 +CC +CC +CC +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +78 +CC +E0 +78 +1C +8C +CC +78 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +C6 +6C +6C +6C +38 +38 +10 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 10 8 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +6D80 +6D80 +7F80 +3300 +2100 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +C6 +6C +38 +38 +6C +C6 +C6 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +C3 +C3 +66 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +0C +18 +30 +70 +60 +C0 +FC +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +E0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +E0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +80 +80 +40 +40 +20 +20 +10 +10 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +E0 +60 +60 +60 +60 +60 +60 +60 +60 +E0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 5 4 0 4 +BITMAP +20 +70 +D8 +88 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 1 0 -2 +BITMAP +FC +ENDCHAR +STARTCHAR quoteleft +ENCODING 96 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 5 +BITMAP +40 +80 +C0 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 6 0 0 +BITMAP +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +F0 +D8 +C8 +C8 +D8 +F0 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 5 0 +BBX 4 6 0 0 +BITMAP +70 +D0 +C0 +C0 +D0 +70 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +18 +18 +78 +D8 +98 +98 +D8 +78 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +70 +C0 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +68 +D8 +98 +98 +D8 +78 +18 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +F0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 10 0 -2 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +80 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 8 0 0 +BITMAP +C0 +C0 +D8 +F0 +E0 +F0 +D8 +CC +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 9 0 +BBX 8 6 0 0 +BITMAP +B6 +DB +DB +DB +DB +DB +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +B0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +B0 +D8 +C8 +C8 +D8 +F0 +C0 +C0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +68 +D8 +98 +98 +D8 +78 +18 +18 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 4 0 +BBX 4 6 0 0 +BITMAP +B0 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +70 +18 +D8 +70 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +C0 +E0 +C0 +C0 +C0 +C0 +60 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +D8 +D8 +D8 +50 +70 +20 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 6 0 0 +BITMAP +D6 +D6 +D6 +6C +6C +6C +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 6 0 0 +BITMAP +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +F8 +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 10 0 -2 +BITMAP +30 +60 +60 +60 +C0 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 3 0 +BBX 1 10 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 10 0 -2 +BITMAP +C0 +60 +60 +60 +30 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 2 0 2 +BITMAP +6C +D8 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 8 1 -2 +BITMAP +C0 +00 +40 +40 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 -1 +BITMAP +10 +70 +D8 +A0 +A0 +D8 +70 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +38 +68 +60 +F0 +60 +60 +68 +D8 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 1 +BITMAP +D8 +70 +D8 +D8 +70 +D8 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +84 +CC +48 +78 +FC +30 +FC +30 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 3 0 +BBX 1 10 1 -2 +BITMAP +80 +80 +80 +80 +00 +00 +80 +80 +80 +80 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 10 0 -2 +BITMAP +70 +C8 +E0 +70 +98 +C8 +70 +38 +98 +70 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 7 +BITMAP +A0 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +42 +99 +A5 +A1 +9D +42 +3C +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 5 0 +BBX 3 5 1 3 +BITMAP +E0 +20 +A0 +00 +E0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 3 0 1 +BITMAP +6C +D8 +6C +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +F8 +08 +08 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +42 +BD +A5 +B9 +A5 +42 +3C +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 7 +BITMAP +E0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 4 0 +BBX 3 3 1 4 +BITMAP +60 +A0 +C0 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +30 +30 +FC +30 +30 +00 +FC +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 3 +BITMAP +60 +A0 +40 +E0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 3 +BITMAP +E0 +40 +20 +C0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 7 +BITMAP +40 +80 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +D8 +D8 +D8 +D8 +D8 +E8 +C0 +C0 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 10 0 -2 +BITMAP +7C +E8 +E8 +E8 +68 +28 +28 +28 +28 +28 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 1 0 3 +BITMAP +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 -2 +BITMAP +40 +C0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 4 0 3 +BITMAP +40 +C0 +40 +40 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 5 0 +BBX 3 5 1 3 +BITMAP +E0 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 3 0 1 +BITMAP +D8 +6C +D8 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +42 +C4 +48 +48 +12 +26 +2F +42 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 7 8 0 0 +BITMAP +42 +C4 +48 +48 +16 +2A +24 +4E +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +E2 +44 +28 +C8 +12 +26 +2F +42 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +30 +00 +30 +30 +60 +C0 +D8 +70 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +08 +10 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +10 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +3F80 +3C00 +6C00 +6F80 +6C00 +FC00 +CC00 +CF80 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 10 0 -2 +BITMAP +3C +66 +C2 +C0 +C0 +C2 +66 +3C +10 +30 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +40 +20 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +10 +20 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +20 +50 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +50 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 0 +BITMAP +80 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 0 +BITMAP +40 +80 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 0 +BITMAP +40 +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F0 +D8 +CC +EC +CC +CC +D8 +F0 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +C6 +C6 +E6 +D6 +D6 +CE +CE +C6 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +04 +08 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +CC +78 +30 +78 +CC +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3A +6C +CE +D6 +D6 +E6 +6C +B8 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +20 +10 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +08 +10 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +10 +28 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +28 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 11 0 0 +BITMAP +04 +08 +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +C0 +F8 +CC +CC +CC +F8 +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +C8 +C8 +D0 +C8 +C8 +C8 +D0 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +40 +20 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +08 +10 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +30 +68 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +28 +50 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +50 +50 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +20 +50 +20 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 9 0 +BBX 8 6 0 0 +BITMAP +7E +9B +7F +D8 +DB +6E +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 5 0 +BBX 4 8 0 -2 +BITMAP +70 +D0 +C0 +C0 +D0 +70 +20 +60 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +80 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +20 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 -1 0 +BITMAP +40 +A0 +00 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +A0 +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +60 +A0 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +28 +50 +00 +B0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +A0 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +30 +00 +FC +00 +30 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 6 6 0 0 +BITMAP +74 +D8 +F8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 11 0 -2 +BITMAP +10 +20 +00 +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 10 0 -2 +BITMAP +C0 +C0 +F0 +D8 +C8 +C8 +D8 +F0 +C0 +C0 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 11 0 -2 +BITMAP +50 +50 +00 +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR Lslash +ENCODING -1 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 6 8 -1 0 +BITMAP +60 +60 +60 +70 +E0 +60 +60 +7C +ENDCHAR +STARTCHAR OE +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +3F80 +6C00 +CC00 +CF80 +CC00 +CC00 +6C00 +3F80 +ENDCHAR +STARTCHAR Scaron +ENCODING -1 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +28 +10 +00 +78 +CC +70 +3C +CC +78 +ENDCHAR +STARTCHAR Ydieresis +ENCODING -1 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 8 0 0 +BITMAP +14 +00 +C3 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Zcaron +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +28 +10 +00 +FC +18 +30 +60 +C0 +FC +ENDCHAR +STARTCHAR breve +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 6 +BITMAP +90 +60 +ENDCHAR +STARTCHAR bullet +ENCODING -1 +SWIDTH 350 0 +DWIDTH 4 0 +BBX 2 2 1 2 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR caron +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +A0 +40 +ENDCHAR +STARTCHAR circumflex +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +40 +A0 +ENDCHAR +STARTCHAR dagger +ENCODING -1 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -2 +BITMAP +30 +30 +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR daggerdbl +ENCODING -1 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -2 +BITMAP +30 +30 +FC +30 +30 +30 +FC +30 +30 +30 +ENDCHAR +STARTCHAR dotaccent +ENCODING -1 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 1 1 0 7 +BITMAP +80 +ENDCHAR +STARTCHAR dotlessi +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 6 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR ellipsis +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 8 1 1 0 +BITMAP +DB +ENDCHAR +STARTCHAR emdash +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 10 1 0 3 +BITMAP +FFC0 +ENDCHAR +STARTCHAR endash +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 1 0 3 +BITMAP +FC +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 8 -1 0 +BITMAP +36 +60 +F6 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 8 -1 0 +BITMAP +36 +66 +F6 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR florin +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 -2 +BITMAP +38 +60 +F8 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR fraction +ENCODING -1 +SWIDTH 167 0 +DWIDTH 4 0 +BBX 5 7 -1 0 +BITMAP +08 +10 +10 +20 +40 +40 +80 +ENDCHAR +STARTCHAR grave +ENCODING -1 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 6 +BITMAP +80 +40 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 3 1 1 +BITMAP +60 +C0 +60 +ENDCHAR +STARTCHAR guilsinglright +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 3 1 1 +BITMAP +C0 +60 +C0 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 2 0 6 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR lslash +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 8 -1 0 +BITMAP +60 +60 +60 +70 +E0 +60 +60 +60 +ENDCHAR +STARTCHAR oe +ENCODING -1 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 9 6 0 0 +BITMAP +7700 +CD80 +CF80 +CC00 +CD80 +7700 +ENDCHAR +STARTCHAR ogonek +ENCODING -1 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 -2 +BITMAP +80 +C0 +ENDCHAR +STARTCHAR perthousand +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +6200 +B400 +6800 +1000 +2D80 +56C0 +8D80 +ENDCHAR +STARTCHAR quotedblbase +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 -2 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotedblleft +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +48 +90 +D8 +ENDCHAR +STARTCHAR quotedblright +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 -2 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR quotesingle +ENCODING -1 +SWIDTH 238 0 +DWIDTH 3 0 +BBX 1 3 1 5 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR ring +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +40 +A0 +40 +ENDCHAR +STARTCHAR scaron +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +20 +00 +70 +D8 +70 +18 +D8 +70 +ENDCHAR +STARTCHAR tilde +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 6 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR trademark +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 4 1 3 +BITMAP +E880 +4D80 +4A80 +4A80 +ENDCHAR +STARTCHAR zcaron +ENCODING -1 +SWIDTH 500 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +50 +20 +00 +F8 +18 +30 +60 +C0 +F8 +ENDCHAR +ENDFONT diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc-splash.c b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc-splash.c new file mode 100644 index 0000000000..214fe98a42 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc-splash.c @@ -0,0 +1,498 @@ +#include <usplash-theme.h> +#include <usplash_backend.h> + +/********************************************************************************** + This is a USplash based theme for the awsome XBMC Media Center for linux. + Graphics were composed mainly of the official XBMC logos. + + Visit my blog at: + http://du-duke.blogspot.com/ + for some more usplash, xbmc stuff. + + some code snippets were taken from: + http://gnome-look.org/content/show.php/MacX+Usplash+Theme?content=73611 + + =================================================================================== + 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 3 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, see <http://www.gnu.org/licenses/>. + ================================================================================== + +**********************************************************************************/ + +extern struct usplash_pixmap pixmap_xbmc_1920_1200; +extern struct usplash_pixmap pixmap_xbmc_1920_1080; +extern struct usplash_pixmap pixmap_xbmc_1680_1050; +extern struct usplash_pixmap pixmap_xbmc_1440_900; +extern struct usplash_pixmap pixmap_xbmc_1280_1024; +extern struct usplash_pixmap pixmap_xbmc_1366_768; +extern struct usplash_pixmap pixmap_xbmc_1280_720; +extern struct usplash_pixmap pixmap_xbmc_1024_768; +extern struct usplash_pixmap pixmap_xbmc_800_600; +extern struct usplash_pixmap pixmap_xbmc_640_480; + +extern struct usplash_pixmap pixmap_xbmc_spinner; +extern struct usplash_font font_helvB10; + +void t_init(struct usplash_theme* theme); +void t_clear_progressbar(struct usplash_theme* theme); +void t_draw_progressbar(struct usplash_theme* theme, int percentage); +void t_animate_step(struct usplash_theme* theme, int pulsating); +void spinner(struct usplash_theme* theme); + +struct usplash_theme usplash_theme; +struct usplash_theme usplash_theme_1920_1080; +struct usplash_theme usplash_theme_1680_1050; +struct usplash_theme usplash_theme_1440_900; +struct usplash_theme usplash_theme_1280_1024; +struct usplash_theme usplash_theme_1366_768; +struct usplash_theme usplash_theme_1280_720; +struct usplash_theme usplash_theme_1024_768; +struct usplash_theme usplash_theme_800_600; +struct usplash_theme usplash_theme_640_480; + +static int spinner_x, spinner_y, spinner_part_width, spinner_height; +static int current_count = 0; +static int current_step = 0; +static int spinner_num_steps = 12; + +// spinner_speed can be between 1 and 25 +// there are 12 images in the spinner, so a value of 2 will make +// it spin around approx. once per second +static int spinner_speed = 2; + +/** ----------------------------------------------------------------------- **/ + +struct usplash_theme usplash_theme = { + .version = THEME_VERSION, + .next = &usplash_theme_1920_1080, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1920_1200, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1920_1080 = { + .version = THEME_VERSION, + .next = &usplash_theme_1680_1050, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1920_1080, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1680_1050 = { + .version = THEME_VERSION, + .next = &usplash_theme_1440_900, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1680_1050, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1440_900 = { + .version = THEME_VERSION, + .next = &usplash_theme_1280_1024, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1440_900, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1280_1024 = { + .version = THEME_VERSION, + .next = &usplash_theme_1366_768, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1280_1024, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1366_768 = { + .version = THEME_VERSION, + .next = &usplash_theme_1280_720, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1366_768, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1280_720 = { + .version = THEME_VERSION, + .next = &usplash_theme_1024_768, + .ratio = USPLASH_16_9, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1280_720, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_1024_768 = { + .version = THEME_VERSION, + .next = &usplash_theme_800_600, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_1024_768, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_800_600 = { + .version = THEME_VERSION, + .next = &usplash_theme_640_480, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_800_600, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +struct usplash_theme usplash_theme_640_480 = { + .version = THEME_VERSION, + .next = NULL, + .ratio = USPLASH_4_3, + + /* Background and font */ + .pixmap = &pixmap_xbmc_640_480, + .font = &font_helvB10, + + /* Palette indexes */ + .background = 0x01, + .progressbar_background = 0x00, + .progressbar_foreground = 0x1E, + .text_background = 0x01, + .text_foreground = 0xB9, + .text_success = 0x23, + .text_failure = 0x24, + + /* Text box position and size in pixels */ + .text_x = 300, + .text_y = 650, + .text_width = 680, + .text_height = 300, + + /* Text details */ + .line_height = 15, + .line_length = 32, + .status_width = 50, + + /* Functions */ + .init = t_init, + .clear_progressbar = t_clear_progressbar, + .draw_progressbar = t_draw_progressbar, + .animate_step = t_animate_step, +}; + +/** ---------------------------------------------------------- **/ + +/* init usplash */ +void t_init(struct usplash_theme *theme) { + // determine spinner position and dimensions + spinner_height = pixmap_xbmc_spinner.height; + spinner_part_width = pixmap_xbmc_spinner.width / spinner_num_steps; + spinner_x = (theme->pixmap->width / 2) - (spinner_part_width / 2); + spinner_y = (theme->pixmap->height / 2) + (((theme->pixmap->height / 2) / 4) / 2) - (pixmap_xbmc_spinner.height / 2); + + // set text box dimensions and size + theme->text_width = 600; + theme->text_x = (theme->pixmap->width / 2) - (theme->text_width / 2); + theme->text_y = 50; + theme->text_height = 250; + + // set theme color indexes + theme->background = 0; + theme->progressbar_background = 0; + theme->progressbar_foreground = 30; + theme->text_background = 0; + theme->text_foreground = 1; + theme->text_success = 35; + theme->text_failure = 36; +} + +/****** + * Animation callback - called 25 times per second by Usplash + * + * Param: struct usplash_theme* theme - theme being used + * int pulsating - boolean int + */ +void t_animate_step(struct usplash_theme* theme, int pulsating) { + current_count = current_count + 1; + + // increase test int for slower spinning + if(current_count == spinner_speed) { + spinner(theme); + current_count = 0; + } +} + +/******** + * Animate the spinner + * helper function to aid in animation of spinner + */ +void spinner(struct usplash_theme* theme) { + current_step = current_step + 1; + + int x0 = (spinner_part_width * current_step) - spinner_part_width; + int y0 = 0; + + // if current step > number of images in the spinner, then reset to beginning (at end or circular spinner) + if(current_step >= spinner_num_steps) { + current_step = 0; + } + + // call usplash_put_part for the small or large spinner image + usplash_put_part(spinner_x, spinner_y, spinner_part_width, spinner_height, &pixmap_xbmc_spinner, x0, y0); +} + +/** not used for now **/ +void t_clear_progressbar(struct usplash_theme *theme) { } +void t_draw_progressbar(struct usplash_theme *theme, int percentage) { } diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1024_768.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1024_768.png Binary files differnew file mode 100644 index 0000000000..4cae722692 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1024_768.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1280_1024.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1280_1024.png Binary files differnew file mode 100644 index 0000000000..5d9252b834 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1280_1024.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1280_720.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1280_720.png Binary files differnew file mode 100644 index 0000000000..f113c1f02f --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1280_720.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1366_768.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1366_768.png Binary files differnew file mode 100644 index 0000000000..6d85645050 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1366_768.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1440_900.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1440_900.png Binary files differnew file mode 100644 index 0000000000..29f151bcaa --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1440_900.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1680_1050.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1680_1050.png Binary files differnew file mode 100644 index 0000000000..72fe255d69 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1680_1050.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1920_1080.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1920_1080.png Binary files differnew file mode 100644 index 0000000000..10da6f44fb --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1920_1080.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1920_1200.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1920_1200.png Binary files differnew file mode 100644 index 0000000000..cf99f004a5 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_1920_1200.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_640_480.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_640_480.png Binary files differnew file mode 100644 index 0000000000..0f6ae7d31a --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_640_480.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_800_600.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_800_600.png Binary files differnew file mode 100644 index 0000000000..2ff6a390eb --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_800_600.png diff --git a/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_spinner.png b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_spinner.png Binary files differnew file mode 100644 index 0000000000..4630b4cee4 --- /dev/null +++ b/tools/XBMCLive/USplashThemes/spinner-blue/xbmc_spinner.png diff --git a/tools/XBMCLive/diskmounter b/tools/XBMCLive/diskmounter new file mode 100755 index 0000000000..f5c83caad6 --- /dev/null +++ b/tools/XBMCLive/diskmounter @@ -0,0 +1,159 @@ +#!/bin/bash +#################### +# This utility searches for available HFS+, NTFS and FAT32 partitions, creates +# mount points for them and mounts the partitions +# +# (c)2008 Luigi Capriotti <l.capriotti@tiscali.it> for use in LiveXBMCV2 +# Base on "diskmount" by Dennis Kaarsemaker <dennis@ubuntu-nl.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +################### + +VERBOSE='n' + +# Root check +if [[ $UID != 0 ]]; then + echo 'You should run this program as root or using sudo' + exit 1 +fi + +OPTIONS='user,fmask=0133,dmask=0022,uid=1000,gid=1000' +MACOPTIONS='user,file_umask=0133,dir_umask=0022,uid=1000,gid=1000' +EXTOPTIONS='' + +# Now for the real work +drivesntfs=`fdisk -l | grep -i 'ntfs' | awk -F '/| ' '{print $3}'` +drivesfat=`fdisk -l | grep -i 'fat32' | awk -F '/| ' '{print $3}'` +driveshfs=`fdisk -l | grep -i 'Apple_HFS' | awk -F '/| ' '{print $3}'` +drivesext=`fdisk -l | grep -i 'Linux' | grep -v 'swap' | awk -F '/| ' '{print $3}'` + +if [ ! -d /media ]; then + mkdir /media +fi + +donesomething='n' +for drive in $drivesntfs; do + if [[ ! `grep $drive /etc/fstab` && ! `pmount | grep $drive` && ! `mount | grep $drive` ]]; then + if [ -e /sys/block/${drive%?}/removable ]; then + if [ "$(cat /sys/block/${drive%?}/removable)" = "0" ]; then + if [ ! -d /media/$drive ] ; then + mkdir /media/$drive + fi + mount -t ntfs -o rw,$OPTIONS /dev/$drive /media/$drive + + donesomething='y' + if [[ $VERBOSE == 'y' ]]; then + echo "Mounted /dev/$drive as '/media/$drive' (read-only)" + fi + else + if [[ $VERBOSE == 'y' ]]; then + echo "Ignoring /dev/$drive - removable drive" + fi + fi + fi + else + if [[ $VERBOSE == 'y' ]]; then + echo "Ignoring /dev/$drive - already in /etc/fstab or mounted" + fi + fi +done + +for drive in $drivesfat; do + if [[ ! `grep $drive /etc/fstab` && ! `pmount | grep $drive` && ! `mount | grep $drive` ]]; then + if [ -e /sys/block/${drive%?}/removable ]; then + if [ "$(cat /sys/block/${drive%?}/removable)" = "0" ]; then + if [ ! -d /media/$drive ]; then + mkdir /media/$drive + fi + mount -t vfat -o rw,$OPTIONS /dev/$drive /media/$drive + + donesomething='y' + if [[ $VERBOSE == 'y' ]]; then + echo "Mounted /dev/$drive as '/media/$drive' (read-only)" + fi + else + if [[ $VERBOSE == 'y' ]]; then + echo "Ignoring /dev/$drive - removable drive" + fi + fi + fi + else + if [[ $VERBOSE == 'y' ]]; then + echo "Ignoring /dev/$drive - already in /etc/fstab or mounted" + fi + fi +done + + +for drive in $driveshfs; do + if [[ ! `grep $drive /etc/fstab` && ! `pmount | grep $drive` && ! `mount | grep $drive` ]]; then + if [ -e /sys/block/${drive%?}/removable ]; then + if [ "$(cat /sys/block/${drive%?}/removable)" = "0" ]; then + if [ ! -d /media/$drive ]; then + mkdir /media/$drive + fi + mount -t hfsplus -o rw,$MACOPTIONS /dev/$drive /media/$drive + + donesomething='y' + if [[ $VERBOSE == 'y' ]]; then + echo "Mounted /dev/$drive as '/media/$drive' (read-only)" + fi + else + if [[ $VERBOSE == 'y' ]]; then + echo "Ignoring /dev/$drive - removable drive" + fi + fi + fi + else + if [[ $VERBOSE == 'y' ]]; then + echo "Ignoring /dev/$drive - already in /etc/fstab or mounted" + fi + fi +done + +for drive in $drivesext; do + if [[ ! `grep $drive /etc/fstab` && ! `pmount | grep $drive` && ! `mount | grep $drive` ]]; then + if [ -e /sys/block/${drive%?}/removable ]; then + if [ "$(cat /sys/block/${drive%?}/removable)" = "0" ]; then + if [ ! -d /media/$drive ]; then + mkdir /media/$drive + fi + mount -o rw,$EXTOPTIONS /dev/$drive /media/$drive + + donesomething='y' + if [[ $VERBOSE == 'y' ]]; then + echo "Mounted /dev/$drive as '/media/$drive' (read-only)" + fi + else + if [[ $VERBOSE == 'y' ]]; then + echo "Ignoring /dev/$drive - removable drive" + fi + fi + fi + else + if [[ $VERBOSE == 'y' ]]; then + echo "Ignoring /dev/$drive - already in /etc/fstab or mounted" + fi + fi +done + +if [[ $VERBOSE == 'y' ]]; then + if [[ $donesomething == 'y' ]]; then + echo "All Linux, Windows and Mac partitions on non-removable disks have been mounted" + else + echo "No usable Linux, Windows or Mac partitions found on non-removable disks" + fi +fi + diff --git a/tools/XBMCLive/installXBMC b/tools/XBMCLive/installXBMC new file mode 100755 index 0000000000..7bfe37ccb5 --- /dev/null +++ b/tools/XBMCLive/installXBMC @@ -0,0 +1,715 @@ +#!/usr/bin/env python +""" + "XBMC Live" installer + V0.996 - 20090526 + Luigi Capriotti @2009 + +""" + +import tempfile +import os, re, sys, time +import subprocess +import random +import shutil +import statvfs +import optparse + +gMinSizeMB = 1500 + +# For HDD installations +gFixedDiskMinSizeMB = 5000 +gBootPartitionSizeMB = 4096 +gSwapPartitionSizeMB = 512 + +gPermStorageFilename = "ext3fs.img" +gBootPartMountPoint = "/tmp/bootPart" +gLivePartMountPoint = "/tmp/livePart" + +gDebugMode = 0 +gInstallerLogFileName = "/var/tmp/installXBMC.log" + +def runSilent(aCmdline): + writeLog("Running: " + aCmdline) + process = subprocess.Popen(aCmdline, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) + stdout_value, stderr_value = process.communicate() + retCode = process.returncode + writeLog("Return code= " + str(retCode)) + writeLog("Results: StdOut=" + repr(stdout_value)) + writeLog("Results: StdErr=" + repr(stderr_value)) + return stdout_value, retCode + +def diskSizeKB(aVolume): + diskusage, retCode = runSilent('fdisk -l ' + aVolume + ' | grep "Disk ' + aVolume + '" | cut -f 5 -d " "') + nBytes = int(diskusage) + return int(nBytes / 1024) + +def freeSpaceMB(aPath): + stats, retCode = runSilent("df -Pk " + aPath) + return int(stats.splitlines()[1].split()[3])/1024 + +def readFile(the_file): + f = file(the_file, 'r') + content = f.read() + f.close() + return content + +def writeFile(the_file, content): + f = file(the_file, 'w') + f.write(content) + f.close + +def writeLog(aLine): + global gInstallerLogFileName + global gDebugMode + + if gDebugMode > 0: + time_now = time.strftime("[%H:%M:%S] ", time.localtime()) + f = file(gInstallerLogFileName, 'a') + f.write(time_now + aLine + '\n') + f.close + +def getKernelParameter(token): + aParam=None + l=open('/proc/cmdline').readline().strip() + for t in l.split(): + if t.startswith(token + '='): + aParam = t.split('=',1)[1] + + return aParam + +def findBootVolume(lookForRootFS): + if not lookForRootFS: + rootPartition = getKernelParameter('root') + if rootPartition.startswith('UUID='): + anUUID = rootPartition.split('=',1)[1] + rootPartition, retCode = runSilent('blkid | grep "' + anUUID + '" | cut -d ":" -f 1') + return rootPartition + + bootMedia = getKernelParameter('boot') + driveList = ["sr0","sr1","sr2","sr3"] + if bootMedia == 'disk' or bootMedia == 'usb': + driveList = ["sda","sdb","sdc","sdd","sde","sdf","sdg"] + + # Find the drive we booted from + found = False + for deviceNode in driveList: + device = "/dev/" + deviceNode + print "Checking device " + device + " for installation source..." + if os.path.exists(device): + if os.path.exists("/sys/block/" + deviceNode + "/removable"): + if isRemovableDisk(device): + if bootMedia == 'disk' or bootMedia == 'usb': + device = device + "1" + mountDevice(device, "", gBootPartMountPoint) + else: + mountDevice(device, "-o ro -t iso9660", gBootPartMountPoint) + + if os.path.exists(gBootPartMountPoint + "/rootfs.img"): + print "Found Boot drive on " + device + found = True + + umountDevice(gBootPartMountPoint) + + if found == True: + break + + print device + " does not contain a rootfs." + + if found == False: + device = None + + return device + +def isRemovableDisk(aDevice): + aDeviceNode = aDevice.split("/")[2] + + fName='/sys/block/' + aDeviceNode + '/removable' + if os.path.exists(fName): + return int(open(fName).readline().strip()) + return 0 + + +def userChoice(prompt, charsGo, charsStop): + bGoOn=0 + while 1: + choice = raw_input(prompt) + if choice == '': + continue + if choice in charsGo: + bGoOn = choice + break + if choice in charsStop: + break + + return bGoOn + +def findDisks(bootDisk): + availDisk = [] + + while 1: + found=0 + for deviceNode in ['sda','sdb','sdc','sdd','sde','sdf','sdg']: + device = "/dev/" + deviceNode + if bootDisk.find(device) >=0: + print "Skipping boot device (" + device + ") ..." + else: + print "Checking device " + device +" ..." + + if os.path.exists(device): + aFile = '/sys/block/' + deviceNode + '/size' + if open(aFile).readline().strip() != "0" : + availDisk.append(device) + + aString = "Found disk: " + device + if isRemovableDisk(device): + aString += " - Removable disk." + print aString + found=1 + + if found == 1: + break + + raw_input("No drives detected, connect a disk and press return...") + print "" + print "Scanning again disk drives..." + print "" + + return availDisk + +def chooseDisk(availableDrives): + if len(availableDrives) == 0: + print + print "No disks" + print + return 0 + print "" + print "Choose disk to use" + print "" + availChoices="" + nChoice = 0 + for t in availableDrives: + diskSizeMB = int(diskSizeKB(t))/1000 + nChoice += 1 + availChoices += str(nChoice) + aString = " " + str(nChoice) + ": " + t + " (" + str(diskSizeMB) + " MB)" + + if isRemovableDisk(t): + aString += " - Removable disk" + else: + aString += " - FIXED disk" + print aString + + print "" + return userChoice("Type the digit, or 0 to restart the procedure: ", availChoices, "0") + +def partitionFormatDisk(device, bIsRemovableDisk, bootPartSize, swapPartSize): + runSilent("dd if=/dev/zero of=" + device + " bs=512 count=2") + runSilent("sync") + + if bIsRemovableDisk: + strFdiskCommands = ["o","n","p","1","","","t","c","a","1","w"] + + stdInFile = tempfile.NamedTemporaryFile() + for line in strFdiskCommands: + stdInFile.write(line + "\n") + stdInFile.flush() + + runSilent("cat " + stdInFile.name + " | fdisk " + device) + stdInFile.close() + + runSilent("mkfs.vfat -I -F 32 -n XBMCLive_" + str(random.randint(0, 999)) + " " + device + "1") + return + + partEnd = "" + if bootPartSize > 0: + partEnd = "+" + str(bootPartSize) + "M" + + strFdiskCommands = ["o","n","p","1","",partEnd,"a","1","w"] + stdInFile = tempfile.NamedTemporaryFile() + for line in strFdiskCommands: + stdInFile.write(line + "\n") + stdInFile.flush() + + runSilent("cat " + stdInFile.name + " | fdisk " + device) + stdInFile.close() + + runSilent("mkfs.ext3 " + device + "1") + + if swapPartSize != 0: + partEnd = "+" + str(swapPartSize) + "M" + + strFdiskCommands = ["n","p","2","",partEnd,"t","2","82","n","p","3","","","w"] + stdInFile = tempfile.NamedTemporaryFile() + for line in strFdiskCommands: + stdInFile.write(line + "\n") + stdInFile.flush() + + runSilent("cat " + stdInFile.name + " | fdisk " + device) + stdInFile.close() + + runSilent("mkswap -c " + device +"2") + runSilent("mkfs.ext3 " + device +"3") + else: + strFdiskCommands = ["n","p","2","","","w"] + stdInFile = tempfile.NamedTemporaryFile() + for line in strFdiskCommands: + stdInFile.write(line + "\n") + stdInFile.flush() + + runSilent("cat " + stdInFile.name + " | fdisk " + device) + stdInFile.close() + + runSilent("mkfs.ext3 " + device +"2") + + runSilent("sync") + + # For debugging purposes only + runSilent("fdisk -l " + device) + runSilent("mount") + +def mountDevice(aDevice, mountOpts, aDirectory): + if not os.path.exists(aDirectory): + os.mkdir(aDirectory) + + outStr, retCode = runSilent("mount " + mountOpts + " " + aDevice + " " + aDirectory) + if retCode > 0: + print "Error mounting device: " + aDevice + " - Exiting." + writeLog("Error mounting device: " + aDevice + " - Exiting.") + runSilent("sleep 5") + sys.exit(-1) + +def umountDevice(aDirectory, removeMountPoint=True): + outStr, retCode = runSilent("umount " + aDirectory) + if retCode > 0: + print "Error unmounting directory: " + aDirectory + " - Exiting." + writeLog("Error unmounting directory: " + aDirectory + " - Exiting.") + runSilent("sleep 5") + sys.exit(-1) + + if removeMountPoint == True: + os.rmdir(aDirectory) + +def copySystemFiles(srcDirectory, dstDirectory, bIsRemovableDisk, skipLargeFiles): + global gDebugMode + # This one needs python 2.6, for future use + # Do not copy storage file + # shutil.copytree(srcDirectory, dstDirectory, ignore=shutil.ignore_patterns(gPermStorageFilename)) + + if not os.path.exists(dstDirectory): + os.mkdir(dstDirectory) + + # For debugging purposes only + runSilent("mount") + runSilent("ls -aRl " + srcDirectory) + runSilent("ls -aRl " + dstDirectory) + + if bIsRemovableDisk: + for root, dirs, files in os.walk(srcDirectory): + for file in files: + # Do not copy storage file + if file == gPermStorageFilename: + continue + + writeLog("Copying file: " + file) + if skipLargeFiles == True: + if file.find("img") > 0: + writeLog("TEST MODE = " + str(gDebugMode) + " : file skipped.") + continue + + from_ = os.path.join(root, file) + to_ = from_.replace(srcDirectory, dstDirectory, 1) + to_directory = os.path.split(to_)[0] + if not os.path.exists(to_directory): + os.makedirs(to_directory) + try: + shutil.copyfile(from_, to_) + except: + writeLog("Error copying file: " + file + " - check your media") + print "Error copying file: " + file + " - check your media" + continue + + if not os.path.exists(dstDirectory + "/" + "Config"): + os.mkdir(dstDirectory + "/" + "Config") + else: + tmpMountPoint="/tmp/tmpMntPoint" + + mountDevice(srcDirectory + "/rootfs.img", "-o ro,loop -t squashfs", tmpMountPoint) + runSilent("cp -a " + tmpMountPoint + "/* " + dstDirectory) + umountDevice(tmpMountPoint) + + # Defaults to current GPU + # May fail if more than one GPU is available (nvidia has proprity though) + hasAMD, retCode = runSilent("lspci -nn | grep 0300 | grep 1002") + hasNVIDIA, retCode = runSilent("lspci -nn | grep 0300 | grep 10de") + + if len(hasNVIDIA): + print "Installing NVIDIA restricted drivers..." + writeLog("Installing NVIDIA restricted drivers...") + mountDevice(srcDirectory + "/restrictedDrivers.nvidia.img", "-o ro,loop", tmpMountPoint) + runSilent("cp -a " + tmpMountPoint + "/* " + dstDirectory) + umountDevice(tmpMountPoint) + elif len(hasAMD): + print "Installing ATI/AMD restricted drivers..." + writeLog("Installing ATI/AMD restricted drivers...") + mountDevice(srcDirectory + "/restrictedDrivers.amd.img", "-o ro,loop", tmpMountPoint) + runSilent("cp -a " + tmpMountPoint + "/* " + dstDirectory) + umountDevice(tmpMountPoint) + + if not os.path.exists(dstDirectory + "/boot"): + os.mkdir(dstDirectory + "/boot") + + aFileName = os.readlink("/initrd.img") + # writeLog("Src=" + srcDirectory + "/initrd0.img") + # writeLog("Dest=" + dstDirectory + "/" + aFileName) + try: + writeLog("Copying " + srcDirectory + "/initrd0.img") + shutil.copyfile(srcDirectory + "/initrd0.img", dstDirectory + "/" + aFileName) + except: + writeLog("Error copying file: " + "initrd0.img") + print "Error copying file: " + "initrd0.img" + " - check your media" + + aFileName = os.readlink("/vmlinuz") + # writeLog("Src=" + srcDirectory + "/vmlinuz") + # writeLog("Dest=" + dstDirectory + "/" + aFileName) + try: + writeLog("Copying " + srcDirectory + "/vmlinuz") + shutil.copyfile(srcDirectory + "/vmlinuz", dstDirectory + "/" + aFileName) + except: + writeLog("Error copying file: " + "vmlinuz") + print "Error copying file: " + "vmlinuz" + " - check your media" + + # shutil.copyfile(srcDirectory + "/boot/xbmc.xpm.gz", dstDirectory + "/boot/xbmc.xpm.gz") + for root, dirs, files in os.walk(srcDirectory + "/boot"): + for file in files: + from_ = os.path.join(root, file) + to_ = from_.replace(srcDirectory, dstDirectory, 1) + to_directory = os.path.split(to_)[0] + if not os.path.exists(to_directory): + os.makedirs(to_directory) + try: + # print "Copying from: " + from_ + " to>: " + to_ + shutil.copyfile(from_, to_) + except: + print "Error copying file: " + file + " - check your media" + writeLog("Error copying file: " + file) + continue + + +def createPermanentStorageFile(aFileFName, aSizeMB): + aCmdLine = "dd if=/dev/zero of=" + aFileFName + " bs=4M count=" + str(aSizeMB/4) + runSilent(aCmdLine) + runSilent("mkfs.ext3 -F " + aFileFName) + return + +def findUUID(aPartition): + cmdLine = 'blkid -s UUID | grep ' + aPartition + ' | cut -d " " -f 2 | cut -d "=" -f 2 | sed \'s/"//g' + "'" + anUUID, retCode = runSilent(cmdLine) + return anUUID.rstrip("\n\r") + +def installGrub(bootDevice, dstDirectory): + runSilent("grub-install --recheck --root-directory=" + dstDirectory + " " + bootDevice) + +def modifyGrubMenu(menuFName, isaRemovableDrive, bootPartition): + if isaRemovableDrive: + content = readFile(menuFName) + if isaRemovableDrive == 1: + content = re.sub("boot=[a-z]*", "boot=usb", content) + else: + content = re.sub("boot=[a-z]*", "boot=disk", content) + else: + content = ("default 0" + "\n") + content += ("hiddenmenu" + "\n") + content += ("timeout 5" + "\n") + content += ("foreground eeeeee" + "\n") + content += ("background 333333" + "\n") + content += ("splashimage=/boot/xbmc.xpm.gz" + "\n") + content += ("\n") + content += ("title XBMCLive" + "\n") + content += ("kernel /vmlinuz root=UUID=" + findUUID(bootPartition) + " quiet splash xbmc=nodiskmount,tempfs,setvolume,noredir loglevel=0" + "\n") + content += ("initrd /initrd.img" + "\n") + content += ("boot" + "\n") + content += ("\n") + content += ("title XBMCLive - SAFE MODE" + "\n") + content += ("kernel /vmlinuz root=UUID=" + findUUID(bootPartition) + " xbmc=nodiskmount,noredir loglevel=0" + "\n") + content += ("initrd /initrd.img" + "\n") + content += ("boot" + "\n") + content += ("\n") + + writeFile(menuFName, content) + +def changePasswords(liveRootDir): + # Lock root account + runSilent("passwd -l root") + + print "Please set a new password for user 'xbmc':" + while 1: + retcode = subprocess.call(["passwd", "xbmc"]) + if retcode >= 0: + break + + shutil.copyfile("/etc/shadow", liveRootDir + "/etc/shadow") + +def prepareFstab(liveRootDir, bootDevice, swapFileSize): + # Prepare /etc/fstab + content = "unionfs / unionfs defaults 0 0\n" + content += "proc /proc proc defaults 0 0\n" + + if swapFileSize == 0: + content += ("UUID=" + findUUID(bootDevice + "2") + " /home ext3 defaults,auto 0 0\n") + else: + content += ("UUID=" + findUUID(bootDevice + "2") + " none swap sw,auto 0 0\n") + content += ("UUID=" + findUUID(bootDevice + "3") + " /home ext3 defaults,auto 0 0\n") + writeFile(liveRootDir + "/etc/fstab", content) + + +def prepareHomeDirectory(bootDevice, swapFileSize): + homeMountPoint = "/tmp/homePart" + + if swapFileSize > 0: + mountDevice(bootDevice + "3", "", homeMountPoint) + else: + mountDevice(bootDevice + "2", "", homeMountPoint) + + if not os.path.exists(homeMountPoint + "/xbmc"): + os.mkdir(homeMountPoint + "/xbmc") + + if not os.path.exists(homeMountPoint + "/xbmc/Videos"): + os.mkdir(homeMountPoint + "/xbmc/Videos") + + if not os.path.exists(homeMountPoint + "/xbmc/Pictures"): + os.mkdir(homeMountPoint + "/xbmc/Pictures") + + if not os.path.exists(homeMountPoint + "/xbmc/Music"): + os.mkdir(homeMountPoint + "/xbmc/Music") + + if not os.path.exists(homeMountPoint + "/xbmc/.xbmc"): + os.mkdir(homeMountPoint + "/xbmc/.xbmc") + + if not os.path.exists(homeMountPoint + "/xbmc/.xbmc/userdata"): + os.mkdir(homeMountPoint + "/xbmc/.xbmc/userdata") + + # Create a sources.xml referencing the above created directories + content = "<sources>" + content += " <video>" + content += " <default></default>" + content += " <source>" + content += " <name>Videos</name>" + content += " <path>/home/xbmc/Videos/</path>" + content += " </source>" + content += " </video>" + content += " <music>" + content += " <default></default>" + content += " <source>" + content += " <name>Music</name>" + content += " <path>/home/xbmc/Music/</path>" + content += " </source>" + content += " </music>" + content += " <pictures>" + content += " <default></default>" + content += " <source>" + content += " <name>Pictures</name>" + content += " <path>/home/xbmc/Pictures/</path>" + content += " </source>" + content += " </pictures>" + content += "</sources>" + + writeFile(homeMountPoint + "/xbmc/.xbmc/userdata/sources.xml", content) + + runSilent("chown -R xbmc:xbmc " + homeMountPoint + "/xbmc") + umountDevice(homeMountPoint) + +def main(): + global gMinSizeMB + global gFixedDiskMinSizeMB + global gBootPartitionSizeMB + global gSwapPartitionSizeMB + global gPermStorageFilename + global gBootPartMountPoint + global gLivePartMountPoint + global gInstallerLogFileName + global gDebugMode + + parser = optparse.OptionParser() + parser.add_option("-i", dest="isoFileName", help="Use specified ISO file as source for XBMC Live files", default=None) + parser.add_option("-d", dest="debugMode", action="store_true", help="Creates debug log file: " + gInstallerLogFileName, default=False) + parser.add_option("-l", dest="debugFileName", help="Use specified file as debug log file", default=None) + parser.add_option("-s", dest="skipFileCopy", action="store_true", help="Do not copy IMG files (debug helper)", default=False) + parser.add_option("-c", dest="doNotShutdown", action="store_true", help="Do not perform a shutdown after execution", default=False) + (cmdLineOptions, args) = parser.parse_args() + + if cmdLineOptions.debugMode == True: + cmdLineOptions.doNotShutdown = True + gDebugMode = 1 + + if not cmdLineOptions.debugFileName == None: + gInstallerLogFileName = cmdLineOptions.debugFileName + cmdLineOptions.doNotShutdown = True + gDebugMode = 1 + + if cmdLineOptions.skipFileCopy == True: + cmdLineOptions.doNotShutdown = True + gDebugMode = 1 + + if not cmdLineOptions.isoFileName == None: + cmdLineOptions.doNotShutdown = True + gDebugMode = 1 + + writeLog("-- Installer Start --") + + if not cmdLineOptions.isoFileName == None: + if not os.path.exists(cmdLineOptions.isoFileName): + print "File: " + cmdLineOptions.isoFileName + " does not exist, exiting..." + sys.exit(-1) + + cmdLine = 'file -b -i ' + cmdLineOptions.isoFileName + aType, retCode = runSilent(cmdLine) + if not aType.find("iso9660") >0: + print "File: " + cmdLineOptions.isoFileName + " is not a valid ISO image, exiting..." + sys.exit(-1) + + availableDisks = [] + + while True: + os.system('clear') + print "" + print "XBMC Live bootable disk creator" + print "---------------------" + print "" + print "The procedure will create a XBMC Live bootable disk" + print "" + print "Requirements:" + print " for USB flash disks: the disk must have at least " + str(gMinSizeMB) + " MB of capacity!" + print " for fixed disks: the disk must have at least " + str(gFixedDiskMinSizeMB) + " MB of capacity!" + print "" + print "CAUTION: the process will erase all data on the specified disk drive!" + print "CAUTION: this is an experimental tool, use at your own risk!" + print "" + raw_input("Press a key to continue, or Ctrl-C to exit.") + + print "" + print "Identifying boot disk..." + print "" + bootVolume = findBootVolume( (cmdLineOptions.isoFileName == None) ) + if bootVolume == None: + if cmdLineOptions.doNotShutdown == True: + raw_input("Error locating boot media, exiting.") + sys.exit(-1) + + raw_input("Error locating boot media, press a key to shutdown...") + runSilent("shutdown -h now") + runSilent("sleep 10") + sys.exit(-1) + + print "Enumerating available disks..." + print "" + availableDisks = findDisks(bootVolume) + + diskIndex = chooseDisk(availableDisks) + if diskIndex == 0: + continue + diskIndex = int(diskIndex) - 1 + removableDiskSelected = isRemovableDisk(availableDisks[diskIndex]) + + diskSizeMB = diskSizeKB(availableDisks[diskIndex])/1024 + minSizeMB = gMinSizeMB + if not removableDiskSelected: + print "" + print "" + print "The selected disk appears to be a fixed disk." + print "" + + if userChoice("Do you want the installer to handle it as a removable disk instead (Y/N)? ","Yy","Nn") == 0: + minSizeMB = gFixedDiskMinSizeMB + else: + removableDiskSelected = 10 + + if diskSizeMB < minSizeMB: + print "" + print "" + print "The selected disk is too small." + if removableDiskSelected: + print "The minimum requirements for removable disks are: " + str(gMinSizeMB) + " MB of disk size" + else: + print "The minimum requirements for fixed disks are: " + str(gFixedDiskMinSizeMB) + " MB of disk size" + print + print "The selected disk has only " + str(diskSizeMB) + " MB of disk space." + print "" + print "Please ignore the selected disk and try again." + print "" + raw_input("Press a button to restart the procedure. ") + continue + + if userChoice("Erasing disk " + availableDisks[diskIndex] + ", proceed (Y/N)? ","Yy","Nn") == 0: + continue + + print "Partitioning & formatting disk..." + + partitionFormatDisk(availableDisks[diskIndex], removableDiskSelected, gBootPartitionSizeMB, gSwapPartitionSizeMB) + + print "Copying system files - please wait..." + + mountDevice(availableDisks[diskIndex] + "1", "", gLivePartMountPoint) + + if cmdLineOptions.isoFileName == None: + bootMedia = getKernelParameter('boot') + mountOpts = "-o ro -t iso9660" + if bootMedia == 'disk' or bootMedia == 'usb': + mountOpts = "-t vfat" + mountDevice(bootVolume, mountOpts, gBootPartMountPoint) + else: + mountDevice(cmdLineOptions.isoFileName, "-o loop", gBootPartMountPoint) + + copySystemFiles(gBootPartMountPoint, gLivePartMountPoint, removableDiskSelected, cmdLineOptions.skipFileCopy) + + umountDevice(gBootPartMountPoint) + + print "Installing GRUB..." + + installGrub(availableDisks[diskIndex], gLivePartMountPoint) + + if not gDebugMode > 10: + if removableDiskSelected: + print "" + print " XBMC Live saves all system changes into a file, if available." + print " If such a file, called 'permanent storage file' does not exist," + print " changes to system configuration are lost when rebooting." + print "" + if not userChoice("Do you want to create a permanent system storage file (Y/N)? ","Yy","Nn") == 0: + availSpace = freeSpaceMB(availableDisks[diskIndex] + "1") + storageSize = (availSpace/10)*7 + if storageSize > 4000: + storageSize = 4000 + print "Permanent system storage size = " + str(storageSize) + " MB, Please wait..." + createPermanentStorageFile(gLivePartMountPoint + "/" + gPermStorageFilename, storageSize) + + modifyGrubMenu(gLivePartMountPoint + "/boot/grub/menu.lst", removableDiskSelected, availableDisks[diskIndex] + "1") + + if not removableDiskSelected: + print "Applying system changes..." + prepareFstab(gLivePartMountPoint, availableDisks[diskIndex], gSwapPartitionSizeMB) + changePasswords(gLivePartMountPoint) + prepareHomeDirectory(availableDisks[diskIndex], gSwapPartitionSizeMB) + + umountDevice(gLivePartMountPoint) + + print "All done!" + print "" + + if cmdLineOptions.doNotShutdown == True: + print "Exiting..." + break + + if userChoice("Do you want to create another bootable disk (Y/N)? ","Yy","Nn") == 0: + print "Shutting down the system in 5 seconds..." + runSilent("sleep 5") + runSilent("shutdown -h now") + sys.exit(-1) + + +if __name__ == '__main__': + # Make sure only root can run the script + if os.getuid() != 0: + print "This script must be run as root." + sys.exit(-1) + + main() diff --git a/tools/XBMCLive/installXBMCFromISO.sh b/tools/XBMCLive/installXBMCFromISO.sh new file mode 100755 index 0000000000..254d618223 --- /dev/null +++ b/tools/XBMCLive/installXBMCFromISO.sh @@ -0,0 +1,23 @@ +#/bin/bash + +restoreAutomount=0 +CHECKGCONFDIR="$(gconftool-2 --dir-exists=/apps/nautilus/preferences)" +if [ "${CHECKGCONFDIR}" = "0" ]; then + CHECKAUTOMOUNT="$(gconftool-2 --get /apps/nautilus/preferences/media_automount)" + if [ "${CHECKAUTOMOUNT}" = "true" ]; then + restoreAutomount=1 + echo "Please disconnect any USB disks and press a key when done..." + read choice + echo Disabling USB automount... + gconftool-2 --set /apps/nautilus/preferences/media_automount --type=bool false + echo "Please connect the USB disk and press a key when done..." + read choice + fi +fi + +sudo python ./installXBMC.py -l ./XBMCLive.log -i ./XBMCLive.iso + +if [ "$restoreAutomount" = "1" ]; then + echo Restoring USB automount... + gconftool-2 --set /apps/nautilus/preferences/media_automount --type=bool true +fi diff --git a/tools/XBMCLive/live-initramfs/COPYING b/tools/XBMCLive/live-initramfs/COPYING new file mode 100644 index 0000000000..d511905c16 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/tools/XBMCLive/live-initramfs/Makefile b/tools/XBMCLive/live-initramfs/Makefile new file mode 100644 index 0000000000..e01ae9b5ac --- /dev/null +++ b/tools/XBMCLive/live-initramfs/Makefile @@ -0,0 +1,134 @@ +# Makefile + +TRANSLATIONS="it" + +all: build + +test: + # Checking for syntax errors + set -e; for SCRIPT in bin/* hooks/* scripts/live scripts/live-functions scripts/live-helpers scripts/*/*; \ + do \ + sh -n $$SCRIPT; \ + done + + # Checking for bashisms (temporary not failing, but only listing) + if [ -x /usr/bin/checkbashisms ]; \ + then \ + checkbashisms bin/* hooks/* scripts/live scripts/live-functions scripts/live-helpers scripts/*/* || true; \ + else \ + echo "bashism test skipped - you need to install devscripts."; \ + fi + +build: + $(MAKE) -C manpages + +install: test build + # Installing configuration + install -D -m 0644 conf/live.conf $(DESTDIR)/etc/live.conf + install -D -m 0644 conf/compcache $(DESTDIR)/usr/share/initramfs-tools/conf.d/compcache + + # Installing executables + mkdir -p $(DESTDIR)/sbin + cp bin/live-getty bin/live-login bin/live-new-uuid bin/live-snapshot bin/live-swapfile $(DESTDIR)/sbin + + mkdir -p $(DESTDIR)/usr/share/live-initramfs + cp bin/live-preseed bin/live-reconfigure contrib/languagelist $(DESTDIR)/usr/share/live-initramfs + + mkdir -p $(DESTDIR)/usr/share/initramfs-tools + cp -r hooks scripts $(DESTDIR)/usr/share/initramfs-tools + + # Installing documentation + mkdir -p $(DESTDIR)/usr/share/doc/live-initramfs + cp -r COPYING docs/* $(DESTDIR)/usr/share/doc/live-initramfs + + mkdir -p $(DESTDIR)/usr/share/doc/live-initramfs/examples + cp -r conf/* $(DESTDIR)/usr/share/doc/live-initramfs/examples + + # Installing manpages + set -e; for MANPAGE in manpages/*.en.1; \ + do \ + install -D -m 0644 $$MANPAGE $(DESTDIR)/usr/share/man/man1/`basename $$MANPAGE .en.1`.1; \ + done + + set -e; for MANPAGE in manpages/*.en.7; \ + do \ + install -D -m 0644 $$MANPAGE $(DESTDIR)/usr/share/man/man7/`basename $$MANPAGE .en.7`.7; \ + done + + set -e; for TRANSLATIONS in $$TRANSLATIONS; \ + do \ + for MANPAGE in manpages/*.$$TRANSLATION.1; \ + do \ + install -D -m 0644 $$MANPAGE $(DESTDIR)/usr/share/man/$$TRANSLATION/man1/`basename $$MANPAGE .$$TRANSLATION.1`.1; \ + done; \ + for MANPAGE in manpages/*.$$TRANSLATION.7; \ + do \ + install -D -m 0644 $$MANPAGE $(DESTDIR)/usr/share/man/$$TRANSLATION/man7/`basename $$MANPAGE .$$TRANSLATION.7`.7; \ + done; \ + done + + # Temporary symlinks + ln -sf live-initramfs.7.gz $(DESTDIR)/usr/share/man/man7/live-getty.7.gz + ln -sf live-initramfs.7.gz $(DESTDIR)/usr/share/man/man7/live-login.7.gz + +uninstall: + # Uninstalling configuration + rm -f $(DESTDIR)/etc/live.conf + + # Uninstalling executables + rm -f $(DESTDIR)/sbin/live-getty $(DESTDIR)/sbin/live-login $(DESTDIR)/sbin/live-snapshot $(DESTDIR)/sbin/live-swapfile + rm -rf $(DESTDIR)/usr/share/live-initramfs + rm -f $(DESTDIR)/usr/share/initramfs-tools/hooks/live + rm -rf $(DESTDIR)/usr/share/initramfs-tools/scripts/live* + rm -f $(DESTDIR)/usr/share/initramfs-tools/scripts/local-top/live + + # Uninstalling documentation + rm -rf $(DESTDIR)/usr/share/doc/live-initramfs + + # Uninstalling manpages + set -e; for MANPAGE in manpages/*.en.1; \ + do \ + rm -f $(DESTDIR)/usr/share/man/man1/`basename $$MANPAGE .en.1`.1; \ + done + + set -e; for MANPAGE in manpages/*.en.7; \ + do \ + rm -f $(DESTDIR)/usr/share/man/man7/`basename $$MANPAGE .en.7`.7; \ + done + + set -e; for TRANSLATIONS in $$TRANSLATIONS; \ + do \ + for MANPAGE in manpages/*.$$TRANSLATION.1; \ + do \ + install -D -m 0644 $$MANPAGE $(DESTDIR)/usr/share/man/$$TRANSLATION/man1/`basename $$MANPAGE .$$TRANSLATION.1`.1; \ + done; \ + for MANPAGE in manpages/*.$$TRANSLATION.7; \ + do \ + install -D -m 0644 $$MANPAGE $(DESTDIR)/usr/share/man/$$TRANSLATION/man7/`basename $$MANPAGE .$$TRANSLATION.7`.7; \ + done; \ + done + + # Temporary symlinks + rm -f $(DESTDIR)/usr/share/man/man7/live-getty.7.gz + rm -f $(DESTDIR)/usr/share/man/man7/live-login.7.gz + +update: + set -e; for FILE in docs/parameters.txt; \ + do \ + sed -i -e 's/2007\\-11\\-19/2007\\-11\\-26/' \ + -e 's/2007-11-19/2007-11-26/' \ + -e 's/19.11.2007/26.11.2007/' \ + -e 's/1.113.1/1.113.2/' \ + $$FILE; \ + done + + # Update language list + wget -O "contrib/languagelist" \ + "http://svn.debian.org/viewsvn/*checkout*/d-i/trunk/packages/localechooser/languagelist" + +clean: + $(MAKE) -C manpages clean + +distclean: + +reinstall: uninstall install diff --git a/tools/XBMCLive/live-initramfs/README b/tools/XBMCLive/live-initramfs/README new file mode 100644 index 0000000000..012aaed790 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/README @@ -0,0 +1,5 @@ +This tree contains a test branch of Debian's live-initramfs including some modifications for Ubuntu compatibility. + +Both Jaunty and Karmic are supported. + + diff --git a/tools/XBMCLive/live-initramfs/bin/live-getty b/tools/XBMCLive/live-initramfs/bin/live-getty new file mode 100755 index 0000000000..6781ea5878 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/bin/live-getty @@ -0,0 +1,20 @@ +#!/bin/sh + +set -e + +AUTOLOGIN="1" + +for ARGUMENT in "${@}" +do + if [ "${ARGUMENT}" = "-l" ] || [ "${ARGUMENT}" = "-n" ] + then + AUTOLOGIN="0" + fi +done + +if [ "${AUTOLOGIN}" = "1" ] +then + exec /sbin/getty -n -l /sbin/live-login ${*} +else + exec /sbin/getty ${*} +fi diff --git a/tools/XBMCLive/live-initramfs/bin/live-login b/tools/XBMCLive/live-initramfs/bin/live-login new file mode 100755 index 0000000000..c2cc5a132e --- /dev/null +++ b/tools/XBMCLive/live-initramfs/bin/live-login @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +USERNAME="root" + +if [ -f /etc/live.conf ] +then + . /etc/live.conf +fi + +exec /bin/login -f "${USERNAME}" diff --git a/tools/XBMCLive/live-initramfs/bin/live-new-uuid b/tools/XBMCLive/live-initramfs/bin/live-new-uuid new file mode 100755 index 0000000000..97cc7d4faa --- /dev/null +++ b/tools/XBMCLive/live-initramfs/bin/live-new-uuid @@ -0,0 +1,75 @@ +#!/bin/sh +# -*- coding: utf-8 -*- +# +# «live-new-uuid» - Creates and injects new UUIDs for live disks +# +# Create new UUIDs for disks to prevent conflicts and booting the wrong live +# directory. Particularly useful in creating recovery disks that need to be +# able to also work with recovery partitioning schemes. +# +# Copyright (C) 2008, Dell Inc. +# +# Author: +# - Mario Limonciello <Mario_Limonciello@Dell.com> +# +# This script 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 application; if not, write to the Free Software Foundation, Inc., 51 +# Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +################################################################################## + +set -e + +help() { + echo + echo "USAGE: $0 initrd.gz <path-to-new-initrd.gz> <path-to-new-live-uuid> " + echo + echo "initrd.gz is the absolute path to the original gzipped initramfs" + echo "<path-to-new-initrd.gz> is the destination directory for the new gzipped initramfs" + echo "<path-to-new-live-uuid> is the destination directory for the new live-uuid-TYPE " + echo + echo "if either path is absent, they will end up in the current directory " + echo "TYPE is determined by an already existing live-uuid-* or by 'uname -s'" +} + +if [ "$#" = "0" ] || [ "x$1" = x-h ] || [ "x$1" = x--help ]; then + help + exit 3 +fi + +CWD=`pwd` +TEMPDIR=`mktemp -d /tmp/uuid-XXXXXX` +TYPE=`uname -r | cut -d '-' -f 3` + +if [ -z "$2" ] || [ ! -d "$2" ] || [ "$2" = "." ]; then + GZIPDIR="$CWD" +else + GZIPDIR="$2" +fi + +if [ -z "$3" ] || [ ! -d "$3" ] || [ "$3" = "." ]; then + LIVEDIR="$CWD" +else + LIVEDIR="$3" +fi + +cd "$TEMPDIR" +zcat "$1" | cpio -id +uuidgen -r > conf/uuid.conf +find . | cpio --quiet --dereference -o -H newc | gzip > "$GZIPDIR/initrd.gz" +if [ "$(ls "$LIVEDIR/live-uuid"-* >/dev/null 2>&1 | wc -l)" = 1 ]; then + cp conf/uuid.conf "$LIVEDIR/live-uuid"-* +else + cp conf/uuid.conf "$LIVEDIR/live-uuid-$TYPE" +fi +cd "$CWD" +rm -rf "$TEMPDIR" diff --git a/tools/XBMCLive/live-initramfs/bin/live-preseed b/tools/XBMCLive/live-initramfs/bin/live-preseed new file mode 100755 index 0000000000..d98c4f36fc --- /dev/null +++ b/tools/XBMCLive/live-initramfs/bin/live-preseed @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +PATH=/usr/sbin:/usr/bin:/sbin:/bin + +root="${1}" +question="${2}" +value="${3}" +seen="${4}" + +[ "${seen}" ] || seen=true + +if ! (echo "SET ${question} ${value}"; echo "FSET ${question} seen ${seen}") | chroot "${1}" /usr/bin/debconf-communicate -fnoninteractive live-initramfs >/dev/null +then + +chroot "${1}" /usr/bin/debconf-communicate -fnoninteractive live-initramfs >/dev/null << EOF +REGISTER debian-installer/dummy ${question} +SET ${question} ${value} +FSET ${question} seen ${seen} +EOF + +fi + +exit 0 diff --git a/tools/XBMCLive/live-initramfs/bin/live-reconfigure b/tools/XBMCLive/live-initramfs/bin/live-reconfigure new file mode 100755 index 0000000000..16cb51dfa4 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/bin/live-reconfigure @@ -0,0 +1,70 @@ +#! /bin/sh + +set -e + +export PATH=/usr/bin:/usr/sbin:/sbin:/bin + +frontend=noninteractive + +findcommandinroot () +{ + ROOT="${1}/" + shift + + while [ "${#}" -ge 1 ] + do + P="${PATH}" + + while [ "${P}" ] + do + D=${P%%:*} + P=${P#*:} + + if [ "${D}" = "${P}" ] + then + P= + fi + + if [ -z "${D}" ] + then + D=. + fi + + if [ -x "${ROOT}${D}/${1}" ] + then + echo "${D}/${1}" + return 0 + fi + done + + shift + done + + return 1 +} + +runcommandinroot () +{ + C=$(findcommandinroot "${1}" "${2}") + ROOT="${1}" + + shift + shift + + [ -n "${C}" ] && chroot "${ROOT}" "${C}" "${@}" +} + +root="${1}" +package="${2}" + +version=$(runcommandinroot "${root}" dpkg-query -W --showformat='${Version}' "${package}" 2>/dev/null) || version="" + +if [ -z "${version}" ] +then + echo >&2 "${0}: package '${package}' is not installed" + exit 0 +fi + +runcommandinroot "${root}" dpkg-reconfigure -fnoninteractive --no-reload "${package}" + +exit 0 diff --git a/tools/XBMCLive/live-initramfs/bin/live-snapshot b/tools/XBMCLive/live-initramfs/bin/live-snapshot new file mode 100755 index 0000000000..18b067bda7 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/bin/live-snapshot @@ -0,0 +1,522 @@ +#!/bin/sh + +# live-snapshot - utility to manage Debian Live systems snapshots +# +# This program mounts a device (fallback to /tmpfs under $MOUNTP +# and saves the /live/cow (or a different directory) filesystem in it +# for reuse in another live-initramfs session. +# Look at the manpage for more informations. +# +# Copyright (C) 2006-2008 Marco Amadori <marco.amadori@gmail.com> +# Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk> +# +# 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 3 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, see <http://www.gnu.org/licenses/>. +# +# On Debian systems, the complete text of the GNU General Public License +# can be found in /usr/share/common-licenses/GPL-3 file. + +# declare here two vars from /etc/live.conf because of "set -u" +ROOTSNAP="" +HOMESNAP="" + +if [ -n "${LIVE_SNAPSHOT_CHECK_UNBOUND}" ] +then + set -eu +else + set -e +fi + +. /usr/share/initramfs-tools/scripts/live-helpers + +LIVE_CONF="/etc/live.conf" +. "${LIVE_CONF}" + +export USERNAME USERFULLNAME HOSTNAME + +EXECUTABLE="${0}" +PROGRAM=$(basename "${EXECUTABLE}") + +# Needs to be available at run and reboot time +SAFE_TMPDIR="/live" + +# Permits multiple runs +MOUNTP="$(mktemp -d -p ${SAFE_TMPDIR} live-snapshot-mnt.XXXXXX)" +DEST="${MOUNTP}/live-sn.cpio.gz" +DEF_SNAP_COW="/live/cow" +TMP_FILELIST="${PROGRAM}.list" + +# Command line defaults and declarations +SNAP_COW="${DEF_SNAP_COW}" +SNAP_DEV="" +SNAP_MNT="" +SNAP_OUTPUT="" +SNAP_RESYNC_STRING="" +SNAP_TYPE="cpio" +SNAP_LIST="/etc/live-snapshot.list" +EXCLUDE_LIST="/etc/live-snapshot.exclude_list" + +Error () +{ + echo "${PROGRAM}: error:" ${@} + exit 1 +} + +panic () +{ + Error ${@} +} + +Header () +{ + echo "${PROGRAM} - utility to perform snapshots of Debian Live systems" + echo + echo "usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--device DEVICE] [-o|--output FILE] [-t|--type TYPE]" + echo " ${PROGRAM} [-r|--resync-string STRING]" + echo " ${PROGRAM} [-f|--refresh]" + echo " ${PROGRAM} [-h|--help]" + echo " ${PROGRAM} [-u|--usage]" + echo " ${PROGRAM} [-v|--version]" +} + +Help () +{ + Header + + echo + echo "Options:" + echo " -c, --cow: copy on write directory (default: ${SNAP_COW})." + echo " -d, --device: output snapshot device (default: ${SNAP_DEV:-auto})." + echo " -o, --output: output image file (default: ${DEST})." + echo " -r, --resync-string: internally used to resync previous made snapshots." + echo " -f, --refresh: try to sync a running snapshot." + echo " -t, --type: snapshot filesystem type. Options: \"squashfs\", \"ext2\", \"ext3\", \"ext4\", \"jffs2\" or \"cpio\".gz archive (default: ${SNAP_TYPE})" + echo + echo "Look at live-snapshot(1) man page for more information." + + exit 0 +} + +Usage () +{ + Header + + echo + echo "Try \"${PROGRAM} --help\" for more information." + + exit 0 +} + +Version () +{ + echo "${PROGRAM}" + echo + echo "Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>" + echo "Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>" + echo + echo "This program is free software; you can redistribute it and/or modify" + echo "it under the terms of the GNU General Public License as published by" + echo "the Free Software Foundation; either version 2 of the License, or" + echo "(at your option) any later version." + echo + echo "This program is distributed in the hope that it will be useful," + echo "but WITHOUT ANY WARRANTY; without even the implied warranty of" + echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" + echo "GNU General Public License for more details." + echo + echo "You should have received a copy of the GNU General Public License" + echo "along with this program; if not, write to the Free Software" + echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA" + echo + echo "On Debian systems, the complete text of the GNU General Public License" + echo "can be found in /usr/share/common-licenses/GPL-2 file." + echo + echo "Homepage: <http://debian-live.alioth.debian.org/>" + + exit 0 +} + +Try_refresh () +{ + FOUND="" + if [ -n "${ROOTSNAP}" ]; then + "${EXECUTABLE}" --resync-string="${ROOTSNAP}" + FOUND="Yes" + fi + + if [ -n "${HOMESNAP}" ]; then + "${EXECUTABLE}" --resync-string="${HOMESNAP}" + FOUND="Yes" + fi + + if [ -z "${FOUND}" ] + then + echo "No autoconfigured snapshots found at boot;" > /dev/null 1>&2 + echo "(no resync string in ${LIVE_CONF})." > /dev/null 1>&2 + exit 1 + fi +} + +Parse_args () +{ + # Parse command line + ARGS="${*}" + ARGUMENTS="$(getopt --longoptions cow:,device:,output,resync-string:,refresh,type:,help,usage,version --name=${PROGRAM} --options c:d:o:t:r:fhuv --shell sh -- ${ARGS})" + + eval set -- "${ARGUMENTS}" + + while true + do + case "${1}" in + -c|--cow) + SNAP_COW="${2}" + shift 2 + ;; + + -d|--device) + SNAP_DEV="${2}" + shift 2 + ;; + + -o|--output) + SNAP_OUTPUT="${2}" + shift 2 + ;; + + -t|--type) + SNAP_TYPE="${2}" + shift 2 + ;; + + -r|--resync-string) + SNAP_RESYNC_STRING="${2}" + break + ;; + + -f|--refresh) + Try_refresh + exit 0 + ;; + + -h|--help) + Help + ;; + + -u|--usage) + Usage + ;; + + -v|--version) + Version + ;; + + --) + shift + break + ;; + + *) + Error "internal error." + ;; + + esac + done +} + +Defaults () +{ + # Parse resync string + if [ -n "${SNAP_RESYNC_STRING}" ] + then + SNAP_COW=$(echo "${SNAP_RESYNC_STRING}" | sed -e 's|^/root\([^:.]*\).*$|'"${DEF_SNAP_COW}"'\1|') + SNAP_DEV=$(echo "${SNAP_RESYNC_STRING}" | cut -f2 -d ':') + SNAP_MNT=$(echo "${SNAP_RESYNC_STRING}" | cut -f3 -d ':') + DEST="${MOUNTP}/${SNAP_MNT}" + + case "${SNAP_MNT}" in + *.cpio.gz) + SNAP_TYPE="cpio" + ;; + + *.squashfs) + SNAP_TYPE="squashfs" + ;; + + *.jffs2) + SNAP_TYPE="jffs2" + ;; + + *.ext2|*.ext3) + SNAP_TYPE="ext2" + ;; + + "") + SNAP_TYPE="whole_partition" + ;; + + *.ext4) + SNAP_TYPE="ext4" + ;; + + *) + Error "unrecognized resync string" + ;; + esac + elif [ -z "${SNAP_OUTPUT}" ] + then + # Set target file based on image + case "${SNAP_TYPE}" in + cpio) + DEST="${MOUNTP}/live-sn.cpio.gz" + ;; + + squashfs|jffs2|ext2) + DEST="${MOUNTP}/live-sn.${SNAP_TYPE}" + ;; + + ext3) + DEST="${MOUNTP}/live-sn.ext2" + ;; + + ext4) + DEST="${MOUNTP}/live-sn.ext4" + ;; + esac + else + DEST="${SNAP_OUTPUT}" + fi +} + +Validate_input () +{ + case "${SNAP_TYPE}" in + cpio|squashfs|jffs2|ext2|ext3|ext4|whole_partition) + ;; + + *) + Error "invalid filesystem type \"${SNAP_TYPE}\"" + ;; + esac + + if [ ! -d "${SNAP_COW}" ] + then + Error "${SNAP_COW} is not a directory" + fi + + if [ "$(id -u)" -ne 0 ] + then + Error "you are not root" + fi +} + +Mount_device () +{ + case "${SNAP_DEV}" in + "") + # create a temp + mount -t tmpfs -o rw tmpfs "${MOUNTP}" + ;; + + *) + if [ -b "${SNAP_DEV}" ] + then + try_mount "${SNAP_DEV}" "${MOUNTP}" rw + fi + ;; + esac +} + +Entry_is_modified () +{ + # Returns true if file exists and it is also present in "cow" directory + # This means it is modified in respect to read-only media, so it deserve + # to be saved + + entry="${1}" + + if [ -e "${entry}" ] || [ -L "${entry}" ] + then + if [ -e "${SNAP_COW}/${entry}" ] || [ -L "${SNAP_COW}/${entry}" ] + then + return 0 + fi + fi + return 1 +} + +Do_filelist () +{ + # BUGS: does not handle deleted files yet + TMP_FILELIST=$1 + + if [ -f "${SNAP_LIST}" ] + then + # if SNAP_COW == /live/cow/home, SNAP_RW = /home + SNAP_RW=$(echo "${SNAP_COW}" | sed -e "s|${DEF_SNAP_COW}||g") + if [ -z "${SNAP_RW}" ] + then + SNAP_RW="/" + fi + + cd "${SNAP_RW}" + # Generate include list removing empty and commented lines + # and transforming paths to relatives + for entry in $(sed -e '/^ *$/d' -e '/^#.*$/d' -e 's#^.*$#./&#' -e 's#/\+#/#g' "${SNAP_LIST}") + do + if [ -d "${entry}" ] + then + find "${entry}" | while read line + do + if Entry_is_modified "${line}" + then + printf "%s\000" "${line}" >> "${TMP_FILELIST}" + fi + done + elif Entry_is_modified "${entry}" + then + # if file exists and it is modified + printf "%s\000" "${entry}" >> "${TMP_FILELIST}" + fi + done + cd "${OLDPWD}" + + # echo Working dir + echo "${SNAP_RW}" + else + cd "${SNAP_COW}" + # removing whiteouts from list + find . -path '*.wh.*' -prune -o -print0 >> "${TMP_FILELIST}" + cd "${OLDPWD}" + # echo Working dir + echo "${SNAP_COW}" + fi +} + +Do_snapshot () +{ + TMP_FILELIST=$(mktemp -p "${SAFE_TMPDIR}" "${TMP_FILELIST}.XXXXXX") + + case "${SNAP_TYPE}" in + squashfs) + echo ".${TMP_FILELIST}" > "${TMP_FILELIST}" + # Removing whiteheads of unionfs + cd "${SNAP_COW}" + find . -name '*.wh.*' >> "${TMP_FILELIST}" + + if [ -e "${EXCLUDE_LIST}" ] + then + # Add explicitly excluded files + grep -v '^#.*$' "${EXCLUDE_LIST}" | grep -v '^ *$' >> "${TMP_FILELIST}" + fi + + cd "${OLDPWD}" + mksquashfs "${SNAP_COW}" "${DEST}" -ef "${TMP_FILELIST}" + ;; + + cpio|whole_partition) + if [ "${SNAP_TYPE}" = "cpio" ] + then + COPY_CMD="cpio --quiet -o0 -H newc | gzip -9c > ${DEST}" + else + COPY_CMD="cpio --quiet -pumd0 ${DEST}/" + fi + + WORKING_DIR=$(Do_filelist "${TMP_FILELIST}") + cd "${WORKING_DIR}" + if [ -e "${EXCLUDE_LIST}" ] + then + # Convert \0 to \n and tag existing (rare but possible) \n in filenames, + # this to let grep -F -v do a proper work in filtering out + cat "${TMP_FILELIST}" | \ + tr '\n' '\1' | \ + tr '\0' '\n' | \ + grep -F -v -f "${EXCLUDE_LIST}" | \ + tr '\n' '\0' | \ + tr '\1' '\n' | \ + $COPY_CMD || exit 1 + else + cat "${TMP_FILELIST}" | \ + $COPY_CMD || exit 1 + fi + cd "${OLDPWD}" + ;; + + # ext2|ext3|ext4 and jffs2 does not easily support an exclude list; files + # should be copied to another directory in order to filter content + ext2|ext3|ext4) + DU_DIM="$(du -ks ${SNAP_COW} | cut -f1)" + REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} / 20)" # Just 5% more to be sure, need something more sophistcated here... + genext2fs --size-in-blocks=${REAL_DIM} --reserved-percentage=0 --root="${SNAP_COW}" "${DEST}" + ;; + + jffs2) + mkfs.jffs2 --root="${SNAP_COW}" --output="${DEST}" + ;; + esac + + if [ -f "${TMP_FILELIST}" ] + then + rm -f "${TMP_FILELIST}" + fi +} + +Clean () +{ + if [ -z "${SNAP_RESYNC_STRING}" ] && echo "${DEST}" | grep -q "${MOUNTP}" + then + echo "${DEST} is present on ${MOUNTP}, therefore no automatic unmounting the latter." > /dev/null 1>&2 + else + umount "${MOUNTP}" + rmdir "${MOUNTP}" + fi +} + +Warn_user () +{ + if [ -z "${SNAP_RESYNC_STRING}" ] + then + case ${SNAP_TYPE} in + cpio|ext2|ext3|ext4) + echo "Please move ${DEST} (if is not already in it)" > /dev/null 1>&2 + echo "in a supported writable partition (e.g ext3, vfat)." > /dev/null 1>&2 + ;; + + squashfs) + echo "To use ${DEST} you need to rebuild your media or add it" > /dev/null 1>&2 + echo "to your multisession disc under the \"/live\" directory." > /dev/null 1>&2 + ;; + + jffs2) + echo "Please cat or flashcp ${DEST} to your partition in order to start using it." > /dev/null 1>&2 + ;; + esac + + if grep -qv persistent /proc/cmdline + then + echo "Remember to boot this live system with \"persistent\" specified at boot prompt." > /dev/null 1>&2 + fi + fi +} + +Main () +{ + Parse_args "${@}" + Defaults + Validate_input + trap 'Clean' EXIT + Mount_device + Do_snapshot + Warn_user +} + +Main "${@:-}" diff --git a/tools/XBMCLive/live-initramfs/bin/live-swapfile b/tools/XBMCLive/live-initramfs/bin/live-swapfile new file mode 100755 index 0000000000..2c6103694b --- /dev/null +++ b/tools/XBMCLive/live-initramfs/bin/live-swapfile @@ -0,0 +1,100 @@ +#!/bin/sh + +# File: live-swapfile - create and use a swap file +# Copyright: (C) 2009 Daniel Baumann <daniel@debian.org> +# License: GPL-3+ + +set -e + +# Options +_SWAP_DIRECTORY="${_SWAP_DIRECTORY:-/live/swap}" +_SWAP_FILE="${_SWAP_FILE:-swapfile.img}" + +_SWAP_SIZE="${_SWAP_SIZE:-auto}" +_SWAP_FACTOR="${_SWAP_FACTOR:-2}" + +_SWAP_PURGE="${_SWAP_PURGE:-true}" +_FORCE="${_FORCE:-true}" + +case "${1}" in + add) + # Reading size of physical memory + _MEM_TOTAL_KB="$(awk '/^MemTotal: / { print $2 }' /proc/meminfo)" + _MEM_TOTAL_MB="$(expr ${_MEM_TOTAL_KB} / 1024)" + + echo "Found ${_MEM_TOTAL_MB} MB physical memory." + + # Setting size of new swapfile + if [ -z "${_SWAP_SIZE}" ] || [ "${_SWAP_SIZE}" = "auto" ] + then + _SWAP_SIZE_KB="$(expr ${_MEM_TOTAL_KB} '*' ${_SWAP_FACTOR})" + _SWAP_SIZE_MB="$(expr ${_SWAP_SIZE_KB} / 1024)" + else + _SWAP_SIZE_MB="${_SWAP_SIZE}" + fi + + echo "Requesting ${_SWAP_SIZE_MB} MB swapfile." + + # Reading size of old swapfile + if [ -e "${_SWAP_DIRECTORY}/${_SWAP_FILE}" ] + then + _SWAP_FILESIZE="$(ls -hl ${_SWAP_DIRECTORY}/${_SWAP_FILE} | awk '{ print $5 }')" + + echo "Found ${_SWAP_FILESIZE} MB swapfile." + fi + + # Creating new swap file + if [ "${_SWAP_FILESIZE}" != "${_SWAP_SIZE_MB}M" ] + then + if [ "${_FORCE}" = "true" ] + then + # Removing old swapfile + rm -f "${_SWAP_DIRECTORY}/${_SWAP_FILE}" + + echo "Creating ${_SWAP_SIZE_MB} MB swapfile." + + mkdir -p "${_SWAP_DIRECTORY}" + + # Unfortunately, swapon does not support files + # with holes, therefore we cannot preallocate. + dd if=/dev/zero of="${_SWAP_DIRECTORY}/${_SWAP_FILE}" bs=1024k count="${_SWAP_SIZE_MB}" + else + echo "Exit." + return 1 + fi + fi + + echo "Enabling ${_SWAP_DIRECTORY}/${_SWAP_FILE}." + + mkswap "${_SWAP_DIRECTORY}/${_SWAP_FILE}" + swapon "${_SWAP_DIRECTORY}/${_SWAP_FILE}" + ;; + + rm|remove) + if grep -qs "${_SWAP_DIRECTORY}/${_SWAP_FILE}" /proc/swaps + then + echo "Disabling ${_SWAP_DIRECTORY}/${_SWAP_FILE}." + + swapoff "${_SWAP_DIRECTORY}/${_SWAP_FILE}" + fi + + if [ "${_SWAP_PURGE}" = "true" ] + then + echo "Removing ${_SWAP_DIRECTORY}/${_SWAP_FILE}." + + rm -f "${_SWAP_DIRECTORY}/${_SWAP_FILE}" + + __DIRECTORY="${_SWAP_DIRECTORY}" + while [ "${__DIRECTORY}" != "/" ] + do + rmdir --ignore-fail-on-non-empty "${__DIRECTORY}" + __DIRECTORY="$(dirname ${__DIRECTORY})" + done + fi + ;; + + *) + echo "Usage: ${0} {add|remove}" + exit 1 + ;; +esac diff --git a/tools/XBMCLive/live-initramfs/build-stamp b/tools/XBMCLive/live-initramfs/build-stamp new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/build-stamp diff --git a/tools/XBMCLive/live-initramfs/conf/compcache b/tools/XBMCLive/live-initramfs/conf/compcache new file mode 100644 index 0000000000..c93c77626c --- /dev/null +++ b/tools/XBMCLive/live-initramfs/conf/compcache @@ -0,0 +1 @@ +COMPCACHE_SIZE="25%" diff --git a/tools/XBMCLive/live-initramfs/conf/live-persistence.binds b/tools/XBMCLive/live-initramfs/conf/live-persistence.binds new file mode 100644 index 0000000000..b2c3833a85 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/conf/live-persistence.binds @@ -0,0 +1,15 @@ +# /etc/live-persistence.binds example +# +# If this file is present in the proper path, each uncommented not empty line +# will be treated as a directory which should not be made persistent and +# which it's content should be volatile. +# +# This is achieved by bind mounting on it a tmpfs clone of the directory specified + +# Exclude some standard temporary paths +/tmp +/var/log +/var/cache + +# Firefox profiles are not always useful to remember +/root/.mozilla diff --git a/tools/XBMCLive/live-initramfs/conf/live-snapshot.exclude_list b/tools/XBMCLive/live-initramfs/conf/live-snapshot.exclude_list new file mode 100644 index 0000000000..82972e36fd --- /dev/null +++ b/tools/XBMCLive/live-initramfs/conf/live-snapshot.exclude_list @@ -0,0 +1,17 @@ +# /etc/live-snapshot.exclude_list example +# +# If this file is present in the proper path, each uncommented not empty line +# will be excluded in the target snapshot when live-snapshot is run. +# +# The syntax for the line is just a full file or directory pathname. + +# Each line is treated like a plain match string for "grep -F -v", +# so be careful: e.g. "/tmp" will exclude also "/var/tmp" ! + +# Exclude some standard temporary paths +/tmp +/var/log +/var/cache + +# Firefox profiles are not always useful to remember +/root/.mozilla diff --git a/tools/XBMCLive/live-initramfs/conf/live-snapshot.list b/tools/XBMCLive/live-initramfs/conf/live-snapshot.list new file mode 100644 index 0000000000..db057335a0 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/conf/live-snapshot.list @@ -0,0 +1,20 @@ +# /etc/live-snapshot resync list example +# +# If this file is present, each uncommented not empty line will be parsed when +# running live-snapshot and included in target snapshot. +# +# The syntax for the line is just a full file or directory pathname. +# Those files and directories, and only those will be included on automatic persistence handling. +# +# Note that in home-sn snapshot all those paths are treated as relative to /home + +# Include itself for reuse +/etc/live-snapshot.list + +# Include networking setups +/etc/network/interfaces +/etc/resolv.conf +/etc/hosts + +# Include the whole Desktop directory of the default user +/home/user/Desktop diff --git a/tools/XBMCLive/live-initramfs/conf/live.conf b/tools/XBMCLive/live-initramfs/conf/live.conf new file mode 100644 index 0000000000..0de5b6c9bf --- /dev/null +++ b/tools/XBMCLive/live-initramfs/conf/live.conf @@ -0,0 +1,7 @@ +# /etc/live.conf - configuration file for live-initramfs(7) + +USERNAME="user" +USERFULLNAME="Debian Live user" +HOSTNAME="debian" + +export USERNAME USERFULLNAME HOSTNAME diff --git a/tools/XBMCLive/live-initramfs/contrib/languagelist b/tools/XBMCLive/live-initramfs/contrib/languagelist new file mode 100644 index 0000000000..2d2a4f16d4 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/contrib/languagelist @@ -0,0 +1,93 @@ +# +# This is the complete list of languages (locales) to choose from. +# langcode;language (en);language (orig);supported_environments;countrycode;fallbacklocale;langlist;console-data +sq;Albanian;Shqip;2;AL;sq_AL.UTF-8;;kbd=lat0-sun16(utf8) +am;Amharic;አማáˆáŠ›;4;ET;am_ET;; +ar;Arabic;عربي;3;EG;ar_EG.UTF-8;;console-setup +eu;Basque;Euskaraz;1;ES;eu_ES.UTF-8;;kbd=lat0-sun16(utf8) +be;Belarusian;БеларуÑкаÑ;2;BY;be_BY.UTF-8;;console-setup +bn;Bengali;বাংলা;4;BD;bn_BD;; +bs;Bosnian;Bosanski;2;BA;bs_BA.UTF-8;;kbd=Lat2-Terminus16(utf8) +bg;Bulgarian;БългарÑки;2;BG;bg_BG.UTF-8;;console-setup +# For C locale, set language to 'en' to make sure questions are "translated" +# to English instead of showing codes. +C;C;No localization;0;;C;en; +ca;Catalan;Català ;1;ES;ca_ES.UTF-8;;kbd=lat0-sun16(utf8) +# Special case for Chinese as the two flavours share the same ISO 639 code +# Both will trigger countrychooser. Each will be the backup for the other +# one +zh_CN;Chinese (Simplified);ä¸æ–‡(简体);3;CN;zh_CN.UTF-8;zh_CN:zh; +zh_TW;Chinese (Traditional);ä¸æ–‡(ç¹é«”);3;TW;zh_TW.UTF-8;zh_TW:zh; +hr;Croatian;Hrvatski;2;HR;hr_HR.UTF-8;;kbd=lat2-sun16(utf8) +cs;Czech;ÄŒeÅ¡tina;2;CZ;cs_CZ.UTF-8;;kbd=lat2-sun16(utf8) +da;Danish;Dansk;1;DK;da_DK.UTF-8;;kbd=lat0-sun16(utf8) +nl;Dutch;Nederlands;1;NL;nl_NL.UTF-8;;kbd=lat0-sun16(utf8) +dz;Dzongkha;རྫོང་à½à¼;4;BT;dz_BT;; +en;English;English;0;US;en_US.UTF-8;;kbd=lat0-sun16(utf8) +# The Esperanto locale *is* (or will be as of 1/11/2006) eo.UTF-8 +# so no country on purpose. The default country is Antarctica because... +# ...why not..:-) +eo;Esperanto;Esperanto;2;AQ;eo.UTF-8;;console-setup +et;Estonian;Eesti;2;EE;et_EE.UTF-8;;kbd=lat0-sun16(utf8) +fi;Finnish;Suomi;1;FI;fi_FI.UTF-8;;kbd=lat0-sun16(utf8) +fr;French;Français;1;FR;fr_FR.UTF-8;;console-setup +gl;Galician;Galego;1;ES;gl_ES.UTF-8;;kbd=lat0-sun16(utf8) +ka;Georgian;ქáƒáƒ თული;4;GE;ka_GE.UTF-8;;console-setup +de;German;Deutsch;1;DE;de_DE.UTF-8;;kbd=lat0-sun16(utf8) +el;Greek;Ελληνικά;2;GR;el_GR.UTF-8;;console-setup +gu;Gujarati;ગà«àªœàª°àª¾àª¤à«€;4;IN;gu_IN;; +he;Hebrew;עברית;3;IL;he_IL.UTF-8;;console-setup +hi;Hindi;हिनà¥à¤¦à¥€ ;4;IN;hi_IN;; +hu;Hungarian;Magyar;2;HU;hu_HU.UTF-8;;kbd=lat2-sun16(utf8) +#X is;Icelandic;Ãslenska;1;IS;is_IS.UTF-8;;kbd=lat9u-16(utf8) +id;Indonesian;Bahasa Indonesia;1;ID;id_ID.UTF-8;;kbd=lat0-sun16(utf8) +#X ga;Irish;Gaeilge;1;IE;ga_IE.UTF-8;;kbd=lat0-sun16(utf8) +it;Italian;Italiano;1;IT;it_IT.UTF-8;;kbd=lat0-sun16(utf8) +ja;Japanese;日本語;3;JP;ja_JP.UTF-8;; +#X kn;Kannada;ಕನà³à²¨à²¡;4;IN;kn_IN;; +#X ks;Kashmiri;कोशà¥à¤°;4;IN;ks_IN;; +#X kk;Kazakh;Қазақ;2;KZ;kk_KZ.UTF-8;;console-setup +km;Khmer;ážáŸ’មែរ;4;KH;km_KH;; +ko;Korean;í•œêµì–´;3;KR;ko_KR.UTF-8;; +ku;Kurdish;Kurdî;2;TR;ku_TR.UTF-8;;kbd=Lat15-Terminus16(utf8) +#X lo;Lao;ລາວ;4;LA;lo_LA;;console-setup +lv;Latvian;Latviski;2;LV;lv_LV.UTF-8;;kbd=lat7-14(utf8) +lt;Lithuanian;LietuviÅ¡kai;2;LT;lt_LT.UTF-8;;kbd=LatArCyrHeb-16(utf8) +#X mg;Malagasy;Malagasy;1;MG;mg_MG.UTF-8;mg_MG:fr_FR:fr:en;kbd=lat0-sun16(utf8) +#X ms;Malay;Bahasa Malaysia;1;MY;ms_MY.UTF-8;;kbd=lat0-sun16(utf8) +ml;Malayalam;മലയാളഠ;4;IN;ml_IN;; +mr;Marathi;मराठी;4;IN;mr_IN;; +mk;Macedonian;МакедонÑки;2;MK;mk_MK.UTF-8;;console-setup +ne;Nepali;नेपाली ;4;NP;ne_NP;; +# The Sami translation is really incomplete. We however keep Sami on request +# of Skolelinux as a kind of reward to them..:-). They need to be able to +# choose Sami as an option so that the Sami locale is set as default +se_NO;Northern Sami;Sámegillii;1;NO;se_NO.UTF-8;se_NO:nb_NO:nb:no_NO:no:nn_NO:nn:da:sv:en;kbd=lat0-sun(utf8) +nb_NO;Norwegian Bokmaal;Norsk bokmÃ¥l;1;NO;nb_NO.UTF-8;nb_NO:nb:no_NO:no:nn_NO:nn:da:sv:en;kbd=lat0-sun16(utf8) +nn_NO;Norwegian Nynorsk;Norsk nynorsk;1;NO;nn_NO.UTF-8;nn_NO:nn:no_NO:no:nb_NO:nb:da:sv:en;kbd=lat0-sun16(utf8) +#X fa;Persian;Ùارسی;3;IR;fa_IR;;console-setup +pl;Polish;Polski;2;PL;pl_PL.UTF-8;;kbd=lat2-sun16(utf8) +pt;Portuguese;Português;1;PT;pt_PT.UTF-8;pt:pt_BR:en;kbd=lat0-sun16(utf8) +pt_BR;Portuguese (Brazil);Português do Brasil;1;BR;pt_BR.UTF-8;pt_BR:pt:en;kbd=lat1-16(utf8) +pa;Punjabi (Gurmukhi);ਪੰਜਾਬੀ;4;IN;pa_IN;; +ro;Romanian;Română;2;RO;ro_RO.UTF-8;;kbd=Lat2-Terminus16(utf8) +ru;Russian;РуÑÑкий;2;RU;ru_RU.UTF-8;;console-setup +#X sa;Sanskrit;संसà¥à¤•à¥ƒà¤¤;4;IN;sa_IN;; +# Serbian commented for consistency: too incomplete +#X sr;Serbian;СрпÑки;2;CS;sr_YU.UTF-8@cyrillic;;console-setup +sk;Slovak;SlovenÄina;2;SK;sk_SK.UTF-8;;kbd=lat2-sun16(utf8) +sl;Slovenian;SlovenÅ¡Äina;2;SI;sl_SI.UTF-8;;kbd=lat2-sun16(utf8) +es;Spanish;Español;1;ES;es_ES.UTF-8;;kbd=lat0-sun16(utf8) +sv;Swedish;Svenska;1;SE;sv_SE.UTF-8;;kbd=lat0-sun16(utf8) +tl;Tagalog;Tagalog;1;PH;tl_PH.UTF-8;;kbd=lat0-sun16(utf8) +ta;Tamil;தமிழà¯;4;IN;ta_IN;; +#X te;Telugu;తెలà±à°—à±;4;IN;te_IN;; +th;Thai;ภาษาไทย;4;TH;th_TH.UTF-8;;console-setup +tr;Turkish;Türkçe;2;TR;tr_TR.UTF-8;;kbd=Lat15-Terminus16(utf8) +uk;Ukrainian;УкраїнÑька;2;UA;uk_UA.UTF-8;;console-setup +#X ur;Urdu;اردو;3;PK;ur_PK.UTF-8;;console-setup +#X ca@valencia;Valencian-Catalan;Valencià -Català ;1;ES;ca_ES.UTF-8@valencia;;kbd=lat0-sun16(utf8) +vi;Vietnamese;Tiếng Việt;3;VN;vi_VN.UTF-8;;console-setup +#X cy;Welsh;Cymraeg;2;GB;cy_GB.UTF-8;;kbd=iso14.f16(utf8) +wo;Wolof;Wolof;2;SN;wo_SN;wo:fr:en; +#X xh;Xhosa;Xhosa;2;ZA;xh_ZA.UTF-8;;kbd=lat0-sun16(utf8) diff --git a/tools/XBMCLive/live-initramfs/debian/bug/live-initramfs.script b/tools/XBMCLive/live-initramfs/debian/bug/live-initramfs.script new file mode 100644 index 0000000000..d56b03530d --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/bug/live-initramfs.script @@ -0,0 +1,13 @@ +#!/bin/sh + +# Checking depends +dpkg -l busybox file initramfs-tools sudo udev user-setup + +# Checking recommends +dpkg -l eject uuid-runtime wget + +# Checking suggests +dpkg -l loop-aes-utils curlftpfs genext2fs httpfs2 squashfs-tools mtd-tools + +# Checking other packages +dpkg -l cryptsetup splashy usplash diff --git a/tools/XBMCLive/live-initramfs/debian/changelog b/tools/XBMCLive/live-initramfs/debian/changelog new file mode 100644 index 0000000000..13b83fdf56 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/changelog @@ -0,0 +1,801 @@ +live-initramfs (1.157.3-1) unstable; urgency=medium + + * ad-hoc fixes for Ubuntu Jaunty, Karmic + + -- Luigi Capriotti <l.capriotti@xbmc.org> Thu, 23 June 2009 10:00:00 +0200 + +live-initramfs (1.157.2-1) unstable; urgency=medium + + * Correcting fstab handling to not always append entries forever when using + persistency. + * Correcting kdm live-autologin handling to not always append entries forever + when using persistency. + * Correcting handling of locale default and environment handling to not always + append entries forever when using persistency. + * Correcting swap partition handling in fstab to not always append entries + forever when using persistency. + * Applying patch from Michael Prokop <mika@grml.org> to support udev >= 0.140. + * Merging swap live-bottom script into fstab script; there is no other sane + possibility to prevent appending again and again in persistent mode. + * Making sure that old swap entries are removed before new ones are added. + * Adding cryptsetup to recommends, it's used for encrypted persistent + partitions. + * Restoring previous behaviour of ejecting the cd when being in non-persistent + mode, thanks to Julien Cristau <jcristau@debian.org>. + * Updating eject prevention for USB devices in initscripts for linux 2.6.29 + and newer. + + -- Daniel Baumann <daniel@debian.org> Thu, 14 May 2009 10:00:00 +0200 + +live-initramfs (1.157.1-1) unstable; urgency=medium + + [ Daniel Baumann ] + * Only snapshotting in initscript when we actually run with persistence. + + [ Rene Mayrhofer ] + * Checking if /var/log is writable before trying to copy live.log to the newly + mounted root filesystem (Closes: #516914). + + [ Daniel Baumann ] + * Improving check in 21xdriver when we don't do anything. + * Adding hack to remove live specific filesystems from umounfs initscript + (Closes: #506410, #515718). + * Adding comsetic line wrapping for output of local-gen messages during boot. + * Merging casper 1.157. + * Only calling install-keymap if it's actually installed, which is always but + in minimal images the case though (Closes: #517153). + * Adding silent boot parameter. + * Respecting media timeout even when specificing media device manually. + * Also allowing to use the removable keyword for specifying a live media. + * Correcting accidental syntax error in one of the previous commits in + 19keyboard bottom script. + * Adding removable-usb keyword to further restrict live media selection. + * Correcting check for usb when using removable-usb keyword. + * Correcting typo in locale bottom script. + + -- Daniel Baumann <daniel@debian.org> Sat, 21 Mar 2009 14:00:00 +0100 + +live-initramfs (1.156.1-1) unstable; urgency=high + + [ Daniel Baumann ] + * Revert using debhelper 7 command in rules. + * Updating copyright file. + * Prefixing debhelper files with package name. + * Updating bug script. + * Removing bashism in initscript. + * Usage of dialog in initscript is not actually a todo. + * Correcting medium eject message in initscript. + * Making medium removal message working again with usplash. + * Rewrapping init script. + * Reordering rules file. + * Merging casper 1.155. + * Adding ext4 support. + * Merging casper 1.156. + * Correct eject login in initscript. + * Updating parameters.txt. + + [ Ronny Standtke ] + * Do not eject USB flash drives (Closes: #457070). + + -- Daniel Baumann <daniel@debian.org> Sun, 8 Feb 2009 15:00:00 +0100 + +live-initramfs (1.154.8-1) unstable; urgency=high + + [ Kai Hendry ] + * Adding basic xrandr support for lenny to enforce a particular + resolution through bootparameter. + + -- Daniel Baumann <daniel@debian.org> Fri, 30 Jan 2009 00:00:00 +0100 + +live-initramfs (1.154.7-1) unstable; urgency=medium + + * Adding note about URL limitations in live-initramfs manpage when + using fetch parameter. + * Removing wc from hook again, that's an ubuntu only problem they have + to care about. + + -- Daniel Baumann <daniel@debian.org> Tue, 27 Jan 2009 18:00:00 +0100 + +live-initramfs (1.154.6-1) unstable; urgency=medium + + * Replacing casper with live in live-new-uuid. + * Including wc in initramfs (Closes: #512413). + * Added missing variable quoting that lead to broken root persistence, thanks + to Thierry Walrant <debian.tgc@walrant.net> (Closes: #512656). + * Adding patch from Thierry Walrant <debian.tgc@walrant.net> to allow setting + a path for the persistence files through persistent-path boot parameter + (Closes: #512661). + * Adding persistent-path to parameter list and manpage. + * Actually building/cleaning manpages through targets in Makefile. + + -- Daniel Baumann <daniel@debian.org> Mon, 26 Jan 2009 02:00:00 +0100 + +live-initramfs (1.154.5-1) unstable; urgency=low + + * Also checking for wicd in 23networking, thanks to Ben Armstrong + <synrg@debian.org>. + * Don't redirect output of fstype detection to standard out, thanks to Ronny + Standtke <Ronny.Standtke@gmx.net>. + * Silencing grep call on /etc/passwd. + * Silencing xorg reconfiguration, thanks to Ronny Standtke + <Ronny.Standtke@gmx.net>. + + -- Daniel Baumann <daniel@debian.org> Mon, 12 Jan 2009 13:00:00 -0500 + +live-initramfs (1.154.4-1) unstable; urgency=low + + [ Rene Mayrhofer ] + * Support further checks on loopback image and support skipping union + mounts (Closes: #509446). + + -- Daniel Baumann <daniel@debian.org> Fri, 26 Dec 2008 09:00:00 +0100 + +live-initramfs (1.154.3-1) unstable; urgency=medium + + * Sourcing live.vars in 21xdriver and 21xvidemode in order to be able + to set variables in previous bottom scripts. + + -- Daniel Baumann <daniel@debian.org> Sat, 20 Dec 2008 15:00:00 +0100 + +live-initramfs (1.154.2-1) unstable; urgency=medium + + [ Daniel Baumann ] + * Updating authors file. + + [ Marco Amadori ] + * Reworked integrity-check (Closes: #507477). + * Cleaned the boot log a bit. + + -- Daniel Baumann <daniel@debian.org> Thu, 11 Dec 2008 06:00:00 +0100 + +live-initramfs (1.154.1-1) unstable; urgency=low + + * Merging casper 1.140-1.154. + * Add a warning message when no image can be found. + * Adding a panic message when we netboot and have no supported network + device (Closes: #496684). + * Turning 'no supported filesystem images found' into a panic message, + rather than a warning. + * Also adding ralink to network device check. + * Removing spurious 'livefs_root' in copy_live_to();. + + -- Daniel Baumann <daniel@debian.org> Tue, 25 Nov 2008 12:00:00 +0100 + +live-initramfs (1.139.1-4) unstable; urgency=medium + + [ Chris Lamb ] + * Remove (accidental?) debian/changelog entry. + * Use "grep -qs" over "grep -q" for compatibility (see grep(1)) + * Use "test -s" instead of testing file availability and size. + * Be consistent in using 0/1 for True/False values instead of English + representations. + * Reflow some grammar in comments and in live-initramfs(7). + * Reflow long 'tr'-based pipelines for readability. + * Don't "cat |" to grep. + + [ Daniel Baumann ] + * Replacing obsolete dh_clean -k with dh_prep. + + [ Marco Amadori ] + * Changed HOSTNAME and /etc/hosts handling. + * Conditional creation of /etc/fstab. + * live-snapshot: fixed include-list handling. + * Reordered persistence lookups and boundaries (Closes: #500672). + * Search for partition labels only (Closes: #486469). + * Implemented a snapshot exclude list. + * Implemented a persistence exclude list. + * Manpage clarifications on "nofiles". + * Do not pollute the logs when looking for swap partitions. + * Removed all "cat | grep", with grep, awk and sed. + + -- Daniel Baumann <daniel@debian.org> Tue, 11 Nov 2008 13:00:00 +0100 + +live-initramfs (1.139.1-3) unstable; urgency=medium + + [ Chris Lamb ] + * Remove local overiddes of log_*_msg - #494257 is now fixed in testing. + + [ Daniel Baumann ] + * Removing currently unused Upstream-Depends field in control. + * Updating vcs fields in control file. + * Sourcing live.vars in 15autologin directly, rather than to inherit + from live-functions. + + [ Marco Amadori ] + * Removed some useless spaces. + * Fix default user handling. + * Added a pretty vital mount debug string. + * Create /etc/mtab on the initramfs ASAP. + * Removed mount -n option, since mtab is there. + * Re-enable "break=live-premount" debug. + * Skipped some runtime duplicated execution. + * Add real cpio to initramfs for snapshot's uses. + * Fixed try_snap() umounting on error. + * Override maybe_break from initramfs-tools. + * Forces use of initramfs cpio over busybox's one. + * Fixed a wrong trial to copy an unexistant snapshot. + * Check for files and umount only if you can mount it first. + * Included more debug and comments on persistence code. + * Set -u in live-snapshot only in debug mode. + + [ Michael Prokop ] + * Ignore errors from fstype. + + -- Daniel Baumann <daniel@debian.org> Fri, 19 Sep 2008 14:00:00 +0200 + +live-initramfs (1.139.1-2) unstable; urgency=medium + + [ Daniel Baumann ] + * If the filesystem type of the rootfs cannot be automatically detected, we + try to assume it from the extension of the imagefile we have found. Thanks + to Jordi Pujol <jordi_pujol@telefonica.net> (Closes: #460456). + * Setting project email address to the new debian-live@lists.debian.org. + * Disabling default usage of local swap partitions. Can be enabled with the + 'swapon' boot parameter. Thanks to Joseph Rawson <umeboshi3@gmail.com> for + bringing it up. + + [ Michal Suchanek ] + * Enabling the "remove CD" prompt in splashy. + + -- Daniel Baumann <daniel@debian.org> Mon, 1 Sep 2008 00:00:00 +0200 + +live-initramfs (1.139.1-1) unstable; urgency=medium + + [ Ben Voui ] + * Adding support for Virtio vd[a-z] drives. + + [ Chris Lamb ] + * Move loop-aes-tools to Suggests; live-helper should install them if + required. + * Remove unnecessary indentation level. + * Modify hiding of harmless X.org reconfiguring messages. + * Revert to using uid 1000 as PAM bug seems to have disappeared + (Closes: #433076) + * Hide error from attempting to "mount --move" + * Rework ugly `echo "debug:..` message to use log_{begin,end}_msg. + * Don't configure X.org if it's not installed. + * Fix check for X.org. + * Add an /etc/fstab to the initramfs to silence harmless "empty fstab" + warnings. + * Silence another "script-not-executable" message for a sourced library. + * Add missing pipe. Thanks to Andreas Bombe. + * Shamefully adding myself to CREDITS + * Tidy "Disabling update-initramfs" message. + * Re-order some commands so we don't call log_begin_msg without calling + log_end_msg. + * Don't configure X when /usr/bin/X does not exist. + * Silence 'script-not-executable' lintian warning - live-functions script is + always sourced. + * Fix spacing in swirl. + * Override log_*_msg to print nicer status text (until #494257 is merged). + * Hide "overwriting possibly-customised configuration file" in X.org setup + output. + * Hide "Shadow passwords are now on" status message on bootup. + * Remove a number of "${quiet}" checks - they are repeated in the log_*_msg + functions. + * Rework locale handling + * Print friendly error message on live-initramfs panic. + * Fix path issue with live-preseed causing noisy errors when booting. + * Silence a number of annoying and distracting bootup messages. + * Add missing "log_end_msg" to live-bottom/21xdriver. + * Set different log messages for live-bottom/21{xdriver,xvidemode}. + * Remove trailing "..." from calls to log_begin_msg - they get added anyway. + * Move some arch-indep helper utilities to Build-Depends-Indep. + * Set default cow_mountopt where the other defaults are used. + * Don't use /sbin/losetup to test for '-r' option when the scripts just use + "lostup" + + [ Daniel Baumann ] + * Updating authors file. + * Merging casper 1.139. + * Not going over the top with exclamation marks in the panic message. + * Updating credits file. + * Slightely adjusting to the more widespread used ascii swirl. + * Merging casper 1.138. + * Merging casper 1.137. + + [ Marco Amadori ] + * Added "-n" option to all mount commands, thanks to Peter Holik + <peter@holik.at> for pointing this out. + * Be sure that the discovered filesystem is not null. + * The list of supported filesytems goes dynamic. + * Added ntfs filesystem to the initramfs. + + [ Michael Prokop ] + * Move sourcing of live-functions in 38disable_restricted_manager to correct + place. + + [ Steven Shiau ] + * Adding support for using tftp in fetch= parameter. + * Another fix about using udevsettle or "udevadm settle". + + -- Daniel Baumann <daniel@debian.org> Sun, 24 Aug 2008 00:00:00 +0200 + +live-initramfs (1.136.3-1) unstable; urgency=medium + + [ Michael Prokop ] + * Make sure mounting /cow-tmpfs provides mount options. + + -- Daniel Baumann <daniel@debian.org> Fri, 18 Jul 2008 00:00:00 +0200 + +live-initramfs (1.136.2-1) unstable; urgency=medium + + * Replacing previous imperfect changes for udevadm with check for + udevadm and using old commands when beeing on etch. Also handling + udevtrigger with udevadm if available. + * Correcting httpfs2 inclusion in hook. + + -- Daniel Baumann <daniel@debian.org> Wed, 16 Jul 2008 00:00:00 +0200 + +live-initramfs (1.136.1-1) unstable; urgency=medium + + [ Chris Lamb ] + * Fix call to log_warning_msg. Thanks to Bradley Smith + <brad@brad-smith.co.uk>. + * Expand glob for kernels in post{inst,rm} to include "vmlinux"-prefixed + kernels on powerpc. + * Check losetup capabilities before specifying to mount as read-only. + * Modprobe 'esp' SCSI driver for the benefit of sparc. + * Quieten call to modprobe ide-generic. + * Move local-top/live to live-premount/modules so it gets called before + find_livefs. + * Sync bug script "dpkg -l" calls with debian/control + + [ Daniel Baumann ] + * Defaulting now to aufs if no union= parameter is given. + * Merging casper version 1.136. + * Merging casper version 1.135. + * Merging casper version 1.134. + * Merging casper version 1.133. + * Converting udev depends into a versioned depends in order to reflect udevadm + introduction. + * Updating live-snapshot to GPL-3+. + * Updating to standards 3.8.0. + * Renaming forgotton uuid file to live-uuid. + + [ Marco Amadori ] + * udevtrigger replacement. + * live-snapshot: fixed the remount helper. + * live-snapshot: now supports a static keep file list. + * Try to bind /cow to /live/cow if unable to move. + * live-snapshot: cleaned some wordings. + * live-snapshot: included vital informations on exit. + * live-snapshot: new "--refresh" option. + * live-snapshot: cleaned and sorted used command line defaults. + * live-snapshot: nicer default auto unmount logic. + * live-snapshot: honour "-o|--output FILE". + * live-snapshot: removed a useless mkdir. + * live-snapshot: removed an unused and useless function. + * live-snapshot: fixes snapshotting from resync string. + + [ Michal Suchanek ] + * Add support for httpfs= and ftpfs= parameters. + + -- Daniel Baumann <daniel@debian.org> Mon, 14 Jul 2008 00:00:00 +0200 + +live-initramfs (1.132.1-1) unstable; urgency=medium + + [ Chris Lamb ] + * Don't escape asterisks in languagelist update code + + [ Daniel Baumann ] + * Updating copyright header in live-snapshot. + * Removing useless whitespaces and empty lines. + * Correcting grammatical errors in live-snapshot description. + * Removing live-snapshot version as this component is always released + within live-initramfs itself. + * Adding Michal Suchanek <hramrach@centrum.cz> to credits file. + * Merging casper 1.132. + * Merging casper 1.131. + * Ignoring floppy devices for live filesystem as well as live + persistency. + * Adding patch from Michal Suchanek <hramrach@centrum.cz> to tail + live.log and show its messages during boot (Closes: #440238). + * Updating vcs fields in control file. + * Handling conflicting klibc includes with initramfs-hooks of other + packages (Closes: 475783). + + [ Marco Amadori ] + * Fixes "live-snapshot on reboot could not find a writable '/tmp' or + '/mnt'" bug. + * Calling live-snapshot now produces an output file. + + [ Michal Suchanek ] + * Workaround loop-aes-utils losetup incompatibility + * Fix toram (change mount --move to mount -o move) + + -- Daniel Baumann <daniel@debian.org> Mon, 02 Jun 2008 00:00:00 +0200 + +live-initramfs (1.130.1-3) unstable; urgency=high + + * Handle non-existing klibc includes in live hook (Closes: #475783). + * Adding loop-aes-utils to recommends. + + -- Daniel Baumann <daniel@debian.org> Sat, 26 Apr 2008 16:00:00 +0200 + +live-initramfs (1.130.1-2) unstable; urgency=medium + + [ Chris Lamb ] + * Remove bogus dependency on Ubuntu "localechooser-data" package + + -- Daniel Baumann <daniel@debian.org> Thu, 17 Apr 2008 06:00:00 +0200 + +live-initramfs (1.130.1-1) unstable; urgency=medium + + [ Chris Lamb ] + * Use triggers when calling update-initramfs in postinst and postrm + + [ Daniel Baumann ] + * Sorting some lines in live hook. + * Merging casper 1.130. + * Merging casper 1.129. + * Adjusting code formating in maintainer scripts. + * Restricting counting of installed kernels based on /boot/vmlinuz-* + instead of /boot/vmlinuz*. + + -- Daniel Baumann <daniel@debian.org> Mon, 14 Apr 2008 00:00:00 +0200 + +live-initramfs (1.128.1-1) unstable; urgency=medium + + [ Marco Amadori ] + * Fixed a misleading debug message. + * Added /cow mounting debug messages. + * Fixed /cow mounting. + * Klibc: added some libraries to the intramfs. + + [ Daniel Baumann ] + * Merging casper 1.128. + + -- Daniel Baumann <daniel@debian.org> Mon, 7 Apr 2008 00:00:00 +0200 + +live-initramfs (1.127.1-1) unstable; urgency=medium + + [ Daniel Baumann ] + * Merging casper 1.127. + * Merging casper 1.126. + * Removing too early recommends to live-initscripts in control to make + some people happy (Closes: #431000). + + [ Chris Lamb ] + * hooks/live, scripts/live: Add USB modules, workaround udevtrigger + (?) bug + * scripts/live-helpers: Don't search ram block devices + * scripts/live-helpers: Search / use case + * scripts/live-helpers: Fixes for set -e + * bin/live-snapshot: Vastly rework script + * bin/live-snapshot: Fix argument handling (Closes: #461595) + * scripts/live: Make 'nopersistent' parameter actually disable + persistence + + -- Daniel Baumann <daniel@debian.org> Mon, 31 Mar 2008 00:00:00 +0200 + +live-initramfs (1.125.1-1) unstable; urgency=medium + + [ Daniel Baumann ] + * Merging casper 1.125. + + [ Chris Lamb ] + * scripts/live-helpers: Cosmetic changes to loop-aes passphrase prompt + * Rename 18hostname -> 06hostname + + -- Daniel Baumann <daniel@debian.org> Mon, 24 Mar 2008 00:00:00 +0100 + +live-initramfs (1.124.1-1) unstable; urgency=medium + + [ Daniel Baumann ] + * Adjusting live-snapshot to live-initramfs. + * Merging casper 1.124. + * Adjusting 44pk_allow to live-initramfs. + * Merging casper 1.123. + * Merging casper 1.122. + * Merging casper 1.121. + * Merging casper 1.120. + + [ Chris Lamb ] + * 99hook: Download hook script from inside target filesystem + + -- Daniel Baumann <daniel@debian.org> Mon, 17 Mar 2008 00:00:00 +0100 + +live-initramfs (1.119.1-1) unstable; urgency=medium + + * Creating resolv.conf when netbooting not just when there's no + resolv.conf, but also when it is empty. + * Making hooks executable after fetching them. + * Removing disabling of kwallet. + * Merging casper 1.119. + + -- Daniel Baumann <daniel@debian.org> Mon, 10 Mar 2008 00:00:00 +0100 + +live-initramfs (1.118.2-1) unstable; urgency=medium + + [ Andrey Asadchev ] + * Explicitly set Xorg video driver. + * Patch to use cryptsetup volumes for persistent storage. + + [ Daniel Baumann ] + * New upstream release. + * Fixing wrong email address in changelog (was bug in git-dch config). + * Bumping package to policy 3.7.3. + * Rewriting copyright in machine-interpretable format. + * Adding hook parameter to execute custom scripts. + * Adding plainroot. + + [ Marco Amadori ] + * Now it includes lzma kernel module dependencies. + + -- Daniel Baumann <daniel@debian.org> Mon, 3 Mar 2008 00:00:00 +0100 + +live-initramfs (1.118.1-1) unstable; urgency=medium + + [ Daniel Baumann ] + * New upstream release. + * Adding direct depends to udev, thanks to Anton Lundin + <glance@acc.umu.se> (Closes: #452448). + * Merging casper 1.111. + * Bumping version to 1.110.1-1. + * Merging casper 1.112. + * Merging casper 1.113. + * Adjusting to live-initramfs. + * Bumping version to 1.113.1-1. + * Merging casper 1.114. + * Merging casper 1.115. + * Merging casper 1.116. + * Merging casper 1.117. + * Merging casper 1.118. + * Bumping version to 1.118.1-1. + + [ Otavio Salvador ] + * debian: add mtd-tools as suggestion since it's required for jffs2 + support + * hooks: include jffs2 kernel module on initramfs image + * live-snapshot: add support to use jffs2 images + * live: add support for jffs2 images and snapshots + * live-helpers: add jffs2 as a valid image + * live-snapshot.en.1: add ext3 and jffs2 images as valid options + + -- Daniel Baumann <daniel@debian.org> Tue, 26 Feb 2008 13:35:00 +0100 + +live-initramfs (1.110.7-1) unstable; urgency=medium + + * New upstream release. + * Fixing fstab handling. + * Fixing regression from mounting the ow device on a nfs volume, + thanks to An-Cheng Huang <ancheng@vyatta.com>. + + -- Daniel Baumann <daniel@debian.org> Mon, 19 Nov 2007 00:00:00 +0100 + +live-initramfs (1.110.6-1) unstable; urgency=medium + + * New upstream release. + * Preparing live-initramfs 1.110.6-1. + * Adding custom reportbug script. + * Fixed a few bashisms, thanks to Trent W. Buck <trentbuck@gmail.com>. + * Adding checkbashsms call to test target of the Makefile as suggested + by Trent W. Buck <trentbuck@gmail.com>. + + -- Daniel Baumann <daniel@debian.org> Mon, 12 Nov 2007 00:00:00 +0100 + +live-initramfs (1.110.5-1) unstable; urgency=medium + + * New upstream release. + * Preparing live-initramfs 1.110.5-1. + * Using kdm initscript autologin overrides, thanks to Kel Modderman + <kel@otaku42.de>. + * Setting the kdm language, thanks to Jordi Pujol + <jordi_pujol@telefonica.net>. + * Adding files to the live filesystem according to the MAC number, + thanks to Jordi Pujol <jordi_pujol@telefonica.net>. + * Fixing some coding style issues. + + -- Daniel Baumann <daniel@debian.org> Mon, 5 Nov 2007 00:00:00 +0100 + +live-initramfs (1.110.4-1) unstable; urgency=medium + + [ Daniel Baumann ] + * New upstream release. + * Preparing live-initramfs 1.110.3-1. + * Correcting homepage field. + * Correcting vcs fields. + + [ Jesse Hathaway ] + * add support for mounting the cow device on an nfs volume + + -- Daniel Baumann <daniel@debian.org> Mon, 29 Oct 2007 00:00:00 +0100 + +live-initramfs (1.110.3-1) unstable; urgency=medium + + [ Daniel Baumann ] + * New upstream release. + * Preparing live-initramfs 1.110.3-1. + * Removing ubuntu support. + + [ Alex Owen ] + * Fix typo to get serial console to work + + [ Jesse Hathaway ] + * add support for exposedroot option for live-helper + + -- Daniel Baumann <daniel@debian.org> Mon, 22 Oct 2007 00:00:00 +0200 + +live-initramfs (1.110.2-1) unstable; urgency=medium + + * New upstream release. + * Preparing live-initramfs 1.110.2-1. + * Fixing typing error. + * Removing nodiratime as it is already included in noatime, thanks to Kel + Modderman <kel@otaku42.de>. + + -- Daniel Baumann <daniel@debian.org> Mon, 15 Oct 2007 00:00:00 +0200 + +live-initramfs (1.110.1-1) unstable; urgency=medium + + * New upstream release. + * Preparing live-initramfs 1.107.2-1. + * Also using nodiratime, not just noatime. + * Merging casper 1.108. + * Adjusting to live-initramfs. + * Merging casper 1.109. + * Adjusting to live-initramfs. + * Merging casper 1.110. + * Adjusting to live-initramfs. + * Bumping version to 1.110.1-1. + + -- Daniel Baumann <daniel@debian.org> Mon, 8 Oct 2007 00:00:00 +0200 + +live-initramfs (1.107.1-1) unstable; urgency=medium + + * New upstream release. + * Preparing live-initramfs 1.102.4-2. + * Replacing backticks with POSIX expression. + * Consistently using curly brackets for variables. + * Fixing bashism. + * Merging casper 1.105. + * Adjusting to live-initramfs. + * Bumping version to 1.105.1-1. + * Applied patch from Jesse W. Hathaway <jesse@mbuki-mvuki.org> to move + cow mount rather than binding it on /live/cow. This prevents the + /cow mount showing up in /proc/mounts. + * Merging casper 1.106. + * Adjusting to live-initramfs. + * Bumping version to 1.106.1-1. + * Fixing wrong homepage field. + * Fixing typing error. + * Merging casper 1.107. + * Bumping version to 1.107.1-1. + + -- Daniel Baumann <daniel@debian.org> Mon, 1 Oct 2007 00:00:00 +0200 + +live-initramfs (1.104.1-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 24 Sep 2007 00:00:00 +0200 + +live-initramfs (1.102.1-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 17 Sep 2007 00:00:00 +0200 + +live-initramfs (1.99.2-1) unstable; urgency=medium + + * New upstream release: + - Contains patch from Jim Paris <jim@jtan.com> to fix wrong ipconfig usage + (Closes: #440235). + + -- Daniel Baumann <daniel@debian.org> Mon, 10 Sep 2007 00:00:00 +0200 + +live-initramfs (1.99.1-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 3 Sep 2007 00:00:00 +0200 + +live-initramfs (1.96.2-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 27 Aug 2007 00:00:00 +0200 + +live-initramfs (1.96.1-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 20 Aug 2007 00:00:00 +0200 + +live-initramfs (1.95.3-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 13 Aug 2007 00:00:00 +0200 + +live-initramfs (1.95.2-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 6 Aug 2007 00:00:00 +0200 + +live-initramfs (1.95.1-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 30 Jul 2007 00:00:00 +0200 + +live-initramfs (1.91.6-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 23 Jul 2007 00:00:00 +0200 + +live-initramfs (1.91.5-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 16 Jul 2007 00:00:00 +0200 + +live-initramfs (1.91.4-1) unstable; urgency=medium + + * New upstream release: + - Dropping transitional package, not needed anymore. + + -- Daniel Baumann <daniel@debian.org> Mon, 9 Jul 2007 00:00:00 +0200 + +live-initramfs (1.91.3-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 2 Jul 2007 00:00:00 +0200 + +live-initramfs (1.91.2-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 25 Jun 2007 00:00:00 +0200 + +live-initramfs (1.91.1-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 18 Jun 2007 00:00:00 +0200 + +live-initramfs (1.90.1-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 11 Jun 2007 00:00:00 +0200 + +live-initramfs (1.87.6-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 4 Jun 2007 00:00:00 +0200 + +live-initramfs (1.87.5-1) unstable; urgency=medium + + * New upstream release, replacing casper. + + -- Daniel Baumann <daniel@debian.org> Mon, 28 May 2007 00:00:00 +0200 + +live-initramfs (1.87.4-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 21 May 2007 00:00:00 +0200 + +live-initramfs (1.87.3-1) unstable; urgency=medium + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 14 May 2007 00:00:00 +0200 + +live-initramfs (1.87.2-1) unstable; urgency=low + + * New upstream release. + + -- Daniel Baumann <daniel@debian.org> Mon, 7 May 2007 00:00:00 +0200 + +live-initramfs (1.87.1-1) unstable; urgency=low + + * Initial release, forking casper. + + -- Daniel Baumann <daniel@debian.org> Mon, 30 Apr 2007 00:00:00 +0200 diff --git a/tools/XBMCLive/live-initramfs/debian/compat b/tools/XBMCLive/live-initramfs/debian/compat new file mode 100644 index 0000000000..7ed6ff82de --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/compat @@ -0,0 +1 @@ +5 diff --git a/tools/XBMCLive/live-initramfs/debian/control b/tools/XBMCLive/live-initramfs/debian/control new file mode 100644 index 0000000000..9774b43131 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/control @@ -0,0 +1,31 @@ +Source: live-initramfs +Section: misc +Priority: optional +Maintainer: Debian Live <debian-live@lists.debian.org> +Uploaders: Daniel Baumann <daniel@debian.org> +Build-Depends: debhelper (>= 5) +Build-Depends-Indep: asciidoc, docbook-xsl, xsltproc +Standards-Version: 3.8.0 +Homepage: http://debian-live.alioth.debian.org/ +Vcs-Browser: http://git.debian.net/?p=debian-live/live-initramfs.git +Vcs-Git: git://git.debian.net/git/debian-live/live-initramfs.git + +Package: live-initramfs +Architecture: all +Depends: ${misc:Depends}, busybox, file, initramfs-tools, sudo, udev, user-setup +Recommends: cryptsetup, eject, uuid-runtime, wget +Suggests: loop-aes-utils, curlftpfs, genext2fs (>= 1.4.1), httpfs2, squashfs-tools, mtd-tools +Description: Debian Live initramfs hook + live-initramfs is a hook for the initramfs-tools, used to generate a initramfs + capable to boot live systems, such as those created by live-helper. This + includes the Debian Live isos, netboot tarballs, and usb stick images. + . + At boot time it will look for a (read-only) media containing a "/live" + directory where a root filesystems (often a compressed filesystem image like + squashfs) is stored. If found, it will create a writable environment, using + aufs or unionfs, for Debian like systems to boot from. + . + You probably do not want to install this package onto a non-live system, + although it will do no harm. + . + live-initramfs is a fork of casper <http://packages.ubuntu.com/casper/>. diff --git a/tools/XBMCLive/live-initramfs/debian/copyright b/tools/XBMCLive/live-initramfs/debian/copyright new file mode 100644 index 0000000000..e703900a54 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/copyright @@ -0,0 +1,29 @@ +Author: Daniel Baumann <daniel@debian.org> +Download: http://debian-live.alioth.debian.org/ + +live-initramfs is a fork of casper <http://packages.ubuntu.com/casper/>. +casper was originally written by Tollef Fog Heen <tfheen@canonical.com> +and Matt Zimmerman <mdz@canonical.com>. + +Files: * +Copyright: + (C) 2007-2009 Daniel Baumann <daniel@debian.org> + (C) 2005-2008 Canonical Ltd. <http://www.cannonical.com/> + (C) 2006-2007 Marco Amadori <marco.amadori@gmail.com> + (C) 2008 Dell Inc. <http://www.dell.com/> +License: GPL-3+ + 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 3 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, see <http://www.gnu.org/licenses/>. + . + On Debian systems, the complete text of the GNU General Public License + can be found in /usr/share/common-licenses/GPL-3 file. diff --git a/tools/XBMCLive/live-initramfs/debian/files b/tools/XBMCLive/live-initramfs/debian/files new file mode 100644 index 0000000000..10df5291d3 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/files @@ -0,0 +1 @@ +live-initramfs_1.157.3-1_all.deb misc optional diff --git a/tools/XBMCLive/live-initramfs/debian/live-initramfs.debhelper.log b/tools/XBMCLive/live-initramfs/debian/live-initramfs.debhelper.log new file mode 100644 index 0000000000..9eca228626 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/live-initramfs.debhelper.log @@ -0,0 +1,11 @@ +dh_installdirs +dh_installchangelogs +dh_installdocs +dh_install +dh_installinit +dh_compress +dh_fixperms +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb diff --git a/tools/XBMCLive/live-initramfs/debian/live-initramfs.init b/tools/XBMCLive/live-initramfs/debian/live-initramfs.init new file mode 100644 index 0000000000..07f707c581 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/live-initramfs.init @@ -0,0 +1,201 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: live-initramfs +# Required-Start: $syslog +# Required-Stop: $syslog +# Should-Start: $local_fs +# Should-Stop: $local_fs +# Default-Start: 1 2 3 4 5 +# Default-Stop: 0 6 +# Short-Description: live-initramfs init script +# Description: Resyncs snapshots, evantually caches files in order to +# let remove the media. +### END INIT INFO + +# Authors: Tollef Fog Heen <tfheen@canonical.com> +# Marco Amadori <marco.amadori@gmail.com> + +PATH=/usr/sbin:/usr/bin:/sbin:/bin +NAME=live-initramfs +SCRIPTNAME=/etc/init.d/${NAME} +DO_SNAPSHOT=/sbin/live-snapshot + +# Exit if system was not booted by live-initramfs +grep -qs boot=live /proc/cmdline || exit 0 + +# Exit if the system was booted from an ISO image rather than a physical CD +grep -qs find_iso= /proc/cmdline && exit 0 + +# Read configuration variable file if it is present +[ -r /etc/live.conf ] && . /etc/live.conf + +# Load the VERBOSE setting and other rcS variables +[ -f /etc/default/rcS ] && . /etc/default/rcS + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# Try to cache everything we're likely to need after ejecting. This +# is fragile and simple-minded, but our options are limited. +cache_path() +{ + path="${1}" + + if [ -d "${path}" ] + then + find "${path}" -type f | xargs cat > /dev/null 2>&1 + elif [ -f "${path}" ] + then + if [ -x "${path}" ] + then + if file "${path}" | grep -q 'dynamically linked' + then + for lib in $(ldd "${path}" | awk '{ print $3 }') + do + cache_path "${lib}" + done + fi + fi + + cat "${path}" >/dev/null 2>&1 + fi +} + +get_boot_device() +{ + # search in /proc/mounts for the device that is mounted at /live/image + while read DEVICE MOUNT REST + do + if [ "${MOUNT}" = "/live/image" ] + then + echo "${DEVICE}" + exit 0 + fi + done < /proc/mounts +} + +device_is_USB_flash_drive() +{ + # remove leading "/dev/" and all trailing numbers from input + DEVICE=$(expr substr ${1} 6 3) + + # check that device starts with "sd" + [ "$(expr substr ${DEVICE} 1 2)" != "sd" ] && return 1 + + # check that the device is an USB device + if readlink /sys/block/${DEVICE} | grep -q usb || + readlink /sys/block/${DEVICE}/device | grep -q usb # linux < 2.6.29 + then + return 0 + fi + + return 1 +} + +do_stop () +{ + if ! grep -qs nopersistent /proc/cmdline && grep -qs persistent /proc/cmdline + then + if [ ! -z "${ROOTSNAP}" ] + then + ${DO_SNAPSHOT} --resync-string="${ROOTSNAP}" + fi + + if [ ! -z "${HOMESNAP}" ] + then + ${DO_SNAPSHOT} --resync-string="${HOMESNAP}" + fi + fi + + # check for netboot + if [ ! -z "${NETBOOT}" ] || grep -qs netboot /proc/cmdline || grep -qsi root=/dev/nfs /proc/cmdline || grep -qsi root=/dev/cifs /proc/cmdline + then + return 0 + fi + + prompt=1 + if grep -qs noprompt /proc/cmdline + then + prompt= + fi + + for path in $(which halt) $(which reboot) /etc/rc?.d /etc/default $(which stty) + do + cache_path "${path}" + done + + for x in $(cat /proc/cmdline) + do + case ${x} in + quickreboot) + QUICKREBOOT="Yes" + ;; + esac + done + + if [ -z ${QUICKREBOOT} ] + then + # TODO: i18n + BOOT_DEVICE="$(get_boot_device)" + + if device_is_USB_flash_drive ${BOOT_DEVICE} + then + # do NOT eject USB flash drives! + # otherwise rebooting with most USB flash drives + # failes because they actually remember the + # "ejected" state even after reboot + MESSAGE="Please remove the USB flash drive" + else + # ejecting is a very good idea here + MESSAGE="Please remove the disc, close the the tray (if any)" + + if [ -x /usr/bin/eject ] + then + eject -p -m /live/image >/dev/null 2>&1 + fi + + [ "$prompt" ] || return 0 + fi + + stty sane < /dev/console + + printf "\n\n${MESSAGE} and press ENTER to continue:" > /dev/console + + if [ -x /sbin/usplash_write ] + then + /sbin/usplash_write "TIMEOUT 86400" + /sbin/usplash_write "TEXT-URGENT ${MESSAGE}" + /sbin/usplash_write "TEXT-URGENT and press ENTER to continue" + fi + + read x < /dev/console + fi +} + +case "${1}" in + start|restart|reload|force-reload|status) + [ "${VERBOSE}" != no ] && log_end_msg 0 + ;; + + stop) + log_begin_msg "${NAME} is resyncing snapshots and caching reboot files..." + do_stop + + case "${?}" in + 0|1) + [ "${VERBOSE}" != no ] && log_end_msg 0 + ;; + + 2) + [ "${VERBOSE}" != no ] && log_end_msg 1 + ;; + esac + ;; + + *) + log_success_msg "Usage: ${SCRIPTNAME} {start|stop|restart|force-reload}" >&2 + exit 3 + ;; +esac diff --git a/tools/XBMCLive/live-initramfs/debian/live-initramfs.postinst b/tools/XBMCLive/live-initramfs/debian/live-initramfs.postinst new file mode 100644 index 0000000000..b94b3bdfb3 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/live-initramfs.postinst @@ -0,0 +1,25 @@ +#!/bin/sh + +case "$(ls -l /boot/vmlinu* | wc -l)" in + 1) + # We only have one kernel installed, so we can use "-u" + # which will use dpkg-trigger inside update-initramfs + INITRAMFS_ARGS="-u" + ;; + + *) + INITRAMFS_ARGS="-u -k all" + ;; +esac + +if [ -x /usr/sbin/update-initramfs ] && [ "${1}" != "triggered" ] && \ + dpkg --compare-versions "${DPKG_RUNNING_VERSION}" ge "1.14.18" +then + # this activates the trigger, if triggers are working + update-initramfs ${INITRAMFS_ARGS} +else + # force it to actually happen + DPKG_MAINTSCRIPT_PACKAGE="" update-initramfs ${INITRAMFS_ARGS} +fi + +#DEBHELPER# diff --git a/tools/XBMCLive/live-initramfs/debian/live-initramfs.postinst.debhelper b/tools/XBMCLive/live-initramfs/debian/live-initramfs.postinst.debhelper new file mode 100644 index 0000000000..2aa52a36e9 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/live-initramfs.postinst.debhelper @@ -0,0 +1,5 @@ +# Automatically added by dh_installinit +if [ -x "/etc/init.d/live-initramfs" ]; then + update-rc.d live-initramfs start 89 0 6 . >/dev/null || exit $? +fi +# End automatically added section diff --git a/tools/XBMCLive/live-initramfs/debian/live-initramfs.postrm b/tools/XBMCLive/live-initramfs/debian/live-initramfs.postrm new file mode 100644 index 0000000000..b94b3bdfb3 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/live-initramfs.postrm @@ -0,0 +1,25 @@ +#!/bin/sh + +case "$(ls -l /boot/vmlinu* | wc -l)" in + 1) + # We only have one kernel installed, so we can use "-u" + # which will use dpkg-trigger inside update-initramfs + INITRAMFS_ARGS="-u" + ;; + + *) + INITRAMFS_ARGS="-u -k all" + ;; +esac + +if [ -x /usr/sbin/update-initramfs ] && [ "${1}" != "triggered" ] && \ + dpkg --compare-versions "${DPKG_RUNNING_VERSION}" ge "1.14.18" +then + # this activates the trigger, if triggers are working + update-initramfs ${INITRAMFS_ARGS} +else + # force it to actually happen + DPKG_MAINTSCRIPT_PACKAGE="" update-initramfs ${INITRAMFS_ARGS} +fi + +#DEBHELPER# diff --git a/tools/XBMCLive/live-initramfs/debian/live-initramfs.postrm.debhelper b/tools/XBMCLive/live-initramfs/debian/live-initramfs.postrm.debhelper new file mode 100644 index 0000000000..73cc19b43e --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/live-initramfs.postrm.debhelper @@ -0,0 +1,5 @@ +# Automatically added by dh_installinit +if [ "$1" = "purge" ] ; then + update-rc.d live-initramfs remove >/dev/null || exit $? +fi +# End automatically added section diff --git a/tools/XBMCLive/live-initramfs/debian/live-initramfs.triggers b/tools/XBMCLive/live-initramfs/debian/live-initramfs.triggers new file mode 100644 index 0000000000..6c9f4543c2 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/live-initramfs.triggers @@ -0,0 +1 @@ +activate update-initramfs diff --git a/tools/XBMCLive/live-initramfs/debian/rules b/tools/XBMCLive/live-initramfs/debian/rules new file mode 100755 index 0000000000..e3c67f1182 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/debian/rules @@ -0,0 +1,55 @@ +#!/usr/bin/make -f + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + $(MAKE) -C manpages clean + + dh_clean + +build: build-stamp +build-stamp: + dh_testdir + + $(MAKE) -C manpages + + touch build-stamp + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Installing package + $(MAKE) install DESTDIR=$(CURDIR)/debian/live-initramfs + + # Removing double files + rm -f debian/live-initramfs/usr/share/doc/live-initramfs/COPYING + rm -f debian/live-initramfs/usr/share/doc/live-initramfs/ChangeLog + mv debian/live-initramfs/usr/share/doc/live-initramfs/ChangeLog.casper debian/live-initramfs/usr/share/doc/live-initramfs/changelog.casper + + # Installing bug control + install -D -m 0755 debian/bug/live-initramfs.script debian/live-initramfs/usr/share/bug/live-initramfs + +binary: binary-indep + +binary-arch: + +binary-indep: install + dh_testdir + dh_testroot + dh_installchangelogs docs/ChangeLog + dh_installdocs + dh_install + dh_installinit --no-restart-on-upgrade --no-start -- start 89 0 6 . + dh_compress + dh_fixperms + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +.PHONY: clean build install binary binary-arch binary-indep diff --git a/tools/XBMCLive/live-initramfs/docs/AUTHORS b/tools/XBMCLive/live-initramfs/docs/AUTHORS new file mode 100644 index 0000000000..79bc320707 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/docs/AUTHORS @@ -0,0 +1,16 @@ +Main Authors: + + * Daniel Baumann <daniel@debian.org> + +Main Contributors: + + * Chris Lamb <chris@chris-lamb.co.uk> + * Marco Amadori <marco.amadori@gmail.com> + +Original Authors: + + live-initramfs is a fork of casper <http://packages.ubuntu.com/casper/>. + casper was originally written by Tollef Fog Heen <tfheen@canonical.com> + and Matt Zimmerman <mdz@canonical.com>. + + See the casper changelog for casper contributors. diff --git a/tools/XBMCLive/live-initramfs/docs/CREDITS b/tools/XBMCLive/live-initramfs/docs/CREDITS new file mode 100644 index 0000000000..2a1ae506c0 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/docs/CREDITS @@ -0,0 +1,25 @@ +Patches (alphabetical order): + + * Alexandre Garcia <ascii_77@yahoo.fr> + * Alex Owen <r.a.owen@qmul.ac.uk> + * Arnaud Cornet <arnaud.cornet@gmail.com> + * Bas Wijnen <wijnen@debian.org> + * Ben Armstrong <synrg@debian.org> + * Ben Voui <intrigeri@boum.org> + * Chris Lamb <chris@chris-lamb.co.uk> + * Davide Natalini <davide.natalini@studio.unibo.it> + * Frederic Lehobey <Frederic.Lehobey@free.fr> + * Hadar Weiss <whadar@gmail.com> + * Jason D. Clinton <me@jasonclinton.com> + * Jonathan Hall <flimzy@flimzy.com> + * Kai Hendry <hendry@iki.fi> + * Malcom Gilles <live@ouabain.org> + * Marco Amadori <marco.amadori@gmail.com> + * Mathieu Geli <mathieu.geli@gmail.com> + * Michael Prokop <mika@grml.org> + * Michal Suchanek <hramrach@centrum.cz> + * Oliver Osburg <o.osburg@uni-jena.de> + * Otavio Salvador <otavio@debian.org> + * Sebastian Raveau <sebastien.raveau@epita.fr> + * Steven Shiau <steven@nchc.org.tw> + * Thomas Lange <lange@informatik.uni-koeln.de> diff --git a/tools/XBMCLive/live-initramfs/docs/ChangeLog b/tools/XBMCLive/live-initramfs/docs/ChangeLog new file mode 100644 index 0000000000..4d0e52a099 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/docs/ChangeLog @@ -0,0 +1,635 @@ +commit 96aa9285ee39f4d3d4245acd8c78accdf73c1fa8 +Author: Daniel Baumann <daniel@debian.org> + + Bumping version to 1.104.1-1. + + Makefile | 2 +- + debian/changelog | 2 +- + docs/parameters.txt | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +commit 1a226e19e03be8ff90aaa50a7b5b9f202f65b8a4 +Author: Daniel Baumann <daniel@debian.org> + + Merging casper 1.104. + + docs/ChangeLog.casper | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +commit bb97432f7c5eeb330d108be6607edfe0de85bfa7 +Author: Daniel Baumann <daniel@debian.org> + + Bumping version to 1.103.1-1. + + Makefile | 2 +- + debian/changelog | 2 +- + docs/parameters.txt | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +commit 29c11f22032ccdb71aaccd5f6eb4a9be3efa5741 +Author: Daniel Baumann <daniel@debian.org> + + Merging casper 1.103. + + docs/ChangeLog.casper | 8 ++++++++ + scripts/live-bottom/23networking | 24 +++++++++++++++--------- + scripts/live-bottom/25configure_init | 8 +++----- + 3 files changed, 26 insertions(+), 14 deletions(-) + +commit 66a175b6255aa061dc78fbd301c9844489c42fc8 +Author: Daniel Baumann <daniel@debian.org> + + Preparing live-initramfs 1.102.2-1. + + Makefile | 10 +++++----- + debian/changelog | 6 ++++++ + docs/parameters.txt | 2 +- + 3 files changed, 12 insertions(+), 6 deletions(-) + +commit 0b8cf3f17ed46e96fb5efd658c8e308ba1a2dd1a +Author: Daniel Baumann <daniel@debian.org> + + Releasing live-initramfs 1.102.1-1. + + debian/changelog | 2 +- + docs/ChangeLog | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 196 insertions(+), 1 deletions(-) + +commit b782261bbdf33ff5c69780cc4c788c339d707f9b +Author: Daniel Baumann <daniel@debian.org> + + Sorting Depends. + + debian/control | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +commit 17b3b36ef3c1fa5cbe5b11c9690a2b0a403db693 +Author: Daniel Baumann <daniel@debian.org> + + Applied patch from Michael Prokop <mika@grml.org> to depend on busybox. + + debian/control | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +commit 27cc7504bc8310e2836014d64576be7d9c974be2 +Author: Daniel Baumann <daniel@debian.org> + + Bumping version to 1.102.1-1. + + Makefile | 2 +- + debian/changelog | 2 +- + docs/parameters.txt | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +commit 9e5b3c1cbeb80a472ba4387ef7e59b5e6bce913b +Author: Daniel Baumann <daniel@debian.org> + + Merging casper 1.102. + + docs/ChangeLog.casper | 10 ++++++ + scripts/live-bottom/42disable_apparmor | 36 ++++++++++++++++++++++ + scripts/live-bottom/42disable_cups_apparmor | 43 --------------------------- + 3 files changed, 46 insertions(+), 43 deletions(-) + +commit 7b5c1e3232d0e02e712a4f984cd1e5009c9e4e9c +Author: Daniel Baumann <daniel@debian.org> + + Adding noapparmor boot parameter. + + scripts/live | 5 +++++ + scripts/live-bottom/42disable_cups_apparmor | 5 +++++ + 2 files changed, 10 insertions(+), 0 deletions(-) + +commit ea5fee194ea66ab0f41a0a973034db201651e09a +Author: Daniel Baumann <daniel@debian.org> + + Bumping version to 1.101.1-1. + + Makefile | 2 +- + debian/changelog | 2 +- + docs/parameters.txt | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +commit b525502a2fdf073f4e326c1ca4dd8c89258ef65d +Author: Daniel Baumann <daniel@debian.org> + + Adjusting to live-initramfs. + + scripts/live-bottom/42disable_cups_apparmor | 37 ++++++++++++++++---------- + 1 files changed, 23 insertions(+), 14 deletions(-) + +commit 9b2894eaf50ce542d03329a0b49bf8df7d633371 +Author: Daniel Baumann <daniel@debian.org> + + Merging casper 1.101. + + docs/ChangeLog.casper | 9 ++++++++ + scripts/live-bottom/42disable_cups_apparmor | 29 +++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+), 0 deletions(-) + +commit f1e9fafee6e04a269a506edd31c62abd6917ecee +Author: Daniel Baumann <daniel@debian.org> + + Merging casper 1.100. + + docs/ChangeLog.casper | 8 ++++++++ + scripts/live-bottom/41apt_cdrom | 3 --- + 2 files changed, 8 insertions(+), 3 deletions(-) + +commit 2df075f459f0a232a084ca6ad037d89764727d5f +Author: Daniel Baumann <daniel@debian.org> + + Using new Homepage field now. + + debian/control | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +commit d29346c7b4c7a67fed080ea46be15421dec12fe7 +Author: Daniel Baumann <daniel@debian.org> + + Applied patch from Frederic Boiteux <fboiteux@calistel.com> about NFSROOT=auto, <http://lists.alioth.debian.org/pipermail/debian-live-devel/2007-September/002173.html>. + + scripts/live | 10 +++++----- + 1 files changed, 5 insertions(+), 5 deletions(-) + +commit 4f4c8e22af7a539cfa8bc9ba371c6a57b8e7cb0c +Author: Daniel Baumann <daniel@debian.org> + + Applied patch from Michael Prokop <mika@grml.org> to migrate live-snapshot.en.1 and live-snapshot.it.1 to asciidoc as well. + + manpages/Makefile | 17 ++++-- + manpages/live-snapshot.en.1 | 71 -------------------------- + manpages/live-snapshot.en.1.txt | 100 ++++++++++++++++++++++++++++++++++++ + manpages/live-snapshot.it.1 | 70 ------------------------- + manpages/live-snapshot.it.1.txt | 107 +++++++++++++++++++++++++++++++++++++++ + 5 files changed, 219 insertions(+), 146 deletions(-) + +commit 3226d2bfd4e2463c9aa7a691f7e9ea132e258af6 +Author: Daniel Baumann <daniel@debian.org> + + Adding Marco Amadori <marco.amadori@gmail.com>. + + docs/CREDITS | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +commit 757b214139daa0f7f312434ed0f77961ea380c4e +Author: Daniel Baumann <daniel@debian.org> + + Sorting Build-Depends. + + debian/control | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +commit 8d6e39ce90ed0be835514a15fbf3a007a2b9f3fa +Author: Daniel Baumann <daniel@debian.org> + + Simplifying make calls. + + debian/rules | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +commit bef37dff239b6c28fef89679537bea8643628fe1 +Author: Daniel Baumann <daniel@debian.org> + + Applied patch from Michael Prokop <mika@grml.org> to remove deprecated manpages/live-initramfs.en.7 (switched to asiidoc). + + manpages/live-initramfs.en.7 | 127 ------------------------------------------ + 1 files changed, 0 insertions(+), 127 deletions(-) + +commit 6a86b38986ab23d5cda24b38dca27c4a659bdfbd +Author: Daniel Baumann <daniel@debian.org> + + Applied patch from Michael Prokop <mika@grml.org> to update debian/control and debian/rules for use of asciidoc. + + debian/control | 2 +- + debian/rules | 2 ++ + 2 files changed, 3 insertions(+), 1 deletions(-) + +commit 6685b97a4041477b2ccbfc9683e35c022cbe9ce7 +Author: Daniel Baumann <daniel@debian.org> + + Applied patch from Michael Prokop <mika@grml.org> to switch to asciidoc for documentation. + + manpages/Makefile | 21 +++ + manpages/live-initramfs.en.7.txt | 304 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 325 insertions(+), 0 deletions(-) + +commit 3b545dfb73b7ce99c3fd6e107d6843891f005ab1 +Author: Daniel Baumann <daniel@debian.org> + + Fixing typing error. + + debian/control | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +commit ab933503a8204649724c525facbc14f734f1cd4e +Author: Daniel Baumann <daniel@debian.org> + + Preparing live-initramfs 1.99.3-1. + + Makefile | 8 ++++---- + debian/changelog | 6 ++++++ + docs/parameters.txt | 2 +- + manpages/live-initramfs.en.7 | 2 +- + manpages/live-snapshot.en.1 | 2 +- + 5 files changed, 13 insertions(+), 7 deletions(-) + +2007-09-09 Daniel Baumann <daniel@debian.org> + + * Using common indenting. + * scripts/live: + - Applied patch from Jim Paris <jim@jtan.com> to fix wrong usage of + ipconfig (Closes: #440235). + * Uploaded 1.99.2-1. + +2007-09-09 Michael Prokop <mika@grml.org> + + * scripts/live: + - Extending toram parameter to specify module. + - Adding forgotten nofstab boot parameter. + * scripts/live-bottom/40install_driver_updates: + - Adding check driver updates. + * scripts/live-bottom/25configure_init: + - Adding check for file-rc. + * scripts/live-bottom/21xvidemode: + - Sorting variable checks always before logging. + * scripts/live, live-bottom/*: + - Adding boot parameters to disable each service. + * scripts/live, live-bottom/22gnome_panel_date: + - Adding nognomefstab boot parameter. + * scripts/live-bottom/38disable_restricted_manager: + - Removing leftover reference to casper-functions. + +2007-09-05 Daniel Baumann <daniel@debian.org> + + * scripts/live, scripts/live-bottom: + - Added nouser parameter to disable user creation. + - Added noxautoconfig parameter to disable xorg re-configuration. + - Added nohosts parameter to disable /etc/hosts creation. + * scripts/live-bottom/15autologin: + - Moved disabling of kpersonalizer to 34disable_kpersonalizer. + +2007-09-01 Daniel Baumann <daniel@debian.org> + + * Merging changes from casper 1.97, 1.98 and 1.99. + * Uploaded 1.99.1-1. + +2007-08-29 Daniel Baumann <daniel@debian.org> + + * scripts/live-bottom/12fstab: + - By default, we do not have fstab, so it is save to just append the + unionfs mount rather than overwritting it. + * hooks/live: + - Including wget if available. + * Uploaded 1.96.2-1. + +2007-08-21 Daniel Baumann <daniel@debian.org> + + * Merging changes from casper 1.96. + * Uploaded 1.96.1-1. + +2007-08-21 Daniel Baumann <daniel@debian.org> + + * scripts/live: + - Applied patch from Jesse W. Hathaway <jesse@mbuki-mvuki.org> to + not use nfsro with kernels larger than 2.6.22 (where unionfs 2.x + is supposed to be available soon). + * Uploaded 1.95.3-1. + +2007-08-11 Daniel Baumann <daniel@debian.org> + + * Uploaded 1.95.2-1. + +2007-08-01 Daniel Baumann <daniel@debian.org> + + * scripts/live-bottom/10adduser: + - Setting debconf preseeding for passwd/make-user manually to true, + overriding any users preseeding on that, so that the user account + gets created for sure. + +2007-07-29 Daniel Baumann <daniel@debian.org> + + * Merging changes from casper 1.95. + * Uploaded 1.95.1-1. + +2007-07-26 Daniel Baumann <daniel@debian.org> + + * Merging changes from casper 1.92, 1.93 and 1.94. + +2007-07-26 Daniel Baumann <daniel@debian.org> + + * bin/live-md5check: + - Removed, using standard md5sum which makes the md5 check slower, + doesn't integrate well with usplash yet, but it makes live-initramfs + architecture independent now. + * scripts/live: + - Fixed typo. + - Added live-media-path as suggested by Jordi Pujol + <jordi_pujol@telefonica.net>. + * Uploaded 1.91.6-1. + +2007-07-19 Daniel Baumann <daniel@debian.org> + + * scripts/live, scripts/live-bottom/02_timezone: + - Added utc boot parameter as suggested by Vladimir Stavrinov + <vs@inist.ru> + +2007-07-18 Daniel Baumann <daniel@debian.org> + + * docs/parameters.txt: + - Added values for vga parameter. + * scripts/live: + - Added patch from Thomas Lange <lange@informatik.uni-koeln.de> to + respect rootserver name from dhcp. + * Uploaded 1.91.5-1. + +2007-07-12 Daniel Baumann <daniel@debian.org> + + * bin/live-snapshot, scripts/live: + - Moved /cow to /live/cow. + * scripts/live, scripts/live-bottom/01integrity_check, 05mountpoints: + - Moved /live_media to /live/image. + * Uploaded 1.91.4-1. + +2007-07-07 Daniel Baumann <daniel@debian.org> + + * scripts/live: + - Added debug parameter. + +2007-06-31 Daniel Baumann <daniel@debian.org> + + * scripts/live: + - Added patch from Julian Andres Klode <jak@jak-linux.org> to add + support for aufs. + * hooks/live, manpage/live-initramfs.en.7, scripts/live-bottom/12fstab: + - Added aufs support. + * Uploaded 1.91.3-1. + +2007-06-30 Daniel Baumann <daniel@debian.org> + + * scripts/live-bottom/12fstab: + - Added disabling of /etc/init.d/checkfs.sh to avoid file systemcheck + at boot time. Added nofastboot parameter to be able to change that. + - Disabled removal of checkroot.sh. + +2007-06-28 Daniel Baumann <daniel@debian.org> + + * Applied patch from Mathieu Geli <mathieu.geli@gmail.com> to set the + timezone with a boot parameter. + +2007-06-25 Daniel Baumann <daniel@debian.org> + + * scripts/live: + - Added missing nfsopts boot parameter. + - Changed default module name from 'order' to 'filesystem'. + - Changed module extension from '.lst' to '.module'. + - Check not just for $MODULE.module, but also + filesystem.$MODULE.module + - Cleaned up parse_cmdline and is_live_path functions. + * debian/control, debian/live-initramfs.init, + scripts/live-premount/10driver_updates: + - Moving eject to recommends. + - Added checks for eject existence. + * Uploaded 1.91.2-1. + +2007-06-17 Daniel Baumann <daniel@debian.org> + + * debian/live-initramfs.postinst: + - Made update-initramfs call conditional as suggested by Thomas Lange + <lange@informatik.uni-koeln.de>. + * debian/live-initramfs.postrm: + - Added update-initramfs call to cleanup. + +2007-06-17 Daniel Baumann <daniel@debiann.org> + + * Added patch from Thomas Lange <lange@informatik.uni-koeln.de> to + properly load ide-generic after udev. + * Uploaded 1.91.1-1. + +2007-06-15 Daniel Baumann <daniel@debian.org> + + * Merging changes from casper 1.91. + +2007-06-14 Daniel Baumann <daniel@debian.org> + + * scripts/live-bottom/18hostname: + - Appending to /etc/hosts to not overwrite custom settings. + +2007-06-08 Daniel Baumann <daniel@debian.org> + + * Merging changes from casper 1.88. + * Merging changes from casper 1.90. + * hooks/live: + - Added force loading of ide-generic module. It is required on some + systems to boot (reported as needed also for some qemu versions). + * Uploaded 1.90.1-1. + +2007-06-04 Daniel Baumann <daniel@debian.org> + + * Uploaded 1.87.6-1. + +2007-05-28 Daniel Baumann <daniel@debian.org> + + * scripts/live-bottom/42apt_upgrade: + - Moved to dedicated live-initscripts package. + +2007-05-24 Daniel Baumann <daniel@debian.org> + + * debian/control: + - Added casper transitional package. + - Removed usplash conflicts. + * scripts/live-bottom/42apt_upgrade: + - Added, idea taken from Kais webconverger. + * Uploaded 1.87.5-1. + +2007-05-23 Daniel Baumann <daniel@debian.org> + + * scripts/*: + - Minor code cleanup. + +2007-05-18 Daniel Baumann <daniel@debian.org> + + * scripts/live, scripts/live-bottom/05mountpoints: + - Replaced 'mount -o move' with 'mount --move'. + * scripts/live, scripts/live-bottom/10adduser: + - Added check for 'nosudo' bootparameter to disable automatic + sudo configuration. + * scripts/live, scripts/live-bottom/13swap: + - Renamed 'swapoff' parameter to 'noswap'. + * scripts/live, scripts/live-bottom/15autologin: + - Added check for 'noxautologin' bootparameter to disable automatic + gdm/kdm login. + * scripts/live, scripts/live-bottom/25configure_init: + - Added check for 'noautologin' bootparameter to disable automatic + terminal login. + * bin/live-snapshot, scripts/live, scripts/live-helpers: + - Also recognize ext3, but treat it like ext2. + * Uploaded 1.87.4-1. + +2007-05-12 Daniel Baumann <daniel@debian.org> + + * scripts/live-bottom/*: + - Added generic header. + +2007-05-12 Daniel Baumann <daniel@debian.org> + + * scripts/live: + - Renamed CASPERCONF to LIVECONF. + - Renamed CASPERGETTY to LIVE_GETTY. + - Renamed LIVEMEDIA_* to LIVE_MEDIA_*. + * Uploaded 1.87.3-1. + +2007-05-11 Daniel Baumann <daniel@debian.org> + + * hooks/live: + - Reformated. + * scripts/live, scripts/live-bottom/13swap: + - Added check for swapoff bootparameter to disable usage of local swap + partitions. + +2007-05-09 Daniel Baumann <daniel@debian.org> + + * manpages/*: + - Added language suffix. + - Partially rewritten and reformated. + +2007-05-08 Daniel Baumann <daniel@debian.org> + + * Makefile, doc/AUTHORS, doc/CREDITS: + - Added. + * doc: + - Renamed to docs. + +2007-05-07 Daniel Baumann <daniel@debian.org> + + * debian/control: + - Added suggests to genext2fs and squashfs-tools. + - Removed depends to dmsetup. + * scripts/live-bottom/10adduser: + - Added patch from Ben Armstrong <synrg@debian.org> to write + $HOME/.su-to-rootrc file. + * scripts/live, scripts/live-bottom/21xvideomode: + - Added patch from Mathieu Geli <mathieu.geli@gmail.com> to have the + ability to force X video mode from kernel append line. + +2007-05-06 Daniel Baumann <daniel@debian.org> + + * Merging patches from casper 1.81+debian-4, see ChangeLog.casper. + * conf/live.conf: + - Renamed HOST to HOSTNAME. + * debian/init: + - Added quickreboot. + - Renamed /cdrom to /live_media. + * doc/ChangeLog.casper: + - Added missing debian uploads. + * manpages/live-initramfs.7: + - Updated. + * hooks/live: + - Reading live.conf earlier. + - Making some udev copies conditional for ubuntu. + - Allowing local keymap when using encrypted filesystems. + * scripts/live: + - Renamed HOST to HOSTNAME. + - Renamed /cdrom to /live_media. + - Added support for live-snapshot. + - Parsing commandline in one central place now. + - Added support for encrypted filesytem images. + - Added support for multiple filesystem images. + * scripts/live-bottom/01integrity_check: + - Renamed /cdrom to /live_media. + * scripts/live-bottom/02etc_live_conf: + - Added. + * scripts/live-bottom/05mountpoints: + - Renamed /cdrom to /live_media. + - Don't do anything if not required. + * scripts/live-bottom/10adduser: + - Changed default password. + - Disabling xscreensaver locking and copying ubiquity desktop only on + ubuntu. + * scripts/live-bottom/14locales: + - Added handling of locale bootparameter. + * scripts/live-bottom/15autologin: + - Added workaround for using gdm default config. + * scripts/live-bottom/18hostname: + - Renamed HOST to HOSTNAME. + * scripts/live-bottom/19keyboard: + - Added handling of keyboard bootparameter. + * scripts/live-bottom/20xconfig: + - Added handling of keyboard bootparameter. + - Added handling of locale bootparameter. + * scripts/live-bottom/23networking: + - Disabled loop over fixed network devices. + * scripts/live-bottom/24preseed: + - Added handling of multiple preseeding files. + - Removed locale handling. + * scripts/live-bottom/25configure_init: + - Added handling of serial ttys. + * scripts/live-bottom/30accessibility: + - Removed extra parsing of commandline. + * scripts/live-functions: + - Added function to really export variables. + * scripts/live-helpers: + - Added support for encrypted filesytem images. + +2007-05-06 Daniel Baumann <daniel@debian.org> + + * bin/casper-getty, casper-login, casper-preseed, casper-reconfigure, + casper-snapshot: + - Renamed to live-*. + * casper-md5check: + - Moved to bin. + - Renamed to live-md5check. + * casper.conf: + - Moved to conf/live.conf. + * caspermon: + - Removed. + * hooks/casper, scripts/casper, casper-bottom, casper-functions, + casper-helpers, casper-premount: + - Renamed to live*. + * bin/live-getty, live-login: + - Reformated. + * conf/live.conf: + - Reformated. + - Setting Debian defaults. + * bin/live-snapshot, debian/dirs, debian/install, debian/rules, + hooks/live, scripts/live: + - Replaces casper directory and file names with live-initramfs + directory and file names. + * debian/manpage: + - Moved to manpages. + - Renamed casper.7 to live-initramfs.7. + - Renamed casper-snapshot.1 to live-snapshot.1. + * debian/init: + - Changed activation parameter from boot=casper to boot=live. + * scripts/live-bottom/02_timezone: + - Fixed wrong script description. + * Uploaded 1.87.2-1. + +2007-04-30 Daniel Baumann <daniel@debian.org> + + * Forked casper 1.87. + * COPYING: + - Added. + * debian/control, debian/ubiquity-casper.install, ubiquity-hooks: + - Removed ubiquity support. + * debian/changelog: + - Moved old changelog to doc/ChangeLog.casper. + - Added new changelog for live-initramfs. + * debian/casper.dirs, casper.init, casper.install, casper.manpages, + casper.postinst: + - Renamed, removed packagename prefix from filename. + * debian/compat, copyright, dirs, manpages: + - Updated. + * debian/examples, links: + - Added. + * debian/rules: + - Updated. + - Added upstream target. + * debian/control: + - Updated. + - Added depends to file. + - Added conflicts/replaces to casper. + * debian/postinst: + - Running 'update-initramfs' for all kernel versions instead of latest + only. + * Uploaded 1.87.1-1. diff --git a/tools/XBMCLive/live-initramfs/docs/ChangeLog.casper b/tools/XBMCLive/live-initramfs/docs/ChangeLog.casper new file mode 100644 index 0000000000..31d5e92e5a --- /dev/null +++ b/tools/XBMCLive/live-initramfs/docs/ChangeLog.casper @@ -0,0 +1,2402 @@ +casper (1.157) jaunty; urgency=low + + [ Emmet Hikory ] + * 10adduser: add Category=Favorites support for netbook-launcher + (LP: #334656) + + [ Luke Yelavich ] + * scripts/casper-bottom/30accessibility && ubiquity-hooks/30accessibility: + - Remove the fast user switch applet from the top panel, to re-enable + the logout/shutdown menu options in the system menu. This is done for + the speech and braille accessibility profiles. Requiring several + keyboard shortcuts to access something that is not entirely accessible + yet only makes things difficult for blind/vision impaired users, and is + likely to cause much confusion if sed menu entries are not present. + + -- Luke Yelavich <themuso@ubuntu.com> Tue, 03 Mar 2009 15:49:21 +1100 + +casper (1.156) jaunty; urgency=low + + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: + - If using a laptop, enable the laptop keyboard layout + - There is no longer a need to set gconf values as root in only-ubiquity + mode + + -- Luke Yelavich <themuso@ubuntu.com> Fri, 06 Feb 2009 08:59:52 +0100 + +casper (1.155) jaunty; urgency=low + + [ Colin Watson ] + * Add myself to debian/copyright as an author, as I've done fairly + significant work on this. + * Eliminate casper-md5check's libm linkage; patch from "SurJector" who + points out that the automatic conversion is sufficient (LP: #293613). + * Restore showmounts/show-cow option (thanks, Carlo de Wolf and "probono"; + LP: #159006, #290330). + + [ Evan Dandrea ] + * Add support for ext4. + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 30 Jan 2009 12:14:00 +0000 + +casper (1.154) jaunty; urgency=low + + [ Evan Dandrea ] + * scripts/casper-bottom/02timezone: + - Remove as it's no longer needed and resets the timezone when + persistence is enabled (LP: #296855). + + [ Colin Watson ] + * Preseed console-setup/optionscode and console-setup/codesetcode to the + empty string on boot to avoid debris from the live filesystem build + process getting in the way of installation (LP: #94177). + + -- Colin Watson <cjwatson@ubuntu.com> Sun, 23 Nov 2008 12:44:45 +0000 + +casper (1.153) jaunty; urgency=low + + * scripts/casper-bottom/10adduser: + - Create links for Mythbuntu items on the Desktop too. + - Don't show removable drives on Mythbuntu desktop + * scripts/casper-bottom/46disable_services: + - New script for disabling services unnecessary to Live + mode that should still start after being installed. + + -- Mario Limonciello <superm1@ubuntu.com> Tue, 04 Nov 2008 01:25:59 -0600 + +casper (1.152) intrepid; urgency=low + + * Use kde4rc now for accessibility profiles + + -- Jonathan Riddell <jriddell@ubuntu.com> Sat, 25 Oct 2008 23:44:54 +0100 + +casper (1.151) intrepid; urgency=low + + * Force ubiquity to --automatic mode for ubuntu-mid + + -- Emmet Hikory <persia@ubuntu.com> Thu, 16 Oct 2008 15:31:16 +0100 + +casper (1.150) intrepid; urgency=low + + * Fix path to Kubuntu help file in 10adduser (really) + + -- Jonathan Riddell <jriddell@ubuntu.com> Thu, 16 Oct 2008 12:16:54 +0100 + +casper (1.149) intrepid; urgency=low + + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: + - Revert to using gconf keys for starting orca, as this is now what + orca does when the user chooses to automatically start orca from Orca's + preferences window. + - Explicitly set orca as the program to start up for magnification, + speech, and braille. + + -- Luke Yelavich <themuso@ubuntu.com> Thu, 16 Oct 2008 11:33:02 +1100 + +casper (1.148) intrepid; urgency=low + + * Skip remounting read-only in try_mount as it's unnecessary and + breaks persistence. Thanks James Westby (LP: #274076). + + -- Evan Dandrea <evand@ubuntu.com> Wed, 15 Oct 2008 13:09:57 -0400 + +casper (1.147) intrepid; urgency=low + + * Fix path to Kubuntu help file in 10adduser + + -- Jonathan Riddell <jriddell@ubuntu.com> Wed, 15 Oct 2008 12:49:29 +0100 + +casper (1.146) intrepid; urgency=low + + * Update About Kubuntu link in 10adduser for KDE 4 + + -- Jonathan Riddell <jriddell@ubuntu.com> Mon, 06 Oct 2008 17:54:15 +0100 + +casper (1.145) intrepid; urgency=low + + * 38disable_restricted_manager: Remove some obsolete l-r-m and + restricted-manager code, and rename the script to 38jockey_disable_check + to better reflect its purpose. + + -- Martin Pitt <martin.pitt@ubuntu.com> Mon, 06 Oct 2008 09:21:40 +0200 + +casper (1.144) intrepid; urgency=low + + * Bump media detection timeout to a minute; thanks to Tormod Volden and + Steve Beattie for analysis (LP: #258432). + * Note that this changes (fixes?) the semantics of LIVEMEDIA_TIMEOUT due + to not using hex values in a for loop which aren't understood by test + -lt (thanks, Steve Beattie). + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 26 Sep 2008 18:35:13 +0100 + +casper (1.143) intrepid; urgency=low + + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: Change the way that orca is set to + automatically start. Orca can be started via a gconf key, however this + is not reflected in the orca UI, and doesn't easily allow the user to + prevent orca from autostarting on an installed system. + + -- Luke Yelavich <themuso@ubuntu.com> Wed, 24 Sep 2008 10:37:35 +1000 + +casper (1.142) intrepid; urgency=low + + * Fix syntax error introduced by is_nice_device regex fix. + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 19 Sep 2008 02:30:59 +0100 + +casper (1.141) intrepid; urgency=low + + [ Johannes Ballé ] + * Handle spaces in file names in md5sum.txt (LP: #251112). + + [ Colin Watson ] + * Support ?= (set value but don't mark as seen) preseeding syntax in + preseed script; previously we only supported it in the keyboard script, + which confusingly doesn't deal with propagating console-setup/* preseeds + to the target filesystem (LP: #253749). + * Update to localechooser's new languagelist format. + + [ Tormod Volden ] + * scripts/casper: don't scan floppy drives for livefs images (LP: #97306) + * scripts/casper: fix broken RE in is_nice_device() (LP: #250328) + * scripts/casper: properly use argument $1 in matches_uuid() + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 19 Sep 2008 02:14:05 +0100 + +casper (1.140) intrepid; urgency=low + + [ Colin Watson ] + * Disable jockey as well as the old restricted-manager. While jockey does + do more than restricted-manager did, it also still uses a good chunk of + memory for a use case that's fairly limited on the live CD. + + [ Luke Yelavich ] + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: + - Check that usr/bin/orca exists and is executable before creating user + settings files. + + -- Luke Yelavich <themuso@ubuntu.com> Fri, 12 Sep 2008 19:23:41 +1000 + +casper (1.139) intrepid; urgency=low + + * add compcache conf.d configuration for initramfs-tools + + -- Oliver Grawert <ogra@ubuntu.com> Thu, 14 Aug 2008 00:25:54 +0200 + +casper (1.138) intrepid; urgency=low + + [ Tormod Volden ] + * use full path for vol_id in swap-on-raid detection (LP: #136804) + + [ Martin Pitt ] + * 33enable_apport_crashes: Change the apport default file, not the + update-notifier gconf keys, to undo the corresponding change for disabling + apport right before the release. + * Add 45disable_guest_account: Purge the gdm-guest-session package from the + live system, since having guest sessions in a live session does not make + much sense. (See gdm-guest-login spec) + + -- Martin Pitt <martin.pitt@ubuntu.com> Thu, 31 Jul 2008 14:19:07 +0200 + +casper (1.137) intrepid; urgency=low + + * Update scripts/casper-bottom/15autologin for KDM from KDE 4. + * Update 32disable_hibernation for KDE 4. + + -- Jonathan Riddell <jriddell@ubuntu.com> Thu, 17 Jul 2008 13:41:38 +0100 + +casper (1.136) intrepid; urgency=low + + * Remove bad-and-wrong setting of PATH to include directories under /root; + now that grep links to more libraries than before, this broke a number + of things. Requires initramfs-tools (>= 0.92bubuntu5) because this + doesn't work with klibc chroot. + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 11 Jul 2008 12:34:35 +0100 + +casper (1.135) intrepid; urgency=low + + [ Loic Minier ] + * Fix use of PREREQ instead of PREREQS in hooks/casper. + + [ Colin Watson ] + * Fix mount argument ordering for klibc mount. + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 09 Jul 2008 12:34:26 +0100 + +casper (1.134) intrepid; urgency=low + + [ Evan Dandrea ] + * Do not use mode= when mounting /cow using persistent mode (LP: #219192). + + [ Colin Watson ] + * Support ?= (set value but don't mark as seen) preseeding syntax for + console-setup/* (LP: #64058). + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 30 Jun 2008 23:52:41 +0100 + +casper (1.133) intrepid; urgency=low + + [ Tormod Volden ] + * Do not use swap on RAID raw devices (LP: #136804) + + [ Agostino Russo ] + * Test if livemedia is a directory before trying to mount it as a + loopfile + * Reverted changes to casper-helpers as requested by Mithrandir since + replaying the journal on a hibernated system would lead to file system + corruption (LP: #230703). + + -- Evan Dandrea <evand@ubuntu.com> Wed, 18 Jun 2008 12:34:58 -0400 + +casper (1.132ubuntu0.2) hardy-proposed; urgency=low + + * Test if livemedia is a directory before trying to mount it as a + loopfile + * Reverted changes to casper-helpers as requested by Mithrandir since + replaying the journal on a hibernated system would lead to file system + corruption (LP: #230703). + + -- Agostino Russo <agostino.russo@gmail.com> Tue, 10 Jun 2008 00:27:12 +0100 + +casper (1.132ubuntu0.1) hardy-proposed; urgency=low + + * Do not scan only vfat volumes when looking for cow devices (LP: #230703) + * Allow casper to use a squashfs filesystem within an arbitrary path (LP: + #230716, #207137) + + -- Agostino Russo <agostino.russo@gmail.com> Thu, 15 May 2008 22:10:50 +0100 + +casper (1.132) intrepid; urgency=low + + [ Colin Watson ] + * Switch default unionfs implementation to aufs. + + [ Agostino Russo ] + * Do not scan only vfat volumes when looking for cow devices (LP: #230703) + * Allow casper to use a squashfs filesystem within an arbitrary path (LP: + #230716, #207137) + + -- Evan Dandrea <evand@ubuntu.com> Wed, 28 May 2008 15:01:30 -0400 + +casper (1.131) hardy; urgency=low + + [ Luke Yelavich ] + * scripts/casper-bottom/30accessibility: Set gconf and orca config values as + root in automatic-ubiquity, only-ubiquity, and debug-ubiquity modes. + * ubiquity-hooks/30accessibility: Remove unneeded gconf call to disable esd. + + [ Colin Watson ] + * Ensure that the live CD user's Desktop directory is owned by them, not + by root (LP: #218576). + * Duplicate a chunk of console-setup logic into the keyboard script so + that we can deal with non-Latin keymaps and the like without having to + have gfxboot-theme-ubuntu help us; the previous approach broke other + uses of console-setup, and thus the alternate install CD (LP: #218754). + This should later be replaced by just running console-setup, and I'll + open another bug for this. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 21 Apr 2008 14:52:05 +0100 + +casper (1.130) hardy; urgency=low + + * Handle use of debian-installer/language for locale selection + (LP: #213930). + + -- Colin Watson <cjwatson@ubuntu.com> Sat, 12 Apr 2008 00:30:10 +0100 + +casper (1.129) hardy; urgency=low + + * Add COPYING file with GPL text (LP: #211923). + * Add casper-new-uuid script to simplify UUID regeneration process, + contributed by Mario Limonciello of Dell (LP: #209847). + * Update casper-snapshot for genext2fs --reserved-blocks => + --reserved-percentage option change (LP: #202048). Add a Breaks as the + most lightweight available method of documenting that we need genext2fs + >= 1.4.1 for this. + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 10 Apr 2008 01:45:47 +0100 + +casper (1.128) hardy; urgency=low + + [ Luke Yelavich ] + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: + - Update gconf keys to ensure onboard actually gets loaded. + - Change ownership of created orca settings files to the user. + - Add extra bits to make orca settings actually work. + + [ Evan Dandrea ] + * Add mode=755 to the tmpfs mount that becomes / in the unionfs mount + so that / in the live filesystem does not end up with 777 permissions + (LP: #206030). + + [ Colin Watson ] + * Make scripts/casper-bottom/38disable_restricted_manager executable + again. + * Depend on uuid-runtime for uuidgen. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 31 Mar 2008 18:11:55 +0100 + +casper (1.127) hardy; urgency=low + + * Leave spawning the noninteractive ubiquity frontend to its initscript. + + -- Evan Dandrea <evand@ubuntu.com> Tue, 25 Mar 2008 15:52:32 -0400 + +casper (1.126) hardy; urgency=low + + * scripts/casper-bottom/10adduser: Test for konqueror not kdesktop, + stops putting a broken icon on the Kubuntu KDE 4 desktop + + -- Jonathan Riddell <jriddell@ubuntu.com> Tue, 25 Mar 2008 15:42:31 +0000 + +casper (1.125) hardy; urgency=low + + [ Colin Watson ] + * Stop quoting Exec arguments in .desktop files. Apparently this used to + work but now the system conforms more strictly to the desktop entry + specification (LP: #204185). + + [ Jonathan Riddell ] + * scripts/casper-bottom/15autologin: Enable auto-login for KDM-KDE4 + + -- Jonathan Riddell <jriddell@ubuntu.com> Thu, 20 Mar 2008 10:20:17 +0000 + +casper (1.124) hardy; urgency=low + + [ Colin Watson ] + * Name generated snapshot images according to their type (LP: #202699). + + [ Martin Pitt ] + * scripts/casper-bottom/44pk_allow_ubuntu: Remove erroneous blank line at + the start of PolicyKit.conf, since this is invalid XML. This broke + PolicyKit completely on the live system. + + -- Martin Pitt <martin.pitt@ubuntu.com> Tue, 18 Mar 2008 10:20:08 +0100 + +casper (1.123) hardy; urgency=low + + * Add scripts/casper-bottom/44pk_allow_ubuntu: Allow PolicyKit privileges + without password to the default live session user. This avoids the need to + press Enter at the password prompt, which is quite confusing. Thanks to + MarioDebian! (LP: #201852) + + -- Martin Pitt <martin.pitt@ubuntu.com> Fri, 14 Mar 2008 17:26:37 +0100 + +casper (1.122) hardy; urgency=low + + * Fix paths in About Kubuntu links + + -- Jonathan Riddell <jriddell@ubuntu.com> Fri, 14 Mar 2008 15:12:38 +0000 + +casper (1.121) hardy; urgency=low + + * Use a link for About Kubuntu docs in Kubuntu-KDE4 + + -- Jonathan Riddell <jriddell@ubuntu.com> Wed, 12 Mar 2008 23:57:50 +0000 + +casper (1.120) hardy; urgency=low + + * Use dhclient directly instead of ifupdown for the url= kernel cmdline + argument so that we don't have to worry about the interfaces file + propagating to the installed system. + + -- Evan Dandrea <evand@ubuntu.com> Tue, 11 Mar 2008 13:08:08 -0400 + +casper (1.119) hardy; urgency=low + + [ Luke Yelavich ] + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: + - Disable compiz for screen reader and braille terminal accessibility + profiles. It is currently not possible to get feedback about open + windows when cycling through them using ALT + Tab with Compiz. + * ubiquity-hooks/30accessibility: Add braille terminal profile. + + [ Colin Watson ] + * Always set language in both /etc/default/locale and /etc/environment + (thanks, Sebastien Bacher). + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 03 Mar 2008 10:21:42 +0000 + +casper (1.118) hardy; urgency=low + + [ Julian Andres Klode, Colin Watson ] + * Use aufs instead of unionfs if union=aufs is given (LP: #187259). + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 14 Feb 2008 18:00:36 +0000 + +casper (1.117) hardy; urgency=low + + * Disable speech for magnifier and braille profiles again. Thanks + Luke Yelavich. + * esd is enabled by default, so the comment in 30accessibility is no + longer relevant. + + -- Evan Dandrea <evand@ubuntu.com> Wed, 13 Feb 2008 01:20:22 -0500 + +casper (1.116) hardy; urgency=low + + * Fix setting orca options in 30accessibility. + * Remove gdm and kdm from init when using automatic-ubiquity and + only-ubiquity. The ubiquity initscript will take care of spawning + these. + + -- Evan Dandrea <evand@ubuntu.com> Mon, 11 Feb 2008 12:19:39 -0500 + +casper (1.115) hardy; urgency=low + + * Add the user to the groups specified by user-setup-udeb. + + -- Evan Dandrea <evand@ubuntu.com> Thu, 24 Jan 2008 19:08:33 +0000 + +casper (1.114) hardy; urgency=low + + [ Colin Watson ] + * casper-md5check: Close md5_file before exiting. + * Disable tracker-applet as well as trackerd, otherwise the former starts + the latter. + * casper-snapshot: Fix argument parsing (thanks, Tormod Volden; + LP: #179411). + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 15 Jan 2008 18:25:21 +0000 + +casper (1.113) hardy; urgency=low + + [ Tollef Fog Heen ] + * dpkg-divert away update-initramfs as it's useless on live CDs and + annoying when people install LVM and similar tools in order to rescue + a system. LP: #150188 + + [ Colin Watson ] + * Adjust /etc/sudoers editing code so that it doesn't repeatedly add + "NOPASSWD:" in persistent mode (LP: #175159). + * Avoid ejecting the CD if booting from an ISO image rather than from a + physical CD (thanks, Agostino Russo; LP: #176014). + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 19 Dec 2007 09:17:50 +0000 + +casper (1.112) hardy; urgency=low + + * hooks/casper: no need to copy udevinfo into the initramfs, it's already + there inside udevadm + * scripts/casper: call udevadm with trigger and settle arguments + * scripts/casper-bottom/23networking: call udevadm with trigger and + settle arguments + * scripts/casper-helpers: call udevadm with info and settle arguments + + -- Scott James Remnant <scott@ubuntu.com> Fri, 14 Dec 2007 15:00:29 +0000 + +casper (1.111) hardy; urgency=low + + * Remove code to set the progress bar to throbbing, this now comes as + standard so we don't need to duplicate it or override things that + attempted to set progress. LP: #162397. + + -- Scott James Remnant <scott@ubuntu.com> Tue, 13 Nov 2007 20:49:31 +0000 + +casper (1.110) gutsy; urgency=low + + * Don't generate fglrx or the nvidia modules in the live session at boot; + we disable restricted-manager in the live session anyway so they aren't + straightforward to use (see #43706). Saves about 19 MB of memory. + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 05 Oct 2007 21:28:29 +0100 + +casper (1.109) gutsy; urgency=low + + * Cache the stty binary before ejecting the CD. + * Skip the CD eject prompt if 'noprompt' is on the kernel command line + (LP: #149159). + * Try each of (e.g.) 2.6.22-13-generic, 2.6.22-13, and 2.6.22 in turn as + directory names for driver updates (LP: #122430). + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 05 Oct 2007 03:24:43 +0100 + +casper (1.108) gutsy; urgency=low + + * If CASPER_GENERATE_UUID is set, generate a random UUID in the initramfs, + and check it against the discovered medium (unless booting with the + ignore_uuid parameter). This allows live CD images to be safely copied + to the hard disk without causing problems when booting future live CDs + (LP: #144800). + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 04 Oct 2007 14:23:37 +0100 + +casper (1.107) gutsy; urgency=low + + * Fix gconf keys for suspend and hibernate (thanks, Oliver Grawert; + LP: #144790). + * Enable suspend again since as far as I can see we no longer need to + probe DMI while figuring out whether to enable it (see #61535). + * Add a 'textonly' boot option to disable X (LP: #65818). + * Write the please-remove-CD message to /dev/console so that it works even + if usplash isn't running, and make sure to set /dev/console into a sane + state so that pressing Enter doesn't just result in ^M being displayed. + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 02 Oct 2007 15:12:57 +0100 + +casper (1.106) gutsy; urgency=low + + * Support preseed/early_command; code supplied here will be run using 'sh + -c' from casper-bottom, and can chroot to /root if needed (LP: #144845). + * Make sure we don't accidentally continue to boot if casper-md5check + fails (LP: #82856). + * Clear out debconf database backup files after preseeding to save memory + (LP: #43706). + * Mount everything as noatime to avoid unnecessary metadata writes. + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 28 Sep 2007 15:27:52 +0100 + +casper (1.105) gutsy; urgency=low + + * scripts/casper-bottom/36disable_trackerd: Disable trackerd in the live + session; it's not very useful in this context and it uses a fair bit of + memory. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 24 Sep 2007 17:25:50 +0100 + +casper (1.104) gutsy; urgency=low + + * casper-md5check: Fall back to text output if opening the usplash FIFO + fails (LP: #131209). + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 20 Sep 2007 01:07:45 +0100 + +casper (1.103) gutsy; urgency=low + + * Disable anacron harder so that it doesn't get started by battery events. + * Don't write out DHCP network interface stanzas if network-manager is + installed (LP: #139403). + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 19 Sep 2007 12:52:21 +0100 + +casper (1.102) gutsy; urgency=low + + * Rename 42disable_cups_apparmor to 42disable_apparmor and remove AppArmor's + rc.d startup links instead of just disabling the cups profile. AA profiles + will not generally work on the live system, so disabling it completely + allows us to ship more profiles without worrying any further. + (LP: #131976) + + -- Martin Pitt <martin.pitt@ubuntu.com> Fri, 14 Sep 2007 08:37:50 +0200 + +casper (1.101) gutsy; urgency=low + + * Add scripts/casper-bottom/42disable_cups_apparmor: Disable AppArmor + protection for cups on the live CD by switching the profiles to complain + mode. This is necessary until AppArmor works properly on stacked file + systems. (LP: #131976) + + -- Martin Pitt <martin.pitt@ubuntu.com> Wed, 12 Sep 2007 16:44:02 +0200 + +casper (1.100) gutsy; urgency=low + + * scripts/casper-bottom/41apt_cdrom: Remove unnecessary /root/cdrom + mounting/unmounting code, which only serves to generate error messages + (scripts/casper-bottom/05mountpoints handles this already). + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 11 Sep 2007 19:47:58 +0100 + +casper (1.99) gutsy; urgency=low + + [ Luke Yelavich ] + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: + - Change gconf setting used to automatically start Orca (LP: #131808). + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 31 Aug 2007 13:09:46 +0100 + +casper (1.98) gutsy; urgency=low + + * Load /preseed.cfg if it exists in the initramfs. + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 29 Aug 2007 16:18:27 +0100 + +casper (1.97) gutsy; urgency=low + + * Fix paths in scripts/casper-bottom/10adduser and + scripts/casper-bottom/38disable_restricted_manager + + -- Jonathan Riddell <jriddell@ubuntu.com> Wed, 29 Aug 2007 15:26:33 +0100 + +casper (1.96) gutsy; urgency=low + + [ Colin Watson ] + * Fix name and executability of timezone script. + + [ Jonathan Riddell ] + * In 10adduser add About Kubuntu document to desktop and remove + restricted-manager autostart files + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 07 Aug 2007 12:51:02 +0100 + +casper (1.95) gutsy; urgency=low + + * Fix regex syntax error while looking for non-CD devices for driver + updates. + * Fix ip= boot parameter, documented but not properly merged from Debian. + (LP: #128689). + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 27 Jul 2007 15:03:41 +0100 + +casper (1.94) gutsy; urgency=low + + [ Colin Watson ] + * Hack around keyboard configuration not being done until after the keymap + is set by having /etc/init.d/usplash reconfigure the console + (LP: #68487). + * Disable pam_lastlog on the console if doing autologin (LP: #126800). + + [ Luke Yelavich ] + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: + - Prevent gksu from grabbing keyboard focus for the v2, v3, and m1 + accessibility profiles. (LP: #67172) + * Start Orca when a Braille device is configured from choosing the + Braille option in the Accessibility menu. (Partially fixes Launchpad + bug #122024) + * Re-enable desktop sounds for the blindness accessibility profile, as + eSpeak should be able to speak alongside audio playback. + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 24 Jul 2007 16:24:55 +0100 + +casper (1.93) gutsy; urgency=low + + * revert gdm-cdd.conf handling for autologin to the chrooted code + as we had it in feisty. not chrooting brings up problems with the + alternatives system (dead symlinks) used for gdm-cdd.conf + + -- Oliver Grawert <ogra@ubuntu.com> Wed, 18 Jul 2007 15:08:16 +0200 + +casper (1.92) gutsy; urgency=low + + [ Colin Watson ] + * Don't bother chrooting just to run test(1). + + [ Evan Dandrea ] + * Added support for URL-based preseeding. + * Added 'noninteractive' option that starts ubiquity in noninteractive + mode on tty1. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 09 Jul 2007 15:23:51 +0100 + +casper (1.91) gutsy; urgency=low + + * Fix Maintainer field (ubuntu-devel-discuss, not ubuntu-devel). + * Remember to strip directories from paths when dealing with driver update + .debs (LP: #120217). + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 14 Jun 2007 09:51:33 +0100 + +casper (1.90) gutsy; urgency=low + + * Added to 22screensaver, to stop the screen automatically locking. + Fixes LP: #13497 for kubuntu as well. + + -- Sarah Hobbs <hobbsee@ubuntu.com> Thu, 07 Jun 2007 00:50:42 +1000 + +casper (1.89) UNRELEASED; urgency=low + + * Update Maintainer field to reflect reality; this package is no longer + maintained by me. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 06 Jun 2007 14:56:46 +0200 + +casper (1.88) gutsy; urgency=low + + * Add default values for root_persistence, home_persistence, + root_snapshot_label, and home_snapshot_label, and parse the persistent + command-line option, which went missing in the last merge from Debian. + This goes some way towards LP #84591 but doesn't quite fix it for me + since the USB stick inexplicably doesn't appear until a little too late. + * Use 'losetup -f' instead of walking /sys/block/loop*. Requires + busybox-initramfs 1:1.1.3-4ubuntu3. + * Install temporary workaround for /dev/loop* breakage in post-2.6.21 + kernels (LP: #118561). + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 04 Jun 2007 16:26:59 +0100 + +casper (1.87) feisty; urgency=low + + [ Colin Watson ] + * Improve language at end of MD5 check (LP: #100088). + + [ Martin Pitt ] + * Add casper-bottom/33enable_apport_crashes: Enable apport crash + notifications. They are disabled now by default in the installed system + for the final release. + + -- Martin Pitt <martin.pitt@ubuntu.com> Mon, 9 Apr 2007 14:31:50 +0200 + +casper (1.86) feisty; urgency=low + + [ Luke Yelavich ] + * scripts/casper-bottom/30accessibility & + ubiquity-hooks/30accessibility: + - Point to new settings file for gnome-orca, as package was changed + from python-support to pycentral. (LP: #91868) + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 5 Apr 2007 16:42:54 +0100 + +casper (1.85) feisty; urgency=low + + * Stop disabling nvidia and fglrx drivers. LP: #94359 + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 2 Apr 2007 13:16:46 +0200 + +casper (1.84) feisty; urgency=low + + [ Jani Monoses ] + * scripts/casper-bottom/13swap: Call /bin/dd not dd so it + correctly detects and uses existing swap partitions (LP: #62868) + + [ Tollef Fog Heen ] + * Make sure that we are settled before trying to set up netbooting. + (LP: #96076) + * Bind-mount /dev too, when configuring X, this should make it easier + for X to be correctly configured on a lot of systems. + * Add /root/lib and /root/usr/lib to /etc/ld.so.conf in the initramfs. + * Add any sources on the CD to APT using apt-cdrom. + * Set the time zone to UTC. LP: #13782 + * Fix deletion of checkroot script. LP: #66585. + + [ Colin Watson ] + * Fix error message if do_netmount fails (LP: #95134). + + -- Tollef Fog Heen <tfheen@ubuntu.com> Fri, 30 Mar 2007 12:37:58 +0200 + +casper (1.83) feisty; urgency=low + + * Fix usplash version in Conflicts. + * Add XS-Vcs-Bzr field to debian/control. + * scripts/casper-bottom/25configure_init: Support for "respawn COMMAND" + has been dropped from upstart jobs; cope with /etc/event.d/tty* using + "respawn" plus "exec COMMAND" now instead (LP: #92928). + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 19 Mar 2007 16:44:22 +0000 + +casper (1.82) feisty; urgency=low + + [ Ben Collins ] + * Depends on eject package, and copy it into initramfs. + * Add log_wait_msg function to use usplash_write INPUTENTER. + * Conflict with usplash older than the one that fixes INPUTENTER. + * Add driver-updates hooks. + + [ Colin Watson ] + * Fix more leftover /live_media wreckage (LP: #84592). + * Add a ubiquity hook to install driver-updates on the target system. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 5 Mar 2007 11:19:48 +0000 + +casper (1.81+debian-4) unstable; urgency=low + + * Added patch from Serkan Sakar <serkan.sakar@gmx.net> to allow local keymap + for use with encryption. + + -- Daniel Baumann <daniel@debian.org> Wed, 11 Apr 2007 09:04:00 +0200 + +casper (1.81+debian-3) unstable; urgency=low + + * Added depends to eject. + * Removed recommends to live-package. + + -- Daniel Baumann <daniel@debian.org> Wed, 21 Mar 2007 00:30:00 +0100 + +casper (1.81+debian-2) unstable; urgency=low + + [ Daniel Baumann ] + * Applied patch from Sebastian Raveau <sebastien.raveau@epita.fr> to + add support for filesystem images encrypted with loop-aes. + + [ Marco Amadori ] + * Added a "quickreboot" boot parameter, that prevent casper to eject the + media, useful for remote rebooting of a casper system, thanks to + Jonathan Hall <flimzy@flimzy.com> for the patch. + + -- Marco Amadori <marco.amadori@gmail.com> Fri, 16 Feb 2007 17:26:58 +0100 + +casper (1.81+debian-1) unstable; urgency=low + + * New upstream release. + * Some cleaning and renaming involved because most of the debian-only code + was merged in ubuntu sources, then back here. + * Extended manpage, thanks to Alex Owen <r.alex.owen@gmail.com> and + Jonathan Hall <flimzy@flimzy.com> (Closes: #409980). + * Included a slightly reworked and bug fixed version of "Allow specific + ordering of images" by Jonathan Hall <flimzy@flimzy.com> with a new boot + parameter: module=NAME. + + -- Marco Amadori <marco.amadori@gmail.com> Thu, 15 Feb 2007 10:21:01 +0100 + +casper (1.81) feisty; urgency=low + + * Merge in Debian's changes. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 7 Feb 2007 14:39:30 +0100 + +casper (1.80) feisty; urgency=low + + * scripts/casper-bottom/31disable_update_notifier: Allow update-notifier + to run for crash report handling, but disable its apt-check hook. + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 1 Feb 2007 00:11:06 +0000 + +casper (1.79+debian-3) unstable; urgency=low + + * Fix DEFCONSOLE for autoserial console, thanks to + "Alex Owen" <r.alex.owen@gmail.com>. + + -- Marco Amadori <marco.amadori@gmail.com> Sun, 4 Feb 2007 20:12:08 +0100 + +casper (1.79+debian-2) unstable; urgency=low + + * It now depends also on "file" (Closes: #409308). + * Fixed LIVEMEDIA_TIMEOUT values (Closes: #409300). + Thanks for both to Jonathan Hall <flimzy@flimzy.com>. + + -- Marco Amadori <marco.amadori@gmail.com> Sat, 3 Feb 2007 18:29:20 +0100 + +casper (1.79+debian-1) unstable; urgency=low + + * New Upstream release. + * Reverted: "Mount the first squashfs as /rofs." + + -- Marco Amadori <marco.amadori@gmail.com> Tue, 16 Jan 2007 12:12:34 +0100 + +casper (1.79) feisty; urgency=low + + [ Colin Watson ] + * ubiquity-hooks/30accessibility: Change /root to /target in + kderc_addtoprefixes (thanks, Jani Monoses). + * Call udevsettle after udevtrigger (thanks, Matthias Urlichs; LP: + #77438). + * Send casper-reconfigure error messages to stderr rather than stdout to + avoid interfering with debconf. + + [ Jani Monoses ] + * ubiquity-hooks/30accessibility, scripts/casper-bottom/30accessibility: + Fix v2 option to start orca in magnifier not speech mode. + Add v1, v2, v3, m1 and m2 Xubuntu options + + [ Tollef Fog Heen ] + * Apply patch from Luka Renko to support kde-guidance-powermanager and + ksmserver instead of klaptoprc as the latter is no longer used. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 10 Jan 2007 20:37:30 +0100 + +casper (1.78) edgy; urgency=low + + * Mount the first squashfs as /rofs. Breaks showmounts and won't work + properly with stacked filesystems, but works around a kernel oops with + multiply-mounted squashfses for Edgy. + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 25 Oct 2006 12:46:05 +0100 + +casper (1.77+debian-7) testing; urgency=medium + + * Backported two 1 line fixes (both serious bugs) from casper-1.79+debian-1 + and casper-1.79+debian-3: + - It now depends also on "file" (Closes: #409308). + - Fix DEFCONSOLE for autoserial console, thanks to + "Alex Owen" <r.alex.owen@gmail.com>. + + -- Marco Amadori <marco.amadori@gmail.com> Thu, 8 Feb 2007 11:19:46 +0100 + +casper (1.77+debian-6) unstable; urgency=medium + + * Improved snapshots features (even still experimental). + * Added "live-media-offset=BYTES" boot param, to enable "hiding" + feature, thanks to Sebastien Raveau <sebastien.raveau@epita.fr>. + * Now it creates /etc/resolv.conf if netbooted. + + -- Marco Amadori <marco.amadori@gmail.com> Fri, 1 Dec 2006 17:43:30 +0100 + +casper (1.77+debian-5) unstable; urgency=low + + * Fixed preseeding locale and keyboard's variant and options. + * Reorganized scans of /proc/cmdline. + * Improved manpages, thanks to Oliver Osburg for syntax corrections. + * Added "nopersistent" boot option to disable the "persistent" boot param. + * Added "xdebconf" boot option, that uses xdebconfigurator on the + rootfs to configure X (experimental). + + -- Marco Amadori <marco.amadori@gmail.com> Mon, 20 Nov 2006 22:12:18 +0100 + +casper (1.77+debian-4) unstable; urgency=medium + + * Removed -phigh from casper-reconfigure, not needed anymore. + * Fixed netboot /etc/network/interfaces generation, thanks to Hadar + <whadar@gmail.com>. + * Fixed X keyboard setup. Thanks to <ascii_77@yahoo.fr> for the idea. + * Fixed keyboard setup. + * Allow commandline-device to show up late, thanks to Bas Wijnen + <wijnen@debian.org> for the code and the care (Closes: #397320). + * Urgency is set to medium to try reaching Etch with important + features/bugfixes. + + -- Marco Amadori <marco.amadori@gmail.com> Mon, 6 Nov 2006 19:00:29 +0100 + +casper (1.77+debian-3) unstable; urgency=medium + + * Fixed "todisk=" parsing. + * Urgency is set to medium to try reaching Etch with important + features/bugfixes. + + -- Marco Amadori <marco.amadori@gmail.com> Wed, 1 Nov 2006 11:15:56 +0100 + +casper (1.77+debian-2) unstable; urgency=medium + + [ Marco Amadori ] + * Improved snapshotting (but still experimental). + * Renamed "host=" boot parameter to "hostname=" and shell variable "HOST" to + "HOSTNAME" for consistence, with linux and with username/USERNAME, as + requested by many people. + * Fixed a "keyb=" typo. + * Added dependence on lsb-base (used by init-script and + casper-snapshot). + * Removed DM support (obsolete). + * Changed a bit locale and keyboard handling. + * Fixed locale generation. + * Urgency is set to medium to try reaching Etch with important + features/bugfixes. + + [ Otavio Salvador ] + * Really lowered usplash conflicts since Debian doesn't has 0.4. + + -- Marco Amadori <marco.amadori@gmail.com> Mon, 30 Oct 2006 17:06:48 +0100 + +casper (1.77+debian-1) unstable; urgency=low + + * New upstream release. + * Added snapshot persistence feature (copy on boot, sync on reboot) via + different ways: squashfs, cpio.gz, and block device filesystems. + * Added boot parameter "live-media=<device>" to force trying to boot from + a specified device. + * Added support for "todisk=<device>" to copy the live media to a + device filesystem, subsequent boots could use "live-media=<device>". + * Slightly polished locales and keyboards handling. + * Extendend manpages. + * Readded a missing "sleep 1", reworked how live_media is detected, + thanks to Bas Wijnen <wijnen@debian.org> for the reports. + (Closes: #394308, #394554). + * Reworked casper-getty system, thanks to Alex Owen (Closes: #394686). + * Postint now rebuild all initramfs. + * Casper now Recommends also squashfs-tools and genext2fs, maybe + needed by casper-snapshot. + * Lowered usplash requirements, since usplash 0.4 is not in debian + yet. + + -- Marco Amadori <marco.amadori@gmail.com> Sun, 22 Oct 2006 20:25:38 +0200 + +casper (1.77) edgy; urgency=low + + * Honour console-setup/modelcode preseeding. Needed for Malone #66719, + #66774. + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 20 Oct 2006 19:59:39 +0100 + +casper (1.76) edgy; urgency=low + + [ Colin Watson ] + * Copy access=m2 accessibility changes into the corresponding ubiquity + hook. + * Remove spurious quoting from accessibility script. + * Clear console-setup/layoutcode and console-setup/variantcode if they + aren't supplied on the command line. + + [ Michael Vogt ] + * scripts/casper-bottom/35fix_language_selector: + - run fontconfig-voodoo if available to make sure that we have + optimal fontconfig settings for the CJK languages (lp: #49334) + + [ Henrik Nilsen Omma ] + * Fix a few accessibility items that were out of date, changing + gnopernicus -> orca and gok -> onboard (the gok entry was missing some + brackets as well; patch from Malone #58836, closes: Malone #65861). + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 16 Oct 2006 20:20:15 +0100 + +casper (1.75) edgy; urgency=low + + * Turn on accessibility in "Motor Difficulties - pointing devices" which + makes onboard start properly. closes: Malone: #65861. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Fri, 13 Oct 2006 14:12:10 +0200 + +casper (1.74) edgy; urgency=low + + [ Tollef Fog Heen ] + * Sync up ubiquity-hooks/30accessibility with + scripts/casper-bottom/30accessibility fixing spelling errors and + enabling accessibility in KDE. + + [ Colin Watson ] + * Fix check for presence of gconf2 (closes: Malone #58836). + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 11 Oct 2006 11:18:00 +0100 + +casper (1.73) edgy; urgency=low + + * Never run install-keymap or preseed debian-installer/keymap if + console-setup is detected, even if console-setup wasn't explicitly + preseeded. Contributes to Malone #60067. + + -- Colin Watson <cjwatson@ubuntu.com> Sat, 7 Oct 2006 01:56:20 +0100 + +casper (1.72) edgy; urgency=low + + * Force suspend and hibernate both off, since reconfiguring + gnome-power-manager kills usplash here. Fixes Malone: #61535 + completely. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Fri, 6 Oct 2006 14:22:23 +0200 + +casper (1.71+debian-1) unstable; urgency=low + + * New upstream release. + * Added experimental casper-snapshot script and manpage. + * Tagged for debtags project. + + -- Marco Amadori <marco.amadori@gmail.com> Thu, 28 Sep 2006 16:04:54 +0200 + +casper (1.71) edgy; urgency=low + + * Use TEXT-URGENT in shutdown script to make sure we display the "please + remove disc and press enter" text. Malone: #61533 + * Increase usplash timeout since "TIMEOUT 0" no longer means "spin + forever". + * Don't move-mount all the squashfs-es into / since that confuses mono + (and some other apps too). Malone: #62756 + * Disable kwallet by default. Malone: #47743 + * Add -n to language selector to make it not whine about + not-fully-installed langpacks. Malone. #37568 + * Override definition of log_end_msg in casper-functions. Make sure all + casper-bottom scripts use this. + * Pulsate bar in casper-top and casper-bottom. Malone: #61535 + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 4 Oct 2006 09:52:06 +0200 + +casper (1.70) edgy; urgency=low + + * Check for new file= alias as well as preseed/file= (closes: Malone + #63145). + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 4 Oct 2006 08:59:53 +0100 + +casper (1.69) edgy; urgency=low + + [ Tollef Fog Heen ] + * Use grep -E in scripts/casper. Malone: #57620 + * Fix syntax error in accessibility script + + [ Colin Watson ] + * Run 'sh -n' over everything in build target to avoid future syntax + errors. + * Fix check for /etc/default/console-setup (closes: Malone #62775). + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 2 Oct 2006 10:58:19 +0100 + +casper (1.68+debian-3) unstable; urgency=low + + * Really add casper manpage (Closes: #389867). + * Lintian cleanness reached. + + -- Marco Amadori <marco.amadori@gmail.com> Thu, 28 Sep 2006 12:36:29 +0200 + +casper (1.68+debian-2) unstable; urgency=low + + * Changed "staticip=" boot param to just "ip=". + * Added a manpage for casper. + * Lintian cleanings. + + -- Marco Amadori <marco.amadori@gmail.com> Tue, 26 Sep 2006 00:45:21 +0200 + +casper (1.68+debian-1) unstable; urgency=low + + * New upstream release. + * Added static network configuration support. + * Fixed gnome-screensaver-lock differences between ubuntu. + * username, host, and userfullname are now also settable + via kernel parameters. + + -- Marco Amadori <marco.amadori@gmail.com> Fri, 8 Sep 2006 11:26:02 +0200 + +casper (1.68) edgy; urgency=low + + * Honour console-setup/layoutcode and console-setup/variantcode preseeding + (closes: Malone #61573). + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 22 Sep 2006 16:09:53 +0100 + +casper (1.67) edgy; urgency=low + + * Make sure to write xorg.conf md5sum to the installed system, not the + live system in ubiquity-hooks/20xconfig + * Implement support for setting KDE's accessibility options too, thanks + to Jonathan Riddell for the patch. + * Use usplash's TEXT-URGENT for important messages when doing md5 checks + * Fix flashing of progress bar on 32 bit arches + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 23 Aug 2006 14:34:57 +0200 + +casper (1.66+debian-1) unstable; urgency=low + + * Added "magic" to make it work seamlessy also on ubuntu systems. + * Default user password now "live". + + -- Marco Amadori <marco.amadori@gmail.com> Fri, 1 Sep 2006 17:18:07 +0200 + +casper (1.66) edgy; urgency=low + + * Fix use of db_get in ubiquity accessibility hook. + * Use sudo instead of su to get to the live session user from the + initramfs or to the newly-installed user from ubiquity. su's argument + handling has changed so that the previous code no longer worked, and su + was never all that good for arguments containing spaces anyway. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 4 Sep 2006 15:46:55 +0100 + +casper (1.65+debian-1) unstable; urgency=low + + * New upstream release. + * Re-included ubiquity sources since it is here anyway in diff.gz. + * Included remote getty patch from Alex Owen (enable it with "casper-getty" + as kernel parameter). + + -- Marco Amadori <marco.amadori@gmail.com> Thu, 17 Aug 2006 14:06:10 +0200 + +casper (1.65) edgy; urgency=low + + * Update to call udevsettle/udevtrigger instead of udevplug + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 21 Aug 2006 19:37:58 +0200 + +casper (1.64) edgy; urgency=low + + * Fix moving of squashfs mount points so that /proc/mounts in the + installed system refers to them correctly (closes: Malone #55019). As a + bonus, this lets us mount them on subdirectories of /casper/ right from + the start. + * Treat locale= as equivalent to debian-installer/locale= (closes: Malone + #53444). + * Fix ubiquity-hooks/30accessibility not to use log_end_msg, and to chroot + to /target instead of /root (closes: Malone #53277). + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 3 Aug 2006 14:00:22 +0100 + +casper (1.63+debian-3) unstable; urgency=low + + * Really do not try to eject cd if netbooted. + * Fixed unionfs ro param in case of nfs netboot (Closes: 383346). + + -- Marco Amadori <marco.amadori@gmail.com> Wed, 16 Aug 2006 20:10:11 +0200 + +casper (1.63+debian-2) unstable; urgency=low + + * Working netboot support (Closes: #380506). + * Polished kernel parameters parsing a bit. + + -- Marco Amadori <marco.amadori@gmail.com> Sun, 13 Aug 2006 15:52:14 +0200 + +casper (1.63+debian-1) unstable; urgency=low + + [Marco Amadori] + * New upstream release. + * Fixed upstream changelog. + * Really fixed the user password issue, now really "debian". + * Reincluded casper-md5ckeck in debian/rules and 05mountpoints in + script/casper-bottom. + * Rewrote netboot support now will support all types of rootfs file images + (not only plain dirs) like cd/dvd one. + * Included a fix for USB by Davide Natalini <davide.natalini@studio.unibo.it> + * Included support for plain directory as RO rootfs. + * Removed xfs support (not implemented in make-live, maybe useless). + + [Alex Owen] + * Added NFS netboot support (Closes: #380506). + * Fixed /etc/inittab editing (Closes: #380488). + * Do not try to eject cd if netbooted (Closes: #380502). + + [Daniel Baumann] + * Minor debian/rules reordering. + * Changed "Section:" from "admin" to "misc". + + -- Marco Amadori <marco.amadori@gmail.com> Sun, 30 Jul 2006 19:10:23 +0200 + +casper (1.63) edgy; urgency=low + + [ Tollef Fog Heen ] + * Change "Live CD user" to "live session user" in the adduser script. + Malone #46882 + * Wait for persistent devices for 30 seconds, not 1500. + * Make sure that readahead-list is installed before chmod -x'ing it. + * Only disable l-r-m and anacron if they are installed. + * Make sure laptop-detect is installed before trying to call it. + * Do not install init script from the initramfs any more. It should + have rc.d links already in the squashfs. + * Minor build system fixes. + * Only copy devmapper relevant files if devmapper is installed. + * Remove ubuntu-specific branding from the default casper. + * Install default configuration file and make it end up in the + initramfs. + * Get rid of CD references and replace with medium or other appropriate + terms. + * Add stacked file system support + + [ Marco Amadori ] + * Added possibility to set locale on chroot, not only at runtime. + * Updated 14locales to latest debian policy. + + [ Malcolm Gilles ] + * USB devices can have ID_PATH with pci-*-usb, too. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 18 Jul 2006 10:20:51 +0200 + +casper (1.61+debian-2) unstable; urgency=low + + * Set password for user to 'debian'. + + -- Daniel Baumann <daniel@debian.org> Wed, 19 Jul 2006 20:56:00 +0200 + +casper (1.61+debian-1) unstable; urgency=low + + [ Daniel Baumann ] + * Rebuild tarball without debian directory. + * Using dpatch for upstream modifications. + * Added patch for proper GDM autologin from Arnaud Cornet + <arnaud.cornet@gmail.com>. + + [ Marco Amadori ] + * New upstream release (Resynced with 1.61, bzr 258). + * Usb discover patch from Malcom Gilles <live@ouabain.org>. + + -- Marco Amadori <marco.amadori@gmail.com> Tue, 18 Jul 2006 23:34:59 +0200 + +casper (1.61) edgy; urgency=low + + * Move PATH setting to top of casper script to avoid silliness where + PATH isn't correctly set. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 17 Jul 2006 12:53:59 +0200 + +casper (1.60) edgy; urgency=low + + * Change start symlinks to kill symlinks for anacron, to avoid it being + started by invoke-rc.d and similar. + * Rearrange source package. + * Redo how the init script works and require it to be installed in the + live fs. + * Bump version number to be higher than Debian's so we don't + automatically sync. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 31 May 2006 00:01:40 +0200 + +casper (1.59+debian-1) unstable; urgency=low + + [ Daniel Baumann ] + * Upload to unstable (Closes: #354539). + + [ Marco Amadori ] + * Added possibility to set locale on chroot, not only at runtime. + * Removed "persistent" wait. + * Fixed persistence lock and added "homepersistence" boot parameter. + * Updated locales handling to latest debian policy. + * Cleanups + + -- Daniel Baumann <daniel@debian.org> Thu, 22 Jun 2006 06:21:00 +0200 + +casper (1.59+debian-0) UNRELEASED; urgency=low + + * Added "toram" boot parameter. + * Extendend fs support to ext2 and xfs file image. + * Changed debian-inexistant "-Q" modprobe option with "-q". + * Removed ubiquity code. + * USERNAME and HOST defaulted to "debian". + * Preliminary netboot (cifs) patch by + "Jason D. Clinton" <me@jasonclinton.com> + * Lowered dependence of dmsetup code (now only Suggests). + * Checks for replacing "udevplug" (ubuntu-only) with "udevtrigger". + * Reworked xorg and anacron patches from + Frederic Lehobey <Frederic.Lehobey@free.fr>. + * scripts/casper-bottom/10adduser: configuring only the $USERNAME for sudo + instead of group 'admin'. + + -- Marco Amadori <marco.amadori@gmail.com> Fri, 16 Jun 2006 11:01:48 +0200 + +casper (1.58) dapper; urgency=low + + * Really rename properly, without dirname. + + -- Scott James Remnant <scott@ubuntu.com> Tue, 30 May 2006 22:47:04 +0100 + +casper (1.57) dapper; urgency=low + + * Rename the anacron rc.d/S* symlinks to K*, instead of removing them. + Because otherwise pbbuttonsd decides that starting anacron on the + LiveCD would be a clever thing to do. + + -- Scott James Remnant <scott@ubuntu.com> Wed, 24 May 2006 23:06:04 +0100 + +casper (1.56) dapper; urgency=low + + * Hopefully work a bit better when checking DVDs on 32 bit + architectures. + * Do an explicit read from /dev/console when waiting for keypress after + CD/DVD has been ejected. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 22 May 2006 16:43:03 +0200 + +casper (1.55) dapper; urgency=low + + * Reconfigure gnome-power-manager when doing live installations. + Malone #45654 + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 22 May 2006 11:16:46 +0200 + +casper (1.54) dapper; urgency=low + + [ Luke Yelavich ] + * Set large print fonts for the v1 accessibility profile. Closes + Malone #45376. + + [ Colin Watson ] + * Fix preseed/file handling (closes: Malone #43683). + + -- Tollef Fog Heen <tfheen@ubuntu.com> Thu, 18 May 2006 19:36:24 +0200 + +casper (1.53) dapper; urgency=low + + [ Tollef Fog Heen ] + * Disable fglrx and nvidida drivers by default. Somewhat addresses + #43706 + + [ Colin Watson ] + * Pass all command-line preseed arguments (other than preseed/file) to + /root's debconf db. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Sat, 13 May 2006 10:14:36 +0200 + +casper (1.52) dapper; urgency=low + + * Export the path in casper-reconfigure so X and friends actually have + sbin in their path. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Thu, 11 May 2006 21:04:11 +0200 + +casper (1.51) dapper; urgency=low + + [ Luke Yelavich ] + * casper-bottom/30accessibility: + - Removed stale reference to acessx_applet. + - Fix some typos for gconf values that had to be set as lists. + + [ Colin Watson ] + * Pass debian-installer/locale to /root's debconf db (closes: Malone + #41896). + * Identify ourselves as casper when communicating with debconf. + * Factor out preseeding code into casper-preseed; this knows that it only + needs to register a question if it fails to set it, which saves memory + by avoiding debconf having to rewrite templates.dat. + * Preseed kbd-chooser/method as well as debian-installer/keymap, so that + kbd-chooser run from ubiquity picks up the selected keyboard (closes: + Malone #42202). + * Use new dpkg-reconfigure --no-reload option (debconf 1.4.72ubuntu6) to + avoid needlessly rewriting templates.dat. + + [ Tollef Fog Heen ] + * Add ... to the end of all usplash messages. Malone #43856 + * Add maybe_break casper-bottom to allow breaking before running bottom + scripts. Malone #43860 + * Don't show the name of the live cd user that's added. + * Mount COW filesystem if show-cow is present on the kernel command line. + Malone #43687 + * Disable the Kubuntu update notifier too. Malone #43806 + * Disable hibernation and enable sleep where appropriate. Malone #23882 + + -- Tollef Fog Heen <tfheen@ubuntu.com> Thu, 11 May 2006 12:11:08 +0200 + +casper (1.50) dapper; urgency=low + + [ Luke Yelavich ] + * Fixed some typos, and added missing settings to some accessibility + profiles, as they were either not working properly, or at all. Malone: + #39472, #39473 + * Removed the desktop wallpaper, and changed the background colour to gray + for the v1 accessibility profile. + * Set the whiteglass mouse theme for the v1 accessibility profile. + * Moved the gconftool-2 -s flag to individual gct calls, to allow for future + use of gconftool-2 flags that are incompatible with -s. + + [ Daniele Favara ] + * Allow custom HOST, USERNAME, USERFULLNAME. Malone: #42118 + * Add example file + - debian/casper.dir: Add examples dir + - debian/casper.conf: Explain briefly how to use new variables + - debian/rules: Install casper.conf as example_conf_casper + + [ Tollef Fog Heen ] + * Stylistic changes to Daniele's changes. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 2 May 2006 14:12:31 +0200 + +casper (1.49) dapper; urgency=low + + * Also look for hardware named wlan* + + -- Scott James Remnant <scott@ubuntu.com> Wed, 26 Apr 2006 13:37:13 +0100 + +casper (1.48) dapper; urgency=low + + * Write /etc/network/interfaces entries for eth0, eth1, eth2, ath0 and + wlan0 if there's no hardware detected for them; as it may be plugged + in after boot. + + -- Scott James Remnant <scott@ubuntu.com> Wed, 26 Apr 2006 12:31:38 +0100 + +casper (1.47) dapper; urgency=low + + [ Tollef Fog Heen ] + * Turn on debugging of the X config. + * Log to a file which gets copied to /var/log/casper.log. Malone: #39895 + * Only pick UTF-8 locales. Malone: #40178 + * Use correct /root rather than /target for seeing what version of + gnome-panel-data is installed. + * Make festival (and probably some other apps) happier by using + 127.0.1.1 for our ubuntu hostname and 127.0.0.1 just resolves to + "localhost". + * Make casper-md5check read from tty8 since it wants to get keypresses + from the active console (where usplash runs). Malone: #40490. + * Copy /etc/modules when installing with ubiquity. Malone: #40311 + * /etc/gdm/gdm-cdd.conf can be a symlink. Cope with that. Malone: #40767 + + [ Colin Watson ] + * ubiquity-casper conflicts/replaces espresso-casper. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 24 Apr 2006 09:41:14 +0200 + +casper (1.46) dapper; urgency=low + + * Use debian-installer/dummy for preseeding rather than espresso/dummy, + since the latter was removed in espresso 0.99.38. + * espresso is being renamed to ubiquity. Rename espresso-casper to + ubiquity-casper to match. + + -- Colin Watson <cjwatson@ubuntu.com> Fri, 21 Apr 2006 12:52:48 +0100 + +casper (1.45) dapper; urgency=low + + [ Matt Zimmerman ] + * [share/shutdown] Disable the usplash timeout and wrap the prompt to two + lines + + [ Tollef Fog Heen ] + * Use devmapper for ia64, hppa and sparc. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 19 Apr 2006 11:36:49 +0200 + +casper (1.44) dapper; urgency=low + + * Reset the timeout after casper-premount has run so we're sure that the + timeout is what we want it to be. Udev seems to change it too. + * Remove a few set -x commands to make the boot slightly less verbose. + * Fix 10adduser to actually install the correct icons for espresso. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 12 Apr 2006 14:20:53 +0200 + +casper (1.43) dapper; urgency=low + + * Copy espresso-kdeui.desktop file to user's desktop + Branch at http://kubuntu.org/~jriddell/bzr/casper/trunk/ + + -- Jonathan Riddell <jriddell@ubuntu.com> Thu, 13 Apr 2006 15:37:49 +0100 + +casper (1.42) dapper; urgency=low + + [ Luke Yelavich ] + * casper-bottom/30accessibility: + - Removed some settings from accessibility profiles as these are now + in the relevant packages. + + [ Tollef Fog Heen ] + * Make sure to call gconftool as the right user. Malone #38408 + * Write an entry for / in fstab. Hopefully fixes Malone #34330 + * Change gdm-cdd.conf if it exists, not gdm.conf. Malone #37467 + * Really disable update-notifier, this time by removing the correct + file. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 11 Apr 2006 15:43:24 +0200 + +casper (1.41) dapper; urgency=low + + * Don't mkdir then install -D, just install -D (this should prevent + ~ubuntu/Desktop being owned by root) + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 29 Mar 2006 10:52:42 +0200 + +casper (1.40) dapper; urgency=low + + * Add snd_powermac to /etc/modules on ppc. (Malone: #27862) + * Use chmod -x instead of mv to disable readahead in order to not + trigger unionfs bugs + * Reboot the system when a key is pressed at the end of the integrity + check. (Malone: #29203) + * Use usplash_write too when doing shutdown. (Malone: #34537) + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 28 Mar 2006 10:09:49 +0200 + +casper (1.39) dapper; urgency=low + + [ Tollef Fog Heen ] + * Disable update-notifier by default, as it won't make much sense for + most people. + + [ Colin Watson ] + * Clear out user-setup questions from the debconf database after creating + the live CD user, to avoid confusing espresso into offering "Ubuntu + LiveCD user" as the user's default full name. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 13 Mar 2006 11:38:39 +0100 + +casper (1.38) dapper; urgency=low + + * Disable readahead since it breaks too much with squashfs and unionfs. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Thu, 9 Mar 2006 09:43:39 +0100 + +casper (1.37) dapper; urgency=low + + * Add support for having the squashfs directly on a device, thanks to + Paul Sladen for idea and a patch. + * If a directory "Examples" exists in ~ after we've run adduser, move it + to the Desktop subdirectory for greater visibility. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Sat, 4 Mar 2006 11:55:50 +0100 + +casper (1.36) dapper; urgency=low + + [ Tollef Fog Heen ] + * Fix typo in find_cow_device so block devices didn't work at all. + Malone #31639. Thanks to Richard Nemec for the catch. + * Update accessibility framework, thanks to Luke Yelavich. + + [ Colin Watson ] + * Move the /cdrom mount into the new root filesystem. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 1 Mar 2006 11:13:54 +0100 + +casper (1.35) dapper; urgency=low + + * Check for preseed/file= in /proc/cmdline and feed any given file to + debconf-set-selections. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 27 Feb 2006 17:32:02 +0000 + +casper (1.34) dapper; urgency=low + + [ Luke Yelavich ] + * Add initial accessibility support framework + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 22 Feb 2006 14:36:07 +0100 + +casper (1.33) dapper; urgency=low + + * Make sure Desktop and the espresso-$ui.desktop is owned by the Ubuntu + user. Malone #31991 + * Fix check for rc6.d/S90reboot at the bottom of 25configure_init to + actually look in the right place. + * Make me the maintainer of the package. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 20 Feb 2006 09:49:02 +0100 + +casper (1.32) dapper; urgency=low + + * Fix copying of /usr/share/applications/espresso-gtkui.desktop. + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 16 Feb 2006 16:47:15 +0000 + +casper (1.31) dapper; urgency=low + + [ Tollef Fog Heen ] + * Print message about rebooting the system when the md5 check is + finished. + * Just have one copy of the casper shutdown scripts and symlink those + into the right place. Malone #20978 + + [ Colin Watson ] + * Copy /usr/share/applications/espresso-gtkui.desktop to the live CD + user's desktop. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 14 Feb 2006 14:52:16 +0100 + +casper (1.30) dapper; urgency=low + + * Set a blank password for the ubuntu user. This hopefully resolves + Malone #30118 + * Pass keyboard layout information to xserver-xorg in the "new" scheme. + * Set up the right console keymap. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 14 Feb 2006 14:48:14 +0100 + +casper (1.29) dapper; urgency=low + + [ Tollef Fog Heen ] + * Fix typo in 22gnome_panel_data + * Configure all detected network interfaces. + * Add support for putting the persistent storage in a loopback file on + vfat volumes + * Configure all detected network interfaces. + * Allow putting the live filesystem image on a VFAT volume + * Allow putting the persistent storage in a loopback file on a VFAT + volume + * Lots of cleanups + + [ Colin Watson ] + * Change casper-reconfigure to take the target root filesystem as its + first argument. + * Add espresso-casper package with hooks to repeat some things done by + casper in the installed system. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 25 Jan 2006 14:25:45 +0100 + +casper (1.28) dapper; urgency=low + + * Depend on user-setup + * First shot at IEEE1394 support. Add sbp2 and ohci1394 as modules to + be copied into the initramfs. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 16 Jan 2006 22:06:35 +0100 + +casper (1.27) dapper; urgency=low + + * Try using unionfs on ppc again + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 10 Jan 2006 20:55:19 +0100 + +casper (1.26) dapper; urgency=low + + * Add persistency support + * Usplash integration + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 10 Jan 2006 17:53:54 +0100 + +casper (1.25) dapper; urgency=low + + * Make /rofs available to in the target system. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 9 Jan 2006 15:25:12 +0100 + +casper (1.24) dapper; urgency=low + + * For debconf-communicate, use a here-doc rather than trying to have \n + working in shell variables. + * The usplash fifo has moved, update paths accordingly. Also conflict + with the old usplash and depend on new enough initramfs-tools. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Fri, 6 Jan 2006 14:20:37 +0100 + +casper (1.23) dapper; urgency=low + + * Move the building to binary-dep, since we're an arch: any package + now. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Thu, 5 Jan 2006 10:37:31 +0100 + +casper (1.22) dapper; urgency=low + + * Bunch debconf-communicate commands together to speed up the boot a + little bit. + * Add integrity checker, this is compiled code, so casper is now arch: + any + + -- Tollef Fog Heen <tfheen@ubuntu.com> Wed, 4 Jan 2006 12:56:13 +0100 + +casper (1.21) dapper; urgency=low + + * If locale is unset, use en_US.UTF8, not whatever comes first in the + list of supported locales. + * Generate locale and set the locale in /etc/environment + * Use user-setup to create the user, rather than doing it ourselves. + * Various cleanups and fixes, such as making debconf-communicate silent + * Disable checkroot when booting + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 2 Jan 2006 11:00:25 +0100 + +casper (1.20) dapper; urgency=low + + * Remove a large bunch of debugging output + * Depend on dmsetup so the hook script can copy in that + * Handle both squashfs and cloop images, with run-time detection + * Use devmapper + cloop on powerpc, not unionfs, since unionfs is a + disaster there. + * Make sure we have both SCSI and IDE CDROM modules available in the + initramfs. + * Do some initial keyboard setup handling so X will, at least in some + cases, have a chance of giving the user a sane keymap. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Mon, 19 Dec 2005 14:23:13 +0100 + +casper (1.19) dapper; urgency=low + + * Switch to initramfs, so casper only survives in spirit + * Use unionfs instead of a writeable devmapper snapshot + * Remove all debconfiscation, since we're an initramfs script now + * Make the postinst call update-initramfs -u + * Mount the CD read-only explicitly + * Make udevinfo silent if the device is not found. + + -- Tollef Fog Heen <tfheen@ubuntu.com> Tue, 13 Dec 2005 16:22:45 +0100 + +casper (1.18) breezy; urgency=low + + * Update translations from Rosetta: Greek, Spanish, French, Hungarian, + Brazilian Portuguese. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 19 Sep 2005 20:05:02 +0100 + +casper (1.17) breezy; urgency=low + + * Set /apps/gnome-screensaver/lock if gnome-screensaver is installed + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 16 Sep 2005 15:24:35 -0700 + +casper (1.16) breezy; urgency=low + + * Install a fake script in /lib/debian-installer.d/S72menu-exit after + pivoting that just calls sleep, to prevent scary console messages as d-i + tries to exit without its root filesystem. + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 14 Sep 2005 10:28:06 +0100 + +casper (1.15) breezy; urgency=low + + * Neutralize branding in startup message + * Use clear in addition to reset, in hopes of concealing error messages on + the console from d-i's death throes + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 9 Sep 2005 11:24:14 -0700 + +casper (1.14) breezy; urgency=low + + * Set RUNNING_UNDER_GDM=yes in the user's environment to stop xscreensaver + locking the screen (Ubuntu #7150). + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 8 Sep 2005 13:37:00 +0100 + +casper (1.13) breezy; urgency=low + + * Use reset, rather than clear, to clean up after the colored dialogs on vt1 + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 7 Sep 2005 16:09:45 -0700 + +casper (1.12) breezy; urgency=low + + * Kill bterm after pivoting so that we can use vt1 rather than vt2, + thereby avoiding a fight between gdm and the X server (closes: Ubuntu + #14851). + + -- Colin Watson <cjwatson@ubuntu.com> Wed, 7 Sep 2005 15:48:40 +0100 + +casper (1.11) breezy; urgency=low + + * Remove debugging code which crept into 1.10 + * Revert changes to casper-udeb.postinst which were intended for + starting usplash earlier (pre-1.10) + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 2 Sep 2005 13:43:03 -0700 + +casper (1.10) breezy; urgency=low + + * Instead of starting usplash directly, create an init script which will + start it later (after the new init), to avoid it being killed by + busybox init + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 29 Aug 2005 20:26:58 -0700 + +casper (1.9) breezy; urgency=low + + * Remember to re-run 30copy-dev from 94usplash, in order to preserve the + device nodes clobbered by udev + * Redirect stdin of /etc/init.d/udev from /dev/console, to avoid + incredibly obnoxious 60-second sleep because it thinks we're + interactive + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 29 Aug 2005 18:30:38 -0700 + +casper (1.8) breezy; urgency=low + + * Add usplash support + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 29 Aug 2005 17:30:57 -0700 + +casper (1.7) breezy; urgency=low + + * Set DEBUG_XORG_PACKAGE=yes when reconfiguring xserver-xorg. The + output is only written to post.log and isn't visible to the user, and + can be invaluable for debugging + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 22 Aug 2005 10:25:38 -0700 + +casper (1.6) breezy; urgency=low + + * Use debconf-copydb again (thanks, Tollef) + * Rename pre.d/20xconfig to pre.d/20prexconfig so that it is distinct from + post.d/20xconfig for purposes of the progress bar (no text for it; it's + very fast) + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 17 Aug 2005 14:55:24 -0700 + +casper (1.5) breezy; urgency=low + + * Call MAKEDEV console in post.d/20xconfig as a workaround for bug + #13523 + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 16 Aug 2005 15:24:06 -0700 + +casper (1.4) breezy; urgency=low + + * Revert to the old debconf hack; the debconf-copydb approach needs more + work + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 15 Aug 2005 22:48:11 -0700 + +casper (1.3) breezy; urgency=low + + * Revert unintentional release of experimental unionfs code in 1.2 + + -- Matt Zimmerman <mdz@ubuntu.com> Sat, 13 Aug 2005 11:19:50 -0700 + +casper (1.2) breezy; urgency=low + + * Fix debconf-copydb regex in 20xconfig + + -- Matt Zimmerman <mdz@ubuntu.com> Sat, 13 Aug 2005 11:07:46 -0700 + +casper (1.1) breezy; urgency=low + + * Cope with xserver-xorg's rename of force_keyboard_detection to + autodetect_keyboard + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 4 Jul 2005 02:52:07 -0700 + +casper (1.0) breezy; urgency=low + + * Version number bump (we've been through a stable Ubuntu release, after + all) + * Rename pre.d/10snapshot to post.d/10filesystem, as it is about to + become more generic + * Seed xserver-xorg/force_keyboard_detection to true in 20xconfig, so as + to cause the keyboard layout to (continue to) be autodetected based on + d-i settings + + -- Matt Zimmerman <mdz@ubuntu.com> Thu, 16 Jun 2005 11:21:54 -0700 + +casper (0.65) breezy; urgency=low + + * As a performance optimization, only reconfigure gnome-panel-data if + booting on a laptop + * Disable the "lock screen" menu item (Ubuntu bug#7150) + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 8 Jun 2005 16:02:14 -0700 + +casper (0.64) breezy; urgency=low + + * Merge colin.watson@canonical.com--2005/casper--debconf-copydb--0 + - Use debconf-copydb rather than our temporary hack + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 31 May 2005 12:08:51 -0700 + +casper (0.63) breezy; urgency=low + + * Merge colin.watson@canonical.com--2005/casper--cdebconf-info--0 + - Update for cdebconf 0.75: use db_info rather than db_x_setbacktitle. + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 18 Apr 2005 20:59:58 -0700 + +casper (0.62) hoary; urgency=low + + * Updated translations from + colin.watson@canonical.com--2005/casper--translations--0 (nb) + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 5 Apr 2005 09:01:02 -0700 + +casper (0.61) hoary; urgency=low + + * Updated translations from + colin.watson@canonical.com--2005/casper--translations--0 (el, es, ro) + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 5 Apr 2005 08:06:51 -0700 + +casper (0.60) hoary; urgency=low + + * Updated translations from + colin.watson@canonical.com--2005/casper--translations--0 (hu, id, pl) + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 28 Mar 2005 11:26:21 -0800 + +casper (0.59) hoary; urgency=low + + * Updated translations from + colin.watson@canonical.com--2005/casper--translations--0 (de, pt_BR) + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 25 Mar 2005 16:51:17 -0800 + +casper (0.58) hoary; urgency=low + + * Remove postfix shutdown links, as well as startup, to avoid an ugly error + + -- Matt Zimmerman <mdz@ubuntu.com> Thu, 24 Mar 2005 18:24:03 -0800 + +casper (0.57) hoary; urgency=low + + * Merge colin.watson@canonical.com--2005/casper--translations--0 up to + patch-2 + * Preseed netcfg/wireless_essid_again for noninteractive network setup, +new + in netcfg 1.08ubuntu3 [colin.watson@canonical.com--2005/casper--netcfg--0] + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 23 Mar 2005 08:33:46 -0800 + +casper (0.56) hoary; urgency=low + + * Suppress error output from eject + * Remind the user to close the CD tray if they have one (Ubuntu #6668) + * Add arch-build target to debian/rules + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 22 Mar 2005 10:21:41 -0800 + +casper (0.55) hoary; urgency=low + + * Remove the hack introduced in 0.54, xorg 6.8.2-5 should be fixed + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 16 Mar 2005 18:11:05 -0800 + +casper (0.54) hoary; urgency=low + + * Temporarily set RECONFIGURE=true when reconfiguring xserver-xorg, to work + around a bug introduced in 6.8.2-3 + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 16 Mar 2005 15:08:45 -0800 + +casper (0.53) hoary; urgency=low + + * Provide target-base-system (i.e. base system installed in /target, also + provided by base-installer). + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 15 Mar 2005 13:01:53 +0000 + +casper (0.52) hoary; urgency=low + + * Arrange for $LANG to be set after pivot_root, so that (e.g.) + xserver-xorg can use it to infer the keymap (Ubuntu #7138) + + -- Matt Zimmerman <mdz@ubuntu.com> Sat, 12 Mar 2005 02:10:59 -0800 + +casper (0.51) hoary; urgency=low + + * Disable kpersonalizer startup on first login + + -- Matt Zimmerman <mdz@ubuntu.com> Sat, 5 Mar 2005 13:47:13 -0800 + +casper (0.50) hoary; urgency=low + + * Add support for configuring kdm autologin + * Rename 15gdm-autologin to 15autologin, and the corresponding debconf template + * Remove obsolete XORG_FORCE_PROBE from 20xconfig + + -- Matt Zimmerman <mdz@ubuntu.com> Thu, 3 Mar 2005 10:37:31 -0800 + +casper (0.49) hoary; urgency=low + + * Fix 20xconfig harder + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 2 Mar 2005 21:20:03 -0800 + +casper (0.48) hoary; urgency=low + + * Source confmodule in 20xconfig + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 2 Mar 2005 21:02:35 -0800 + +casper (0.47) hoary; urgency=low + + * Copy over the value of debian-installer/keymap into the target system, + to allow the new logic in xserver-xorg.config to work + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 2 Mar 2005 20:45:38 -0800 + +casper (0.46) hoary; urgency=low + + * Lock the live user's password entirely. Since the user is now + automagically logged in, continuously, both on the console and in X, + their password is irrelevant. + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 28 Feb 2005 08:31:13 -0800 + +casper (0.45) hoary; urgency=low + + * Enable TimedLogin in gdm, so that if the user logs out, they are + automatically logged back in after a few seconds (Ubuntu #6667) + + -- Matt Zimmerman <mdz@ubuntu.com> Sun, 27 Feb 2005 16:06:16 -0800 + +casper (0.44) hoary; urgency=low + + * Configure init to spawn shells on virtual consoles, rather than login + prompts (Ubuntu #6666) + * Skip X configuration if a serial console is in use + * Set the live user's password to be blank, rather than "ubuntu". This + is, paradoxically, more secure if the user decides to install + openssh-server, since empty passwords are disallowed by default + + -- Matt Zimmerman <mdz@ubuntu.com> Sun, 27 Feb 2005 15:40:15 -0800 + +casper (0.43) hoary; urgency=low + + * Override localechooser progress bar text to be more appropriate for the + live CD (closes: Ubuntu #6664). + + -- Colin Watson <cjwatson@ubuntu.com> Thu, 24 Feb 2005 19:12:00 +0000 + +casper (0.42) hoary; urgency=low + + * Preseed netcfg/no_interfaces, to avoid prompt when no network interfaces + can be configured (closes: Ubuntu #6107). + * Remove redundant DH_COMPAT setting in debian/rules, since there's + already a (different) debian/compat. + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 22 Feb 2005 12:43:43 +0000 + +casper (0.41) hoary; urgency=low + + * Cope with change in default /etc/sudoers (admin group). + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 22 Feb 2005 09:14:30 +0000 + +casper (0.40) hoary; urgency=low + + * Copy /dev/tts to the live system as well as /dev/vc, for serial console. + + -- Colin Watson <cjwatson@ubuntu.com> Mon, 21 Feb 2005 19:03:54 +0000 + +casper (0.39) hoary; urgency=low + + * Fix reboot operation (cache the reboot binary) + + -- Matt Zimmerman <mdz@ubuntu.com> Thu, 10 Feb 2005 20:51:08 -0800 + +casper (0.38) hoary; urgency=low + + * Eject the CD during shutdown/reboot + - Awful hack to copy /dev/cdroms to the live system, because the CD is + mounted using devfs names + - Add /usr/share/casper/shutdown script to casper-udeb + - Copy /usr/share/casper/shutdown to /etc/rc[06].d in 25configure-init + * Remove caspermon binary package, inadvertently enabled (not even + remotely ready) + + -- Matt Zimmerman <mdz@ubuntu.com> Thu, 10 Feb 2005 13:43:56 -0800 + +casper (0.37) hoary; urgency=low + + * Fix casper-udeb/runlevel template + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 8 Feb 2005 19:37:43 -0800 + +casper (0.36) hoary; urgency=low + + * Rename post.d/25disable-init-scripts to 25configure-init + * Add casper-udeb/runlevel, to allow the default runlevel + to be set + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 8 Feb 2005 19:14:16 -0800 + +casper (0.35) hoary; urgency=low + + * Preseed netcfg/wireless_essid + * Remove obsolete confmodule load from pre.d/12fstab + * Don't mount a tmpfs on /var/run; it doesn't save a huge amount of + snapshot space, and packages expect their directories there to be + persistent + + -- Matt Zimmerman <mdz@ubuntu.com> Mon, 7 Feb 2005 15:46:52 -0800 + +casper (0.34) hoary; urgency=low + + * Use casper-reconfigure in 10adduser as well + * Add post.d/93save-logs to save copies of the bootstrap logs to + /var/log/casper + * Stop reconfiguring fontconfig; it insists on rebuilding the entire + font cache, and the only benefit was to unable subpixel hints + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 2 Feb 2005 10:42:19 -0800 + +casper (0.33) hoary; urgency=low + + * Re-upload to fix borked source package + + -- Matt Zimmerman <mdz@ubuntu.com> Sun, 30 Jan 2005 12:21:07 -0800 + +casper (0.32) hoary; urgency=low + + * Factor out debconf hackery into casper-reconfigure + * Mount sysfs earlier, so we don't need to mess with it in 20xconfig + * Break 22simple-reconfig into 22fontconfig and 22gnome-panel-data, and + create progress bar text for them + * Preseed netcfg/dhcp_failed, to avoid a prompt when DHCP fails + + -- Matt Zimmerman <mdz@ubuntu.com> Sat, 29 Jan 2005 14:03:36 -0800 + +casper (0.31) hoary; urgency=low + + * Clear tty2 and print a nice message, before signalling init + + -- Matt Zimmerman <mdz@ubuntu.com> Sat, 29 Jan 2005 13:15:44 -0800 + +casper (0.30) hoary; urgency=low + + * Reconfigure fontconfig, to enable subpixel rendering based on the + hardware in use + + -- Matt Zimmerman <mdz@ubuntu.com> Thu, 27 Jan 2005 14:21:49 -0800 + +casper (0.29) hoary; urgency=low + + * Fix the problem described in 0.28 by preseeding a default for + netcfg/get_hostname + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 25 Jan 2005 23:04:03 -0800 + +casper (0.28) hoary; urgency=low + + * Suppress network configuration questions + + - The goal is to make a reasonable effort to configure one interface + automatically, but if that is not possible, fall back to no + configuration. We aren't quite there yet. + + - If we fail to resolve our IP into a hostname using DNS, netcfg seems + to fall back to an empty value, rather than the default in the + template. + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 25 Jan 2005 22:55:35 -0800 + +casper (0.27) hoary; urgency=low + + * Add post.d/22simple-reconfig + - Reconfigure gnome-panel-data if it is installed, to set up the GNOME + session based on whether the system is a laptop + - Corresponding progress template + - mount /proc earlier (needed for, e.g. laptop-detect) + * Warn about screen blanking in X configuration progress message + * Simplify post.d/20xconfig and pre.d/13swap a bit + * Update TODO + + -- Matt Zimmerman <mdz@ubuntu.com> Sat, 22 Jan 2005 15:56:49 -0800 + +casper (0.26) hoary; urgency=low + + * Set NOPASSWD in /etc/sudoers for the initial user + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 21 Jan 2005 16:53:49 -0800 + +casper (0.25) hoary; urgency=low + + * mount /proc before signalling init, as it now uses /proc to determine + what is and is not a kernel thread + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 21 Jan 2005 16:04:52 -0800 + +casper (0.24) hoary; urgency=low + + * Add a backtitle properly + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 21 Jan 2005 09:07:19 -0800 + +casper (0.23) hoary; urgency=low + + * Add a backtitle + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 21 Jan 2005 09:02:01 -0800 + +casper (0.22) hoary; urgency=low + + * Search for swap on SCSI disks as well as IDE + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 19 Jan 2005 14:27:09 -0800 + +casper (0.21) unstable; urgency=low + + * Cosmetic changes to debconf templates + * Fix 10adduser to register debconf questions before setting their + values and flags + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 19 Jan 2005 14:14:20 -0800 + +casper (0.20) hoary; urgency=low + + * Remove legacy symlinks from casper/pre.d; they are now contained in + the relevant udebs + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 19 Jan 2005 13:22:33 -0800 + +casper (0.19) hoary; urgency=low + + * Update TODO + * casper-udeb Depends: md-modules + + -- Matt Zimmerman <mdz@ubuntu.com> Wed, 19 Jan 2005 11:23:51 -0800 + +casper (0.18) hoary; urgency=low + + * Enable new adduser code, using db_fset ... seen to suppress the questions + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 18 Jan 2005 15:06:48 -0800 + +casper (0.17) hoary; urgency=low + + * Convert snapshot setup to use debconf instead of hardcoded parameters + * Remove obselete-before-being-used username template + * Convert post.d/10adduser to use debconf passthrough to the passwd package, + and thus share its user-adding code rather than duplicating it. + - But don't enable it yet, since we need to find a way to prevent its + questions from being asked + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 18 Jan 2005 13:04:48 -0800 + +casper (0.16) hoary; urgency=low + + * casper-udeb Depends: casper-check, harddrive-detection + * Automatically find and enable swap devices + + -- Matt Zimmerman <mdz@ubuntu.com> Tue, 18 Jan 2005 11:23:48 -0800 + +casper (0.15) hoary; urgency=low + + * Set anna/standard_modules to false at startup to suppress unnecessary + udeb retrieval. + + -- Colin Watson <cjwatson@ubuntu.com> Tue, 18 Jan 2005 13:41:00 +0000 + +casper (0.14) hoary; urgency=low + + * Enable X autoconfiguration(!) + + -- Matt Zimmerman <mdz@ubuntu.com> Sat, 15 Jan 2005 02:19:58 -0800 + +casper (0.13) hoary; urgency=low + + * Rename templates so that they are named after the {pre,post}.d hook + which uses them + * Remove some unused templates + + -- Matt Zimmerman <mdz@ubuntu.com> Fri, 14 Jan 2005 10:11:02 -0800 + +casper (0.12) hoary; urgency=low + + * Add debconf templates for various things that we currently hardcode. + Not actually used yet due to need for testing, but having the + templates present greatly simplifies testing the remaining integration + work + + -- Matt Zimmerman <mdz@ubuntu.com> Thu, 13 Jan 2005 20:32:39 -0800 + +casper (0.11) hoary; urgency=low + + * Update post.d/20xconfig to use debconf passthrough to cdebconf + (requires debconf 1.4.42 and cdebconf 0.75), but leave it disabled for + now + * Create /etc/fstab in the target (this also seems to solve the problem + with noatime disappearing, and so should reduce snapshot utilization) + + -- Matt Zimmerman <mdz@debian.org> Thu, 13 Jan 2005 18:25:36 -0800 + +casper (0.10) hoary; urgency=low + + * Remove rc?.d/K??hwclock.sh links, to avoid changing the system clock + during reboot or shutdown + + -- Matt Zimmerman <mdz@debian.org> Thu, 13 Jan 2005 18:13:31 -0800 + +casper (0.9) hoary; urgency=low + + * Fix gdm autologin configuration (broken in 0.8) + + -- Matt Zimmerman <mdz@debian.org> Wed, 12 Jan 2005 10:52:05 -0800 + +casper (0.8) hoary; urgency=low + + * Add debian-installer/casper-udeb/title template, to specify more + readable menu item text + * Create /usr/lib/casper/{pre,post}.d and move all of our internal logic + there + * Create temporary symlinks in pre.d for the prebaseconfig.d items we + want + * Convert errors into proper error dialogs + * Make some pre.d scripts idempotent, for ease of testing + + -- Matt Zimmerman <mdz@debian.org> Tue, 11 Jan 2005 16:59:35 -0800 + +casper (0.7) hoary; urgency=low + + * Disable X configuration temporarily; need to resolve debconf issues + + -- Matt Zimmerman <mdz@canonical.com> Tue, 11 Jan 2005 13:14:43 -0800 + +casper (0.6) hoary; urgency=low + + * Allow "modprobe ext2" to fail; apparently it's sometimes compiled in + + -- Matt Zimmerman <mdz@debian.org> Tue, 11 Jan 2005 12:12:28 -0800 + +casper (0.5) hoary; urgency=low + + * Attempt to configure X + - This doesn't work very well yet (PCI BusID doesn't seem to get + updated, for example), so we still don't start gdm by default) + * Conditionalize some of the configuration code, so we automatically do + the right thing if gdm or X isn't installed + * Add German translation from Andreas Mueller + * modprobe ext2, to let powerpc work (this should probably happen + elsewhere, but for now...) + + -- Matt Zimmerman <mdz@debian.org> Sun, 9 Jan 2005 17:49:56 -0800 + +casper (0.4) hoary; urgency=low + + * Mount tmpfs on /tmp and /var/run, should save many writes to the snapshot + + -- Matt Zimmerman <mdz@debian.org> Fri, 7 Jan 2005 18:35:26 -0800 + +casper (0.3) hoary; urgency=low + + * Disable anacron and postfix startup + * Don't cripple /bin/apt-install in d-i (this was a workaround to + prevent d-i from installing packages which should have been present in + the filesystem image anyway, but weren't) + + -- Matt Zimmerman <mdz@debian.org> Fri, 7 Jan 2005 18:10:55 -0800 + +casper (0.2) hoary; urgency=low + + * Use mount --move to move the cdrom mount point, so that we can unmount + /initrd and free up the memory used by d-i + * Use /dev/ram1 rather than /dev/ram0 for the COW stuff, since /dev/ram0 + is used for initrds and we want to avoid confusion + * Organize casper-udeb.postinst into shell functions + * Add a progress bar + * Add a debian/compat file (version 4) + + -- Matt Zimmerman <mdz@debian.org> Fri, 7 Jan 2005 08:01:21 -0800 + +casper (0.1) hoary; urgency=low + + * Initial Release. + + -- Matt Zimmerman <mdz@canonical.com> Wed, 5 Jan 2005 14:30:28 -0800 diff --git a/tools/XBMCLive/live-initramfs/docs/parameters.txt b/tools/XBMCLive/live-initramfs/docs/parameters.txt new file mode 100644 index 0000000000..60ad65002b --- /dev/null +++ b/tools/XBMCLive/live-initramfs/docs/parameters.txt @@ -0,0 +1,73 @@ +Boot Parameters for Debian Live +------------------------------- + +Updated for live-initramfs 1.156.1-1 on 2009-02-08. + +These options (can be combined) work from the bootloader prompt: + +live access=ACCESS +live console=TTY,SPEED +live debug +live fetch=URL +live hostname=HOSTNAME +live username=USER +live userfullname=USERFULLNAME +live integrity-check +live ip=[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF] [,[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF]]* +live ip[=frommedia] +live {keyb|kbd-chooser/method}=KEYBOARD +live {klayout|console-setup/layoutcode}=LAYOUT +live {kvariant|console-setup/variantcode}=VARIANT +live {kmodel|console-setup/modelcode}=CODE +live koptions=OPTIONS +live live-getty +live {live-media|bootfrom}=DEVICE +live {live-media-encryption|encryption}=TYPE +live live-media-offset=BYTES +live live-media-path=PATH +live live-media-timeout=SECONDS +live {locale|debian-installer/locale}=LOCALE +live module=NAME +live netboot[=nfs|cifs] +live nfsopts= +live noautologin +live noxautologin +live nofastboot +live nopersistent +live nosudo +live swapon +live nouser +live noxautoconfig +live persistent[=nofiles] +live persistent-path=PATH +live {preseed/file|file}=FILE +live package/question=VALUE +live quickreboot +live showmounts +live timezone=TIMEZONE +live todisk=DEVICE +live toram +live union=aufs|unionfs +live utc=yes|no +live xdebconf +live xvideomode=RESOLUTION + +Values for the vga kernel parameter: + +Colours 640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200 +--------+-------------------------------------------------------------- + 4 bits | ? ? 0x302 ? ? ? ? + 8 bits | 0x300 0x301 0x303 0x305 0x161 0x307 0x31C +15 bits | ? 0x310 0x313 0x316 0x162 0x319 0x31D +16 bits | ? 0x311 0x314 0x317 0x163 0x31A 0x31E +24 bits | ? 0x312 0x315 0x318 ? 0x31B 0x31F +32 bits | ? ? ? ? 0x164 ? + +Colours 640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200 +--------+-------------------------------------------------------------- + 4 bits | ? ? 770 ? ? ? ? + 8 bits | 768 769 771 773 353 775 796 +15 bits | ? 784 787 790 354 793 797 +16 bits | ? 758 788 791 355 794 798 +24 bits | ? 786 789 792 ? 795 799 +32 bits | ? ? ? ? 356 ? diff --git a/tools/XBMCLive/live-initramfs/hooks/live b/tools/XBMCLive/live-initramfs/hooks/live new file mode 100755 index 0000000000..4e29226a9e --- /dev/null +++ b/tools/XBMCLive/live-initramfs/hooks/live @@ -0,0 +1,178 @@ +#!/bin/sh + +# initramfs hook for live-initramfs (Debian Live) + +set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions + +# live-initramfs hook + +# Handling live-initramfs + +# Configuration +if [ -r /etc/live.conf ] +then + . /etc/live.conf + + mkdir -p "${DESTDIR}"/etc + cp /etc/live.conf "${DESTDIR}"/etc +fi + +# Directories +mkdir -p "${DESTDIR}"/lib/live-initramfs + +# Executables +copy_exec /usr/share/live-initramfs/live-reconfigure /bin +copy_exec /usr/share/live-initramfs/live-preseed /bin + +# Scripts +cp /usr/share/initramfs-tools/scripts/live-functions "${DESTDIR}"/scripts +cp /usr/share/initramfs-tools/scripts/live-helpers "${DESTDIR}"/scripts + +# klibc dependencies +for FILE in /lib/libacl* /lib/libblkid* /lib/libuuid* /lib/libdevmapper* /lib/libattr* +do + if [ ! -e "${DESTDIR}"/"${FILE}" ] + then + cp -a "${FILE}" "${DESTDIR}"/"${FILE}" + fi +done + +# Handling other stuff + +# Configuration: keymap (usefull when using encryption) +if [ -x /bin/loadkeys ] && [ -r /etc/console/boottime.kmap.gz ] +then + copy_exec /bin/loadkeys /bin + + mkdir -p "${DESTDIR}"/etc + cp /etc/console/boottime.kmap.gz "${DESTDIR}"/etc +fi + +# Configuration: Unique ID +if [ -n "${LIVE_GENERATE_UUID}" ] +then + mkdir -p "${DESTDIR}"/conf + uuidgen -r > "${DESTDIR}"/conf/uuid.conf +fi + +# Filesystem: cifs +if [ -x /sbin/mount.cifs ] +then + copy_exec /sbin/mount.cifs /sbin + manual_add_modules cifs +fi + +# Filesystem: ext3/ext4 +manual_add_modules ext3 +manual_add_modules ext4 + +# Filesystem: jffs2 +manual_add_modules jffs2 + +# Filesystem: squashfs +copy_exec /sbin/losetup /sbin +manual_add_modules loop +manual_add_modules squashfs +manual_add_modules sqlzma +manual_add_modules unlzma + +# Filesystem: aufs/unionfs +manual_add_modules aufs +manual_add_modules unionfs + +# Filesystem: vfat +manual_add_modules nls_cp437 +manual_add_modules nls_iso8859-1 +manual_add_modules nls_utf8 +manual_add_modules vfat + +# Filesystem: ntfs +manual_add_modules ntfs + +# Hardware: cdrom +manual_add_modules ide-cd +manual_add_modules ide-generic +manual_add_modules ohci1394 +manual_add_modules sbp2 +manual_add_modules sr_mod + +# Hardware: usb +manual_add_modules sd_mod + +# Hardware: network +auto_add_modules net + +# Program: eject +if [ -x /usr/bin/eject ] +then + copy_exec /usr/bin/eject /bin +fi + +# Program: md5sum +copy_exec /usr/bin/md5sum /bin + +# Program: cpio +# busybox and klibc lacks --no-absolute-filenames and --sparse, needed for snapshots +if [ -e "${DESTDIR}/bin/cpio" ] +then + # Override already present cpio's, mostly klibc's + rm "${DESTDIR}/bin/cpio" +fi +copy_exec /bin/cpio /bin + +# Program: udev +if [ -x /sbin/udevadm ] +then + # lenny + copy_exec /sbin/udevadm /sbin +else + # etch + copy_exec /sbin/udevtrigger /sbin + copy_exec /sbin/udevsettle /sbin +fi +if [ -x /usr/bin/udevinfo ] +then + copy_exec /usr/bin/udevinfo /bin +fi + +# Program: wget +if [ -x /usr/bin/wget ] +then + copy_exec /usr/bin/wget /bin +fi + +# FUSE kernel module +manual_add_modules fuse + +# FUSE filesystem: httpfs2 +if [ -x /usr/bin/httpfs2_ssl ] +then + copy_exec /usr/bin/httpfs2_ssl /bin/httpfs +elif [ -x /usr/bin/httpfs2 ] +then + copy_exec /usr/bin/httpfs2 /bin/httpfs +fi + +# FUSE filesystem: curlftpfs +if [ -x /usr/bin/curlftpfs ] +then + copy_exec /usr/bin/curlftpfs /bin +fi diff --git a/tools/XBMCLive/live-initramfs/manpages/Makefile b/tools/XBMCLive/live-initramfs/manpages/Makefile new file mode 100644 index 0000000000..c2ddc94bc0 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/Makefile @@ -0,0 +1,28 @@ +all: doc + +doc: doc_man doc_html + +doc_html: html-stamp + +html-stamp: live-initramfs.en.7.txt live-snapshot.en.1.txt + asciidoc -b xhtml11 live-initramfs.en.7.txt + asciidoc -b xhtml11 live-snapshot.en.1.txt + touch html-stamp + +doc_man: man-stamp + +man-stamp: live-initramfs.en.7.txt live-snapshot.en.1.txt + # live-initramfs: + asciidoc -d manpage -b docbook live-initramfs.en.7.txt + xsltproc /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl live-initramfs.en.7.xml + mv live-initramfs.7 live-initramfs.en.7 + # live-snapshot: + asciidoc -d manpage -b docbook live-snapshot.en.1.txt + xsltproc /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl live-snapshot.en.1.xml + mv live-snapshot.1 live-snapshot.en.1 + touch man-stamp + +clean: + rm -f live-initramfs.en.7.html live-initramfs.en.7.xml live-initramfs.en.7 + rm -f live-snapshot.en.1.html live-snapshot.en.1.xml live-snapshot.en.1 + rm -f html-stamp man-stamp diff --git a/tools/XBMCLive/live-initramfs/manpages/html-stamp b/tools/XBMCLive/live-initramfs/manpages/html-stamp new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/html-stamp diff --git a/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7 b/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7 new file mode 100644 index 0000000000..58e0520b73 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7 @@ -0,0 +1,314 @@ +.\" Title: live-initramfs +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 <http://docbook.sf.net/> +.\" Date: 06/29/2009 +.\" Manual: +.\" Source: +.\" +.TH "LIVE\-INITRAMFS" "7" "06/29/2009" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +live-initramfs \- Debian Live initramfs hook +.SH "SYNOPSIS" +BOOT=live +.sp +as kernel parameter at boot prompt\&. +.sp +.SH "DESCRIPTION" +live\-initramfs is a hook for the initramfs\-tools, used to generate a initramfs capable to boot live systems, such as those created by \fBlive\-helper\fR(7)\&. This includes the Debian Live isos, netboot tarballs, and usb stick images\&. +.sp +At boot time it will look for a (read\-only) media containing a "/live" directory where a root filesystems (often a compressed filesystem image like squashfs) is stored\&. If found, it will create a writable environment, using aufs, for Debian like systems to boot from\&. +.sp +You probably do not want to install this package onto a non\-live system, although it will do no harm\&. +.sp +live\-initramfs is a fork of \fIcasper\fR\&[1]\&. casper was originally written by Tollef Fog Heen <tfheen@canonical\&.com> and Matt Zimmerman <mdz@canonical\&.com>\&. +.sp +.SH "BOOT OPTIONS" +Here is the complete list of recognized boot parameters by live\-initramfs\&. +.PP +access=\fBACCESS\fR +.RS 4 +Set the accessibility level for physically or visually impared users\&. ACCESS must be one of v1, v2, v3, m1, or m2\&. v1=lesser visual impairment, v2=moderate visual impairment, v3=blindness, m1=minor motor difficulties, m2=moderate motor difficulties\&. +.RE +.PP +console=\fBTTY,SPEED\fR +.RS 4 +Set the default console to be used with the "live\-getty" option\&. Example: "console=ttyS0,115200" +.RE +.PP +debug +.RS 4 +Makes initramfs boot process more verbose\&. +.RE +.PP +fetch=\fBURL\fR +.RS 4 +Another form of netboot by downloading a squashfs image from a given url, copying to ram and booting it\&. Due to current limitations in busyboxs wget and DNS resolution, an URL can not contain a hostname but an IP only\&. +.RE +Not working: http://example\&.com/path/to/your_filesystem\&.squashfs Working: http://1\&.2\&.3\&.4/path/to/your_filesystem\&.squashfs +.sp +Also note that therefore it\'s currently not possible to fetch an image from a namebased virtualhost of an httpd if it is sharing the ip with the main httpd instance\&. +.PP +hostname=\fBHOSTNAME\fR, username=\fBUSER\fR, userfullname=\fBUSERFULLNAME\fR +.RS 4 +Those parameters lets you override values read from the config file\&. +.sp +.RS 4 +.nf +ignore_uuid +.fi +.RE +.RE +Do not check that any UUID embedded in the initramfs matches the discovered medium\&. live\-initramfs may be told to generate a UUID by setting LIVE_GENERATE_UUID=1 when building the initramfs\&. +.PP +integrity\-check +.RS 4 +If specified, an MD5 sum is calculated on the live media during boot and compared to the value found in md5sum\&.txt found in the root directory of the live media\&. +.RE +.PP +ip=\fB[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF] [,[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF]]\fR* +.RS 4 +Let you specify the name(s) and the options of the interface(s) that should be configured at boot time\&. Do not specify this if you want to use dhcp (default)\&. It will be changed in a future release to mimick official kernel boot param specification (e\&.g\&. ip=10\&.0\&.0\&.1::10\&.0\&.0\&.254:255\&.255\&.255\&.0::eth0,:::::eth1:dhcp)\&. +.RE +.PP +ip=[\fBfrommedia\fR] +.RS 4 +If this variable is set, dhcp and static configuration are just skipped and the system will use the (must be) media\-preconfigured /etc/network/interfaces instead\&. +.RE +.PP +{keyb|kbd\-chooser/method}=\fBKEYBOARD\fR, {klayout|console\-setup/layoutcode}=\fBLAYOUT\fR, {kvariant|console\-setup/variantcode}=\fBVARIANT\fR, {kmodel|console\-setup/modelcode}=\fBCODE\fR, koptions=\fBOPTIONS\fR +.RS 4 +Configure the running keyboard as specified, if this one misses live\-initramfs behaves as if "keyb=us" was specified\&. It will be interfered from "locale=" if locale is only 2 lowecase letters as a special case\&. You could also specify console layout, variant, code, and options (no defaults)\&. +.RE +.PP +live\-getty +.RS 4 +This changes the auto\-login on virtual terminals to use the (experimental) live\-getty code\&. With this option set the standard kernel argument "console=" is parsed and if a serial console is specified then live\-getty is used to autologin on the serial console\&. +.RE +.PP +{live\-media|bootfrom}=\fBDEVICE\fR +.RS 4 +If you specify one of this two equivalent forms, live\-initramfs will first try to find this device for the "/live" directory where the read\-only root filesystem should reside\&. If it did not find something usable, the normal scan for block devices is performed\&. +.RE +Instead of specifing an actual device name, the keyword \fIremovable\fR can be used to limit the search of acceptable live media to removable type only\&. Note that if you want to further restrict the media to usb mass storage only, you can use the \fIremovable\-usb\fR keyword\&. +.PP +{live\-media\-encryption|encryption}=\fBTYPE\fR +.RS 4 +live\-initramfs will mount the encrypted rootfs TYPE, asking the passphrase, useful to build paranoid live systems :\-)\&. TYPE supported so far are "aes" for loop\-aes encryption type\&. +.RE +.PP +live\-media\-offset=\fBBYTES\fR +.RS 4 +This way you could tell live\-initramfs that your image starts at offset BYTES in the above specified or autodiscovered device, this could be useful to hide the Debian Live iso or image inside another iso or image, to create "clean" images\&. +.RE +.PP +live\-media\-path=\fBPATH\fR +.RS 4 +Sets the path to the live filesystem on the medium\&. By default, it is set to +\fI/live\fR +and you should not change that unless you have customized your media accordingly\&. +.RE +.PP +live\-media\-timeout=\fBSECONDS\fR +.RS 4 +Set the timeout in seconds for the device specified by "live\-media=" to become ready before giving up\&. +.RE +.PP +{locale|debian\-installer/locale}=\fBLOCALE\fR +.RS 4 +Configure the running locale as specified, if not present the live\-media rootfs configured locale will be used and if also this one misses live\-initramfs behave as "locale=en_US\&.UTF\-8" was specified\&. If only 2 lowercase letter are specified (like "it"), the "maybe wanted" locale is generated (like en:EN\&.UTF\-8), in this case if also "keyb=" is unspecified is set with those 2 lowercase letters (keyb=us)\&. Beside that facility, only UTF8 locales are supported by live\-initramfs\&. +.RE +.PP +module=\fBNAME\fR +.RS 4 +Instead of using the default optional file "filesystem\&.module" (see below) another file could be specified without the extension "\&.module"; it should be placed on "/live" directory of the live medium\&. +.RE +.PP +netboot[=\fBnfs\fR|\fBcifs\fR] +.RS 4 +This tells live\-initramfs to perform a network mount\&. The parameter "nfsroot=" (with optional "nfsopts="), should specify where is the location of the root filesystem\&. With no args, will try cifs first, and if it fails nfs\&. +.RE +.PP +nfsopts= +.RS 4 +This lets you specify custom nfs options\&. +.RE +.PP +noautologin +.RS 4 +This parameter disables the automatic terminal login only, not touching gdk/kdm\&. +.RE +.PP +noxautologin +.RS 4 +This parameter disables the automatic login of gdm/kdm only, not touching terminals\&. +.RE +.PP +nofastboot +.RS 4 +This parameter disables the default disabling of filesystem checks in /etc/fstab\&. If you have static filesystems on your harddisk and you want them to be checked at boot time, use this parameter, otherwise they are skipped\&. +.RE +.PP +nopersistent +.RS 4 +disables the "persistent" feature, useful if the bootloader (like syslinux) has been installed with persistent enabled\&. +.sp +.RS 4 +.nf +noprompt +.fi +.RE +.RE +Do not prompt to eject the CD on reboot\&. +.PP +nosudo +.RS 4 +This parameter disables the automatic configuration of sudo\&. +.RE +.PP +swapon +.RS 4 +This parameter enables usage of local swap partitions\&. +.RE +.PP +nouser +.RS 4 +This parameter disables the creation of the default user completely\&. +.RE +.PP +noxautoconfig +.RS 4 +This parameter disables Xorg auto\-reconfiguration at boot time\&. This is valuable if you either do the detection on your own, or, if you want to ship a custom, premade xorg\&.conf in your live system\&. +.RE +.PP +persistent[=nofiles] +.RS 4 +live\-initramfs will look for persistent and snapshot partitions or files labeled "live\-rw", "home\-rw", and files called "live\-sn*", "home\-sn*" and will try to, in order: mount as /cow the first, mount the second in /home, and just copy the contents of the latter in appropriate locations (snapshots)\&. Snapshots will be tried to be updated on reboot/shutdown\&. Look at live\-snapshot(1) for more informations\&. If "nofiles" is specified, only filesystems with matching labels will be searched; no filesystems will be traversed looking for archives or image files\&. This results in shorter boot times\&. +.sp +.RS 4 +.nf +persistent\-path=PATH +.fi +.RE +.RE +live\-initramfs will look for persistency files in the root directory of a partition, with this parameter, the path can be configured so that you can have multiple directories on the same partition to store persistency files\&. +.PP +{preseed/file|file}=\fBFILE\fR +.RS 4 +A path to a file present on the rootfs could be used to preseed debconf database\&. +.RE +.PP +package/question=\fBVALUE\fR +.RS 4 +All debian installed packages could be preseeded from command\-line that way, beware of blanks spaces, they will interfere with parsing, use a preseed file in this case\&. +.RE +.PP +quickreboot +.RS 4 +This option causes live\-initramfs to reboot without attempting to eject the media and without asking the user to remove the boot media\&. +.RE +.PP +showmounts +.RS 4 +This parameter will make live\-initramfs to show on "/" the ro filesystems (mostly compressed) on "/live"\&. This is not enabled by default because could lead to problems by applications like "mono" which store binary paths on installation\&. +.sp +.RS 4 +.nf +silent +.fi +.RE +.RE +If you boot with the normal quiet parameter, live\-initramfs hides most messages of its own\&. When adding silent, it hides all\&. +.sp +.sp +.RS 4 +.nf +textonly +.fi +.RE +Start up to text\-mode shell prompts, disabling the graphical user interface\&. +.PP +timezone=\fBTIMEZONE\fR +.RS 4 +By default, timezone is set to UTC\&. Using the timezone parameter, you can set it to your local zone, e\&.g\&. Europe/Zurich\&. +.RE +.PP +todisk=\fBDEVICE\fR +.RS 4 +Adding this parameter, live\-initramfs will try to copy the entire read\-only media to the specified device before mounting the root filesystem\&. It probably needs a lot of free space\&. Subsequent boots should then skip this step and just specify the "live\-media=DEVICE" boot parameter with the same DEVICE used this time\&. +.RE +.PP +toram +.RS 4 +Adding this parameter, live\-initramfs will try to copy the whole read\-only media to the computer\'s RAM before mounting the root filesystem\&. This could need a lot of ram, according to the space used by the read\-only media\&. +.RE +.PP +union=\fBaufs\fR|\fBunionfs\fR +.RS 4 +By default, live\-initramfs uses aufs\&. With this parameter, you can switch to unionfs\&. +.RE +.PP +utc=\fByes\fR|\fBno\fR +.RS 4 +By default, Debian systems do assume that the hardware clock is set to UTC\&. You can change or explicitly set it with this parameter\&. +.RE +.PP +xdebconf +.RS 4 +Uses xdebconfigurator, if present on the rootfs, to configure X instead of the standard procedure (experimental)\&. +.RE +.PP +xvideomode=\fBRESOLUTION\fR +.RS 4 +Doesn\'t do xorg autodetection, but enforces a given resolution\&. +.RE +.SH "FILES" +.sp +.RS 4 +.nf +/etc/live\&.conf +.fi +.RE +Some variables can be configured via this config file (inside the live system)\&. +.sp +.sp +.RS 4 +.nf +/live/filesystem\&.module +.fi +.RE +This optional file (inside the live media) contains a list of white\-space or carriage\-return\-separated file names corresponding to disk images in the "/live" directory\&. If this file exists, only images listed here will be merged into the root aufs, and they will be loaded in the order listed here\&. The first entry in this file will be the "lowest" point in the aufs, and the last file in this list will be on the "top" of the aufs, directly below /cow\&. Without this file, any images in the "/live" directory are loaded in alphanumeric order\&. +.sp +.sp +.RS 4 +.nf +/etc/live\-persistence\&.binds +.fi +.RE +This optional file (which resides in the rootfs system, not in the live media) is used as a list of directories which not need be persistent: ie\&. their content does not need to survive reboots when using the persistence features\&. +.sp +This saves expensive writes and speeds up operations on volatile data such as web caches and temporary files (like e\&.g\&. /tmp and \&.mozilla) which are regenerated each time\&. This is achieved by bind mounting each listed directory with a tmpfs on the original path\&. +.sp +.SH "SEE ALSO" +live\-snapshot(1), initramfs\-tools(8), live\-helper(7), live\-initscripts(7), live\-webhelper(7) +.sp +.SH "BUGS" +Report bugs against live\-initramfs \fIhttp://packages\&.qa\&.debian\&.org/live\-initramfs\fR\&. +.sp +.SH "HOMEPAGE" +More information about the Debian Live project can be found at \fIhttp://debian\-live\&.alioth\&.debian\&.org/\fR and \fIhttp://wiki\&.debian\&.org/DebianLive/\fR\&. +.sp +.SH "AUTHORS" +live\-initramfs is maintained by Daniel Baumann <daniel@debian\&.org> for the Debian project\&. +.sp +live\-initramfs is a fork of \fIcasper\fR\&[1]\&. casper was originally written by Tollef Fog Heen <tfheen@canonical\&.com> and Matt Zimmerman <mdz@canonical\&.com>\&. +.sp +.SH "NOTES" +.IP " 1." 4 +casper +.RS 4 +\%http://packages.ubuntu.com/casper/ +.RE diff --git a/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.html b/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.html new file mode 100644 index 0000000000..5b8379ea60 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.html @@ -0,0 +1,853 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.2.6" />
+<style type="text/css">
+/* Debug borders */
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
+/*
+ border: 1px solid red;
+*/
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+tt {
+ color: navy;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ font-family: sans-serif;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+
+div.sectionbody {
+ font-family: serif;
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+span#author {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+span#email {
+}
+span#revision {
+ font-family: sans-serif;
+}
+
+div#footer {
+ font-family: sans-serif;
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+div#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+div#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+div#preamble,
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-right: 10%;
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.5em;
+ margin-bottom: 2.5em;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+
+div.listingblock {
+ margin-right: 0%;
+}
+div.listingblock > div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock > div.content {
+ padding-left: 2.0em;
+}
+
+div.attribution {
+ text-align: right;
+}
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 2px solid silver;
+}
+
+div.exampleblock > div.content {
+ border-left: 2px solid silver;
+ padding: 0.5em;
+}
+
+div.verseblock div.content {
+ white-space: pre;
+}
+
+div.imageblock div.content { padding-left: 0; }
+div.imageblock img { border: 1px solid silver; }
+span.image img { border-style: none; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+div.olist > ol {
+ list-style-type: decimal;
+}
+div.olist2 > ol {
+ list-style-type: lower-alpha;
+}
+
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead {
+ font-family: sans-serif;
+ font-weight: bold;
+}
+tfoot {
+ font-weight: bold;
+}
+
+div.hlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hlist td {
+ padding-bottom: 15px;
+}
+td.hlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+}
+td.hlist2 {
+ vertical-align: top;
+}
+
+@media print {
+ div#footer-badges { display: none; }
+}
+
+div#toctitle {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+/* Workarounds for IE6's broken and incomplete CSS2. */
+
+div.sidebar-content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+div.sidebar-title, div.image-title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ margin-top: 0.0em;
+ margin-bottom: 0.5em;
+}
+
+div.listingblock div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock-content {
+ padding-left: 2.0em;
+}
+
+div.exampleblock-content {
+ border-left: 2px solid silver;
+ padding-left: 0.5em;
+}
+
+/* IE6 sets dynamically generated links as visited. */
+div#toc a:visited { color: blue; }
+
+/* Because IE6 child selector is broken. */
+div.olist2 ol {
+ list-style-type: lower-alpha;
+}
+div.olist2 div.olist ol {
+ list-style-type: decimal;
+}
+</style>
+<title>live-initramfs(7)</title>
+</head>
+<body>
+<div id="header">
+<h1>live-initramfs(7)</h1>
+</div>
+<h2 id="_name">Name</h2>
+<div class="sectionbody">
+<div class="para"><p>live-initramfs - Debian Live initramfs hook</p></div>
+</div>
+<h2 id="_synopsis">Synopsis</h2>
+<div class="sectionbody">
+<div class="para"><p>BOOT=live</p></div>
+<div class="para"><p>as kernel parameter at boot prompt.</p></div>
+</div>
+<h2 id="_description">Description</h2>
+<div class="sectionbody">
+<div class="para"><p>live-initramfs is a hook for the initramfs-tools, used to generate a initramfs
+capable to boot live systems, such as those created by <strong>live-helper</strong>(7).
+This includes the Debian Live isos, netboot tarballs, and usb stick images.</p></div>
+<div class="para"><p>At boot time it will look for a (read-only) media containing a "/live"
+directory where a root filesystems (often a compressed filesystem image like
+squashfs) is stored. If found, it will create a writable environment, using
+aufs, for Debian like systems to boot from.</p></div>
+<div class="para"><p>You probably do not want to install this package onto a non-live system,
+although it will do no harm.</p></div>
+<div class="para"><p>live-initramfs is a fork of <a href="http://packages.ubuntu.com/casper/">casper</a>.
+casper was originally written by Tollef Fog Heen <tfheen@canonical.com>
+and Matt Zimmerman <mdz@canonical.com>.</p></div>
+</div>
+<h2 id="_boot_options">Boot options</h2>
+<div class="sectionbody">
+<div class="para"><p>Here is the complete list of recognized boot parameters by live-initramfs.</p></div>
+<div class="vlist"><dl>
+<dt>
+access=<strong>ACCESS</strong>
+</dt>
+<dd>
+<p>
+Set the accessibility level for physically or visually impared users. ACCESS
+must be one of v1, v2, v3, m1, or m2. v1=lesser visual impairment, v2=moderate
+visual impairment, v3=blindness, m1=minor motor difficulties, m2=moderate motor
+difficulties.
+</p>
+</dd>
+<dt>
+console=<strong>TTY,SPEED</strong>
+</dt>
+<dd>
+<p>
+Set the default console to be used with the "live-getty" option. Example:
+"console=ttyS0,115200"
+</p>
+</dd>
+<dt>
+debug
+</dt>
+<dd>
+<p>
+Makes initramfs boot process more verbose.
+</p>
+</dd>
+<dt>
+fetch=<strong>URL</strong>
+</dt>
+<dd>
+<p>
+Another form of netboot by downloading a squashfs image from a given url,
+copying to ram and booting it. Due to current limitations in busyboxs wget
+and DNS resolution, an URL can not contain a hostname but an IP only.
+</p>
+</dd>
+</dl></div>
+<div class="para"><p>Not working: http://example.com/path/to/your_filesystem.squashfs
+Working: http://1.2.3.4/path/to/your_filesystem.squashfs</p></div>
+<div class="para"><p>Also note that therefore it's currently not possible to fetch an image from a
+namebased virtualhost of an httpd if it is sharing the ip with the main httpd
+instance.</p></div>
+<div class="vlist"><dl>
+<dt>
+hostname=<strong>HOSTNAME</strong>, username=<strong>USER</strong>, userfullname=<strong>USERFULLNAME</strong>
+</dt>
+<dd>
+<p>
+Those parameters lets you override values read from the config file.
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>ignore_uuid</tt></pre>
+</div></div>
+</dd>
+</dl></div>
+<div class="para"><p>Do not check that any UUID embedded in the initramfs matches the discovered
+medium. live-initramfs may be told to generate a UUID by setting
+LIVE_GENERATE_UUID=1 when building the initramfs.</p></div>
+<div class="vlist"><dl>
+<dt>
+integrity-check
+</dt>
+<dd>
+<p>
+If specified, an MD5 sum is calculated on the live media during boot and
+compared to the value found in md5sum.txt found in the root directory of the
+live media.
+</p>
+</dd>
+<dt>
+ip=<strong>[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF] [,[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF]]</strong>*
+</dt>
+<dd>
+<p>
+Let you specify the name(s) and the options of the interface(s) that should be
+configured at boot time. Do not specify this if you want to use dhcp (default).
+It will be changed in a future release to mimick official kernel boot param
+specification (e.g. ip=10.0.0.1::10.0.0.254:255.255.255.0::eth0,:::::eth1:dhcp).
+</p>
+</dd>
+<dt>
+ip=[<strong>frommedia</strong>]
+</dt>
+<dd>
+<p>
+If this variable is set, dhcp and static configuration are just skipped and the
+system will use the (must be) media-preconfigured /etc/network/interfaces
+instead.
+</p>
+</dd>
+<dt>
+{keyb|kbd-chooser/method}=<strong>KEYBOARD</strong>, {klayout|console-setup/layoutcode}=<strong>LAYOUT</strong>, {kvariant|console-setup/variantcode}=<strong>VARIANT</strong>, {kmodel|console-setup/modelcode}=<strong>CODE</strong>, koptions=<strong>OPTIONS</strong>
+</dt>
+<dd>
+<p>
+Configure the running keyboard as specified, if this one misses live-initramfs
+behaves as if "keyb=us" was specified. It will be interfered from "locale=" if
+locale is only 2 lowecase letters as a special case. You could also specify
+console layout, variant, code, and options (no defaults).
+</p>
+</dd>
+<dt>
+live-getty
+</dt>
+<dd>
+<p>
+This changes the auto-login on virtual terminals to use the (experimental)
+live-getty code. With this option set the standard kernel argument "console=" is
+parsed and if a serial console is specified then live-getty is used to autologin
+on the serial console.
+</p>
+</dd>
+<dt>
+{live-media|bootfrom}=<strong>DEVICE</strong>
+</dt>
+<dd>
+<p>
+If you specify one of this two equivalent forms, live-initramfs will first try
+to find this device for the "/live" directory where the read-only root
+filesystem should reside. If it did not find something usable, the normal scan
+for block devices is performed.
+</p>
+</dd>
+</dl></div>
+<div class="para"><p>Instead of specifing an actual device name, the keyword <em>removable</em> can be used
+to limit the search of acceptable live media to removable type only. Note that
+if you want to further restrict the media to usb mass storage only, you can use
+the <em>removable-usb</em> keyword.</p></div>
+<div class="vlist"><dl>
+<dt>
+{live-media-encryption|encryption}=<strong>TYPE</strong>
+</dt>
+<dd>
+<p>
+live-initramfs will mount the encrypted rootfs TYPE, asking the passphrase,
+useful to build paranoid live systems :-). TYPE supported so far are "aes" for
+loop-aes encryption type.
+</p>
+</dd>
+<dt>
+live-media-offset=<strong>BYTES</strong>
+</dt>
+<dd>
+<p>
+This way you could tell live-initramfs that your image starts at offset BYTES in
+the above specified or autodiscovered device, this could be useful to hide the
+Debian Live iso or image inside another iso or image, to create "clean" images.
+</p>
+</dd>
+<dt>
+live-media-path=<strong>PATH</strong>
+</dt>
+<dd>
+<p>
+Sets the path to the live filesystem on the medium. By default, it is set to
+<em>/live</em> and you should not change that unless you have customized your media
+accordingly.
+</p>
+</dd>
+<dt>
+live-media-timeout=<strong>SECONDS</strong>
+</dt>
+<dd>
+<p>
+Set the timeout in seconds for the device specified by "live-media=" to become
+ready before giving up.
+</p>
+</dd>
+<dt>
+{locale|debian-installer/locale}=<strong>LOCALE</strong>
+</dt>
+<dd>
+<p>
+Configure the running locale as specified, if not present the live-media rootfs
+configured locale will be used and if also this one misses live-initramfs behave
+as "locale=en_US.UTF-8" was specified. If only 2 lowercase letter are specified
+(like "it"), the "maybe wanted" locale is generated (like en:EN.UTF-8), in this
+case if also "keyb=" is unspecified is set with those 2 lowercase letters
+(keyb=us). Beside that facility, only UTF8 locales are supported by
+live-initramfs.
+</p>
+</dd>
+<dt>
+module=<strong>NAME</strong>
+</dt>
+<dd>
+<p>
+Instead of using the default optional file "filesystem.module" (see below)
+another file could be specified without the extension ".module"; it should be
+placed on "/live" directory of the live medium.
+</p>
+</dd>
+<dt>
+netboot[=<strong>nfs</strong>|<strong>cifs</strong>]
+</dt>
+<dd>
+<p>
+This tells live-initramfs to perform a network mount. The parameter "nfsroot="
+(with optional "nfsopts="), should specify where is the location of the root
+filesystem. With no args, will try cifs first, and if it fails nfs.
+</p>
+</dd>
+<dt>
+nfsopts=
+</dt>
+<dd>
+<p>
+This lets you specify custom nfs options.
+</p>
+</dd>
+<dt>
+noautologin
+</dt>
+<dd>
+<p>
+This parameter disables the automatic terminal login only, not touching gdk/kdm.
+</p>
+</dd>
+<dt>
+noxautologin
+</dt>
+<dd>
+<p>
+This parameter disables the automatic login of gdm/kdm only, not touching
+terminals.
+</p>
+</dd>
+<dt>
+nofastboot
+</dt>
+<dd>
+<p>
+This parameter disables the default disabling of filesystem checks in
+/etc/fstab. If you have static filesystems on your harddisk and you want them to
+be checked at boot time, use this parameter, otherwise they are skipped.
+</p>
+</dd>
+<dt>
+nopersistent
+</dt>
+<dd>
+<p>
+disables the "persistent" feature, useful if the bootloader (like syslinux) has
+been installed with persistent enabled.
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>noprompt</tt></pre>
+</div></div>
+</dd>
+</dl></div>
+<div class="para"><p>Do not prompt to eject the CD on reboot.</p></div>
+<div class="vlist"><dl>
+<dt>
+nosudo
+</dt>
+<dd>
+<p>
+This parameter disables the automatic configuration of sudo.
+</p>
+</dd>
+<dt>
+swapon
+</dt>
+<dd>
+<p>
+This parameter enables usage of local swap partitions.
+</p>
+</dd>
+<dt>
+nouser
+</dt>
+<dd>
+<p>
+This parameter disables the creation of the default user completely.
+</p>
+</dd>
+<dt>
+noxautoconfig
+</dt>
+<dd>
+<p>
+This parameter disables Xorg auto-reconfiguration at boot time. This is valuable
+if you either do the detection on your own, or, if you want to ship a custom,
+premade xorg.conf in your live system.
+</p>
+</dd>
+<dt>
+persistent[=nofiles]
+</dt>
+<dd>
+<p>
+live-initramfs will look for persistent and snapshot partitions or files labeled
+"live-rw", "home-rw", and files called "live-sn*", "home-sn*" and will try to,
+in order: mount as /cow the first, mount the second in /home, and just copy the
+contents of the latter in appropriate locations (snapshots). Snapshots will be
+tried to be updated on reboot/shutdown. Look at live-snapshot(1) for more
+informations. If "nofiles" is specified, only filesystems with matching labels
+will be searched; no filesystems will be traversed looking for archives or image
+files. This results in shorter boot times.
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>persistent-path=PATH</tt></pre>
+</div></div>
+</dd>
+</dl></div>
+<div class="para"><p>live-initramfs will look for persistency files in the root directory of a partition,
+with this parameter, the path can be configured so that you can have multiple
+directories on the same partition to store persistency files.</p></div>
+<div class="vlist"><dl>
+<dt>
+{preseed/file|file}=<strong>FILE</strong>
+</dt>
+<dd>
+<p>
+A path to a file present on the rootfs could be used to preseed debconf
+database.
+</p>
+</dd>
+<dt>
+package/question=<strong>VALUE</strong>
+</dt>
+<dd>
+<p>
+All debian installed packages could be preseeded from command-line that way,
+beware of blanks spaces, they will interfere with parsing, use a preseed file in
+this case.
+</p>
+</dd>
+<dt>
+quickreboot
+</dt>
+<dd>
+<p>
+This option causes live-initramfs to reboot without attempting to eject the
+media and without asking the user to remove the boot media.
+</p>
+</dd>
+<dt>
+showmounts
+</dt>
+<dd>
+<p>
+This parameter will make live-initramfs to show on "/" the ro filesystems
+(mostly compressed) on "/live". This is not enabled by default because could
+lead to problems by applications like "mono" which store binary paths on
+installation.
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>silent</tt></pre>
+</div></div>
+</dd>
+</dl></div>
+<div class="para"><p>If you boot with the normal quiet parameter, live-initramfs hides most messages
+of its own. When adding silent, it hides all.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>textonly</tt></pre>
+</div></div>
+<div class="para"><p>Start up to text-mode shell prompts, disabling the graphical user interface.</p></div>
+<div class="vlist"><dl>
+<dt>
+timezone=<strong>TIMEZONE</strong>
+</dt>
+<dd>
+<p>
+By default, timezone is set to UTC. Using the timezone parameter, you can set it
+to your local zone, e.g. Europe/Zurich.
+</p>
+</dd>
+<dt>
+todisk=<strong>DEVICE</strong>
+</dt>
+<dd>
+<p>
+Adding this parameter, live-initramfs will try to copy the entire read-only
+media to the specified device before mounting the root filesystem. It probably
+needs a lot of free space. Subsequent boots should then skip this step and just
+specify the "live-media=DEVICE" boot parameter with the same DEVICE used this
+time.
+</p>
+</dd>
+<dt>
+toram
+</dt>
+<dd>
+<p>
+Adding this parameter, live-initramfs will try to copy the whole read-only media
+to the computer's RAM before mounting the root filesystem. This could need a lot
+of ram, according to the space used by the read-only media.
+</p>
+</dd>
+<dt>
+union=<strong>aufs</strong>|<strong>unionfs</strong>
+</dt>
+<dd>
+<p>
+By default, live-initramfs uses aufs. With this parameter, you can switch to
+unionfs.
+</p>
+</dd>
+<dt>
+utc=<strong>yes</strong>|<strong>no</strong>
+</dt>
+<dd>
+<p>
+By default, Debian systems do assume that the hardware clock is set to UTC. You
+can change or explicitly set it with this parameter.
+</p>
+</dd>
+<dt>
+xdebconf
+</dt>
+<dd>
+<p>
+Uses xdebconfigurator, if present on the rootfs, to configure X instead of the
+standard procedure (experimental).
+</p>
+</dd>
+<dt>
+xvideomode=<strong>RESOLUTION</strong>
+</dt>
+<dd>
+<p>
+Doesn't do xorg autodetection, but enforces a given resolution.
+</p>
+</dd>
+</dl></div>
+</div>
+<h2 id="_files">Files</h2>
+<div class="sectionbody">
+<div class="literalblock">
+<div class="content">
+<pre><tt>/etc/live.conf</tt></pre>
+</div></div>
+<div class="para"><p>Some variables can be configured via this config file (inside the live system).</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>/live/filesystem.module</tt></pre>
+</div></div>
+<div class="para"><p>This optional file (inside the live media) contains a list of white-space or
+carriage-return-separated file names corresponding to disk images in the "/live"
+directory. If this file exists, only images listed here will be merged into the
+root aufs, and they will be loaded in the order listed here. The first entry
+in this file will be the "lowest" point in the aufs, and the last file in
+this list will be on the "top" of the aufs, directly below /cow. Without
+this file, any images in the "/live" directory are loaded in alphanumeric order.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>/etc/live-persistence.binds</tt></pre>
+</div></div>
+<div class="para"><p>This optional file (which resides in the rootfs system, not in the live media)
+is used as a list of directories which not need be persistent: ie. their
+content does not need to survive reboots when using the persistence features.</p></div>
+<div class="para"><p>This saves expensive writes and speeds up operations on volatile data such as
+web caches and temporary files (like e.g. /tmp and .mozilla) which are
+regenerated each time. This is achieved by bind mounting each listed directory
+with a tmpfs on the original path.</p></div>
+</div>
+<h2 id="_see_also">See also</h2>
+<div class="sectionbody">
+<div class="para"><p>live-snapshot(1), initramfs-tools(8), live-helper(7), live-initscripts(7),
+live-webhelper(7)</p></div>
+</div>
+<h2 id="_bugs">Bugs</h2>
+<div class="sectionbody">
+<div class="para"><p>Report bugs against live-initramfs
+<a href="http://packages.qa.debian.org/live-initramfs">http://packages.qa.debian.org/live-initramfs</a>.</p></div>
+</div>
+<h2 id="_homepage">Homepage</h2>
+<div class="sectionbody">
+<div class="para"><p>More information about the Debian Live project can be found at
+<a href="http://debian-live.alioth.debian.org/">http://debian-live.alioth.debian.org/</a> and
+<a href="http://wiki.debian.org/DebianLive/">http://wiki.debian.org/DebianLive/</a>.</p></div>
+</div>
+<h2 id="_authors">Authors</h2>
+<div class="sectionbody">
+<div class="para"><p>live-initramfs is maintained by Daniel Baumann <daniel@debian.org>
+for the Debian project.</p></div>
+<div class="para"><p>live-initramfs is a fork of <a href="http://packages.ubuntu.com/casper/">casper</a>.
+casper was originally written by Tollef Fog Heen <tfheen@canonical.com>
+and Matt Zimmerman <mdz@canonical.com>.</p></div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2009-06-29 14:34:55 CEST
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.txt b/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.txt new file mode 100644 index 0000000000..b7ffa11522 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.txt @@ -0,0 +1,356 @@ +live-initramfs(7) +================= + +Name +---- +live-initramfs - Debian Live initramfs hook + +Synopsis +-------- +BOOT=live + +as kernel parameter at boot prompt. + +Description +----------- + +live-initramfs is a hook for the initramfs-tools, used to generate a initramfs +capable to boot live systems, such as those created by *live-helper*(7). +This includes the Debian Live isos, netboot tarballs, and usb stick images. + +At boot time it will look for a (read-only) media containing a "/live" +directory where a root filesystems (often a compressed filesystem image like +squashfs) is stored. If found, it will create a writable environment, using +aufs, for Debian like systems to boot from. + +You probably do not want to install this package onto a non-live system, +although it will do no harm. + +live-initramfs is a fork of link:http://packages.ubuntu.com/casper/[casper]. +casper was originally written by Tollef Fog Heen <tfheen@canonical.com> +and Matt Zimmerman <mdz@canonical.com>. + +Boot options +------------ + +Here is the complete list of recognized boot parameters by live-initramfs. + + access=*ACCESS*:: + +Set the accessibility level for physically or visually impared users. ACCESS +must be one of v1, v2, v3, m1, or m2. v1=lesser visual impairment, v2=moderate +visual impairment, v3=blindness, m1=minor motor difficulties, m2=moderate motor +difficulties. + + console=*TTY,SPEED*:: + +Set the default console to be used with the "live-getty" option. Example: +"console=ttyS0,115200" + + debug:: + +Makes initramfs boot process more verbose. + + fetch=*URL*:: + +Another form of netboot by downloading a squashfs image from a given url, +copying to ram and booting it. Due to current limitations in busyboxs wget +and DNS resolution, an URL can not contain a hostname but an IP only. + +Not working: http://example.com/path/to/your_filesystem.squashfs +Working: http://1.2.3.4/path/to/your_filesystem.squashfs + +Also note that therefore it's currently not possible to fetch an image from a +namebased virtualhost of an httpd if it is sharing the ip with the main httpd +instance. + + hostname=*HOSTNAME*, username=*USER*, userfullname=*USERFULLNAME*:: + +Those parameters lets you override values read from the config file. + + ignore_uuid + +Do not check that any UUID embedded in the initramfs matches the discovered +medium. live-initramfs may be told to generate a UUID by setting +LIVE_GENERATE_UUID=1 when building the initramfs. + + integrity-check:: + +If specified, an MD5 sum is calculated on the live media during boot and +compared to the value found in md5sum.txt found in the root directory of the +live media. + + ip=**[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF] [,[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF]]***:: + +Let you specify the name(s) and the options of the interface(s) that should be +configured at boot time. Do not specify this if you want to use dhcp (default). +It will be changed in a future release to mimick official kernel boot param +specification (e.g. ip=10.0.0.1::10.0.0.254:255.255.255.0::eth0,:::::eth1:dhcp). + + ip=[**frommedia**]:: + +If this variable is set, dhcp and static configuration are just skipped and the +system will use the (must be) media-preconfigured /etc/network/interfaces +instead. + + {keyb|kbd-chooser/method}=**KEYBOARD**, {klayout|console-setup/layoutcode}=**LAYOUT**, {kvariant|console-setup/variantcode}=**VARIANT**, {kmodel|console-setup/modelcode}=**CODE**, koptions=**OPTIONS**:: + +Configure the running keyboard as specified, if this one misses live-initramfs +behaves as if "keyb=us" was specified. It will be interfered from "locale=" if +locale is only 2 lowecase letters as a special case. You could also specify +console layout, variant, code, and options (no defaults). + + live-getty:: + +This changes the auto-login on virtual terminals to use the (experimental) +live-getty code. With this option set the standard kernel argument "console=" is +parsed and if a serial console is specified then live-getty is used to autologin +on the serial console. + + {live-media|bootfrom}=**DEVICE**:: + +If you specify one of this two equivalent forms, live-initramfs will first try +to find this device for the "/live" directory where the read-only root +filesystem should reside. If it did not find something usable, the normal scan +for block devices is performed. + +Instead of specifing an actual device name, the keyword 'removable' can be used +to limit the search of acceptable live media to removable type only. Note that +if you want to further restrict the media to usb mass storage only, you can use +the 'removable-usb' keyword. + + {live-media-encryption|encryption}=**TYPE**:: + +live-initramfs will mount the encrypted rootfs TYPE, asking the passphrase, +useful to build paranoid live systems :-). TYPE supported so far are "aes" for +loop-aes encryption type. + + live-media-offset=**BYTES**:: + +This way you could tell live-initramfs that your image starts at offset BYTES in +the above specified or autodiscovered device, this could be useful to hide the +Debian Live iso or image inside another iso or image, to create "clean" images. + + live-media-path=**PATH**:: + +Sets the path to the live filesystem on the medium. By default, it is set to +'/live' and you should not change that unless you have customized your media +accordingly. + + live-media-timeout=**SECONDS**:: + +Set the timeout in seconds for the device specified by "live-media=" to become +ready before giving up. + + {locale|debian-installer/locale}=**LOCALE**:: + +Configure the running locale as specified, if not present the live-media rootfs +configured locale will be used and if also this one misses live-initramfs behave +as "locale=en_US.UTF-8" was specified. If only 2 lowercase letter are specified +(like "it"), the "maybe wanted" locale is generated (like en:EN.UTF-8), in this +case if also "keyb=" is unspecified is set with those 2 lowercase letters +(keyb=us). Beside that facility, only UTF8 locales are supported by +live-initramfs. + + module=**NAME**:: + +Instead of using the default optional file "filesystem.module" (see below) +another file could be specified without the extension ".module"; it should be +placed on "/live" directory of the live medium. + + netboot[=**nfs**|**cifs**]:: + +This tells live-initramfs to perform a network mount. The parameter "nfsroot=" +(with optional "nfsopts="), should specify where is the location of the root +filesystem. With no args, will try cifs first, and if it fails nfs. + + nfsopts=:: + +This lets you specify custom nfs options. + + noautologin:: + +This parameter disables the automatic terminal login only, not touching gdk/kdm. + + noxautologin:: + +This parameter disables the automatic login of gdm/kdm only, not touching +terminals. + + nofastboot:: + +This parameter disables the default disabling of filesystem checks in +/etc/fstab. If you have static filesystems on your harddisk and you want them to +be checked at boot time, use this parameter, otherwise they are skipped. + + nopersistent:: + +disables the "persistent" feature, useful if the bootloader (like syslinux) has +been installed with persistent enabled. + + noprompt + +Do not prompt to eject the CD on reboot. + + nosudo:: + +This parameter disables the automatic configuration of sudo. + + swapon:: + +This parameter enables usage of local swap partitions. + + nouser:: + +This parameter disables the creation of the default user completely. + + noxautoconfig:: + +This parameter disables Xorg auto-reconfiguration at boot time. This is valuable +if you either do the detection on your own, or, if you want to ship a custom, +premade xorg.conf in your live system. + + persistent[=nofiles]:: + +live-initramfs will look for persistent and snapshot partitions or files labeled +"live-rw", "home-rw", and files called "live-sn*", "home-sn*" and will try to, +in order: mount as /cow the first, mount the second in /home, and just copy the +contents of the latter in appropriate locations (snapshots). Snapshots will be +tried to be updated on reboot/shutdown. Look at live-snapshot(1) for more +informations. If "nofiles" is specified, only filesystems with matching labels +will be searched; no filesystems will be traversed looking for archives or image +files. This results in shorter boot times. + + persistent-path=PATH + +live-initramfs will look for persistency files in the root directory of a partition, +with this parameter, the path can be configured so that you can have multiple +directories on the same partition to store persistency files. + + {preseed/file|file}=**FILE**:: + +A path to a file present on the rootfs could be used to preseed debconf +database. + + package/question=**VALUE**:: + +All debian installed packages could be preseeded from command-line that way, +beware of blanks spaces, they will interfere with parsing, use a preseed file in +this case. + + quickreboot:: + +This option causes live-initramfs to reboot without attempting to eject the +media and without asking the user to remove the boot media. + + showmounts:: + +This parameter will make live-initramfs to show on "/" the ro filesystems +(mostly compressed) on "/live". This is not enabled by default because could +lead to problems by applications like "mono" which store binary paths on +installation. + + silent + +If you boot with the normal quiet parameter, live-initramfs hides most messages +of its own. When adding silent, it hides all. + + textonly + +Start up to text-mode shell prompts, disabling the graphical user interface. + + timezone=**TIMEZONE**:: + +By default, timezone is set to UTC. Using the timezone parameter, you can set it +to your local zone, e.g. Europe/Zurich. + + todisk=**DEVICE**:: + +Adding this parameter, live-initramfs will try to copy the entire read-only +media to the specified device before mounting the root filesystem. It probably +needs a lot of free space. Subsequent boots should then skip this step and just +specify the "live-media=DEVICE" boot parameter with the same DEVICE used this +time. + + toram:: + +Adding this parameter, live-initramfs will try to copy the whole read-only media +to the computer's RAM before mounting the root filesystem. This could need a lot +of ram, according to the space used by the read-only media. + + union=**aufs**|**unionfs**:: + +By default, live-initramfs uses aufs. With this parameter, you can switch to +unionfs. + + utc=**yes**|**no**:: + +By default, Debian systems do assume that the hardware clock is set to UTC. You +can change or explicitly set it with this parameter. + + xdebconf:: + +Uses xdebconfigurator, if present on the rootfs, to configure X instead of the +standard procedure (experimental). + + xvideomode=**RESOLUTION**:: + +Doesn't do xorg autodetection, but enforces a given resolution. + +Files +----- + + /etc/live.conf + +Some variables can be configured via this config file (inside the live system). + + /live/filesystem.module + +This optional file (inside the live media) contains a list of white-space or +carriage-return-separated file names corresponding to disk images in the "/live" +directory. If this file exists, only images listed here will be merged into the +root aufs, and they will be loaded in the order listed here. The first entry +in this file will be the "lowest" point in the aufs, and the last file in +this list will be on the "top" of the aufs, directly below /cow. Without +this file, any images in the "/live" directory are loaded in alphanumeric order. + + /etc/live-persistence.binds + +This optional file (which resides in the rootfs system, not in the live media) +is used as a list of directories which not need be persistent: ie. their +content does not need to survive reboots when using the persistence features. + +This saves expensive writes and speeds up operations on volatile data such as +web caches and temporary files (like e.g. /tmp and .mozilla) which are +regenerated each time. This is achieved by bind mounting each listed directory +with a tmpfs on the original path. + + +See also +-------- + +live-snapshot(1), initramfs-tools(8), live-helper(7), live-initscripts(7), +live-webhelper(7) + +Bugs +---- + +Report bugs against live-initramfs +link:http://packages.qa.debian.org/live-initramfs[http://packages.qa.debian.org/live-initramfs]. + +Homepage +-------- + +More information about the Debian Live project can be found at +link:http://debian-live.alioth.debian.org/[http://debian-live.alioth.debian.org/] and +link:http://wiki.debian.org/DebianLive/[http://wiki.debian.org/DebianLive/]. + +Authors +------- + +live-initramfs is maintained by Daniel Baumann <daniel@debian.org> +for the Debian project. + +live-initramfs is a fork of link:http://packages.ubuntu.com/casper/[casper]. +casper was originally written by Tollef Fog Heen <tfheen@canonical.com> +and Matt Zimmerman <mdz@canonical.com>. diff --git a/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.xml b/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.xml new file mode 100644 index 0000000000..5ef1d386da --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-initramfs.en.7.xml @@ -0,0 +1,601 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<refentry lang="en">
+<refmeta>
+<refentrytitle>live-initramfs</refentrytitle>
+<manvolnum>7</manvolnum>
+</refmeta>
+<refnamediv>
+ <refname>live-initramfs</refname>
+ <refpurpose>Debian Live initramfs hook</refpurpose>
+</refnamediv>
+<refsynopsisdiv>
+<simpara>BOOT=live</simpara>
+
+<simpara>as kernel parameter at boot prompt.</simpara>
+
+</refsynopsisdiv>
+<refsect1 id="_description">
+<title>Description</title>
+<simpara>live-initramfs is a hook for the initramfs-tools, used to generate a initramfs
+capable to boot live systems, such as those created by <emphasis role="strong">live-helper</emphasis>(7).
+This includes the Debian Live isos, netboot tarballs, and usb stick images.</simpara>
+
+<simpara>At boot time it will look for a (read-only) media containing a "/live"
+directory where a root filesystems (often a compressed filesystem image like
+squashfs) is stored. If found, it will create a writable environment, using
+aufs, for Debian like systems to boot from.</simpara>
+
+<simpara>You probably do not want to install this package onto a non-live system,
+although it will do no harm.</simpara>
+
+<simpara>live-initramfs is a fork of <ulink url="http://packages.ubuntu.com/casper/">casper</ulink>.
+casper was originally written by Tollef Fog Heen <tfheen@canonical.com>
+and Matt Zimmerman <mdz@canonical.com>.</simpara>
+
+</refsect1>
+<refsect1 id="_boot_options">
+<title>Boot options</title>
+<simpara>Here is the complete list of recognized boot parameters by live-initramfs.</simpara>
+
+<variablelist>
+<varlistentry>
+<term>
+access=<emphasis role="strong">ACCESS</emphasis>
+</term>
+<listitem>
+<simpara>
+Set the accessibility level for physically or visually impared users. ACCESS
+must be one of v1, v2, v3, m1, or m2. v1=lesser visual impairment, v2=moderate
+visual impairment, v3=blindness, m1=minor motor difficulties, m2=moderate motor
+difficulties.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+console=<emphasis role="strong">TTY,SPEED</emphasis>
+</term>
+<listitem>
+<simpara>
+Set the default console to be used with the "live-getty" option. Example:
+"console=ttyS0,115200"
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+debug
+</term>
+<listitem>
+<simpara>
+Makes initramfs boot process more verbose.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+fetch=<emphasis role="strong">URL</emphasis>
+</term>
+<listitem>
+<simpara>
+Another form of netboot by downloading a squashfs image from a given url,
+copying to ram and booting it. Due to current limitations in busyboxs wget
+and DNS resolution, an URL can not contain a hostname but an IP only.
+</simpara>
+</listitem>
+</varlistentry>
+</variablelist>
+<simpara>Not working: http://example.com/path/to/your_filesystem.squashfs
+Working: http://1.2.3.4/path/to/your_filesystem.squashfs</simpara>
+
+<simpara>Also note that therefore it's currently not possible to fetch an image from a
+namebased virtualhost of an httpd if it is sharing the ip with the main httpd
+instance.</simpara>
+
+<variablelist>
+<varlistentry>
+<term>
+hostname=<emphasis role="strong">HOSTNAME</emphasis>, username=<emphasis role="strong">USER</emphasis>, userfullname=<emphasis role="strong">USERFULLNAME</emphasis>
+</term>
+<listitem>
+<simpara>
+Those parameters lets you override values read from the config file.
+</simpara>
+<literallayout class="monospaced">ignore_uuid</literallayout>
+</listitem>
+</varlistentry>
+</variablelist>
+<simpara>Do not check that any UUID embedded in the initramfs matches the discovered
+medium. live-initramfs may be told to generate a UUID by setting
+LIVE_GENERATE_UUID=1 when building the initramfs.</simpara>
+
+<variablelist>
+<varlistentry>
+<term>
+integrity-check
+</term>
+<listitem>
+<simpara>
+If specified, an MD5 sum is calculated on the live media during boot and
+compared to the value found in md5sum.txt found in the root directory of the
+live media.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ip=<emphasis role="strong">[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF] [,[CLIENT_IP]:[SERVER_IP]:[GATEWAY_IP]:[NETMASK]:[HOSTNAME]:[DEVICE]:[AUTOCONF]]</emphasis>*
+</term>
+<listitem>
+<simpara>
+Let you specify the name(s) and the options of the interface(s) that should be
+configured at boot time. Do not specify this if you want to use dhcp (default).
+It will be changed in a future release to mimick official kernel boot param
+specification (e.g. ip=10.0.0.1::10.0.0.254:255.255.255.0::eth0,:::::eth1:dhcp).
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ip=[<emphasis role="strong">frommedia</emphasis>]
+</term>
+<listitem>
+<simpara>
+If this variable is set, dhcp and static configuration are just skipped and the
+system will use the (must be) media-preconfigured /etc/network/interfaces
+instead.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+{keyb|kbd-chooser/method}=<emphasis role="strong">KEYBOARD</emphasis>, {klayout|console-setup/layoutcode}=<emphasis role="strong">LAYOUT</emphasis>, {kvariant|console-setup/variantcode}=<emphasis role="strong">VARIANT</emphasis>, {kmodel|console-setup/modelcode}=<emphasis role="strong">CODE</emphasis>, koptions=<emphasis role="strong">OPTIONS</emphasis>
+</term>
+<listitem>
+<simpara>
+Configure the running keyboard as specified, if this one misses live-initramfs
+behaves as if "keyb=us" was specified. It will be interfered from "locale=" if
+locale is only 2 lowecase letters as a special case. You could also specify
+console layout, variant, code, and options (no defaults).
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+live-getty
+</term>
+<listitem>
+<simpara>
+This changes the auto-login on virtual terminals to use the (experimental)
+live-getty code. With this option set the standard kernel argument "console=" is
+parsed and if a serial console is specified then live-getty is used to autologin
+on the serial console.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+{live-media|bootfrom}=<emphasis role="strong">DEVICE</emphasis>
+</term>
+<listitem>
+<simpara>
+If you specify one of this two equivalent forms, live-initramfs will first try
+to find this device for the "/live" directory where the read-only root
+filesystem should reside. If it did not find something usable, the normal scan
+for block devices is performed.
+</simpara>
+</listitem>
+</varlistentry>
+</variablelist>
+<simpara>Instead of specifing an actual device name, the keyword <emphasis>removable</emphasis> can be used
+to limit the search of acceptable live media to removable type only. Note that
+if you want to further restrict the media to usb mass storage only, you can use
+the <emphasis>removable-usb</emphasis> keyword.</simpara>
+
+<variablelist>
+<varlistentry>
+<term>
+{live-media-encryption|encryption}=<emphasis role="strong">TYPE</emphasis>
+</term>
+<listitem>
+<simpara>
+live-initramfs will mount the encrypted rootfs TYPE, asking the passphrase,
+useful to build paranoid live systems :-). TYPE supported so far are "aes" for
+loop-aes encryption type.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+live-media-offset=<emphasis role="strong">BYTES</emphasis>
+</term>
+<listitem>
+<simpara>
+This way you could tell live-initramfs that your image starts at offset BYTES in
+the above specified or autodiscovered device, this could be useful to hide the
+Debian Live iso or image inside another iso or image, to create "clean" images.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+live-media-path=<emphasis role="strong">PATH</emphasis>
+</term>
+<listitem>
+<simpara>
+Sets the path to the live filesystem on the medium. By default, it is set to
+<emphasis>/live</emphasis> and you should not change that unless you have customized your media
+accordingly.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+live-media-timeout=<emphasis role="strong">SECONDS</emphasis>
+</term>
+<listitem>
+<simpara>
+Set the timeout in seconds for the device specified by "live-media=" to become
+ready before giving up.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+{locale|debian-installer/locale}=<emphasis role="strong">LOCALE</emphasis>
+</term>
+<listitem>
+<simpara>
+Configure the running locale as specified, if not present the live-media rootfs
+configured locale will be used and if also this one misses live-initramfs behave
+as "locale=en_US.UTF-8" was specified. If only 2 lowercase letter are specified
+(like "it"), the "maybe wanted" locale is generated (like en:EN.UTF-8), in this
+case if also "keyb=" is unspecified is set with those 2 lowercase letters
+(keyb=us). Beside that facility, only UTF8 locales are supported by
+live-initramfs.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+module=<emphasis role="strong">NAME</emphasis>
+</term>
+<listitem>
+<simpara>
+Instead of using the default optional file "filesystem.module" (see below)
+another file could be specified without the extension ".module"; it should be
+placed on "/live" directory of the live medium.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+netboot[=<emphasis role="strong">nfs</emphasis>|<emphasis role="strong">cifs</emphasis>]
+</term>
+<listitem>
+<simpara>
+This tells live-initramfs to perform a network mount. The parameter "nfsroot="
+(with optional "nfsopts="), should specify where is the location of the root
+filesystem. With no args, will try cifs first, and if it fails nfs.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+nfsopts=
+</term>
+<listitem>
+<simpara>
+This lets you specify custom nfs options.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+noautologin
+</term>
+<listitem>
+<simpara>
+This parameter disables the automatic terminal login only, not touching gdk/kdm.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+noxautologin
+</term>
+<listitem>
+<simpara>
+This parameter disables the automatic login of gdm/kdm only, not touching
+terminals.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+nofastboot
+</term>
+<listitem>
+<simpara>
+This parameter disables the default disabling of filesystem checks in
+/etc/fstab. If you have static filesystems on your harddisk and you want them to
+be checked at boot time, use this parameter, otherwise they are skipped.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+nopersistent
+</term>
+<listitem>
+<simpara>
+disables the "persistent" feature, useful if the bootloader (like syslinux) has
+been installed with persistent enabled.
+</simpara>
+<literallayout class="monospaced">noprompt</literallayout>
+</listitem>
+</varlistentry>
+</variablelist>
+<simpara>Do not prompt to eject the CD on reboot.</simpara>
+
+<variablelist>
+<varlistentry>
+<term>
+nosudo
+</term>
+<listitem>
+<simpara>
+This parameter disables the automatic configuration of sudo.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+swapon
+</term>
+<listitem>
+<simpara>
+This parameter enables usage of local swap partitions.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+nouser
+</term>
+<listitem>
+<simpara>
+This parameter disables the creation of the default user completely.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+noxautoconfig
+</term>
+<listitem>
+<simpara>
+This parameter disables Xorg auto-reconfiguration at boot time. This is valuable
+if you either do the detection on your own, or, if you want to ship a custom,
+premade xorg.conf in your live system.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+persistent[=nofiles]
+</term>
+<listitem>
+<simpara>
+live-initramfs will look for persistent and snapshot partitions or files labeled
+"live-rw", "home-rw", and files called "live-sn*", "home-sn*" and will try to,
+in order: mount as /cow the first, mount the second in /home, and just copy the
+contents of the latter in appropriate locations (snapshots). Snapshots will be
+tried to be updated on reboot/shutdown. Look at live-snapshot(1) for more
+informations. If "nofiles" is specified, only filesystems with matching labels
+will be searched; no filesystems will be traversed looking for archives or image
+files. This results in shorter boot times.
+</simpara>
+<literallayout class="monospaced">persistent-path=PATH</literallayout>
+</listitem>
+</varlistentry>
+</variablelist>
+<simpara>live-initramfs will look for persistency files in the root directory of a partition,
+with this parameter, the path can be configured so that you can have multiple
+directories on the same partition to store persistency files.</simpara>
+
+<variablelist>
+<varlistentry>
+<term>
+{preseed/file|file}=<emphasis role="strong">FILE</emphasis>
+</term>
+<listitem>
+<simpara>
+A path to a file present on the rootfs could be used to preseed debconf
+database.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+package/question=<emphasis role="strong">VALUE</emphasis>
+</term>
+<listitem>
+<simpara>
+All debian installed packages could be preseeded from command-line that way,
+beware of blanks spaces, they will interfere with parsing, use a preseed file in
+this case.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+quickreboot
+</term>
+<listitem>
+<simpara>
+This option causes live-initramfs to reboot without attempting to eject the
+media and without asking the user to remove the boot media.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+showmounts
+</term>
+<listitem>
+<simpara>
+This parameter will make live-initramfs to show on "/" the ro filesystems
+(mostly compressed) on "/live". This is not enabled by default because could
+lead to problems by applications like "mono" which store binary paths on
+installation.
+</simpara>
+<literallayout class="monospaced">silent</literallayout>
+</listitem>
+</varlistentry>
+</variablelist>
+<simpara>If you boot with the normal quiet parameter, live-initramfs hides most messages
+of its own. When adding silent, it hides all.</simpara>
+
+<literallayout class="monospaced">textonly</literallayout>
+<simpara>Start up to text-mode shell prompts, disabling the graphical user interface.</simpara>
+
+<variablelist>
+<varlistentry>
+<term>
+timezone=<emphasis role="strong">TIMEZONE</emphasis>
+</term>
+<listitem>
+<simpara>
+By default, timezone is set to UTC. Using the timezone parameter, you can set it
+to your local zone, e.g. Europe/Zurich.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+todisk=<emphasis role="strong">DEVICE</emphasis>
+</term>
+<listitem>
+<simpara>
+Adding this parameter, live-initramfs will try to copy the entire read-only
+media to the specified device before mounting the root filesystem. It probably
+needs a lot of free space. Subsequent boots should then skip this step and just
+specify the "live-media=DEVICE" boot parameter with the same DEVICE used this
+time.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+toram
+</term>
+<listitem>
+<simpara>
+Adding this parameter, live-initramfs will try to copy the whole read-only media
+to the computer's RAM before mounting the root filesystem. This could need a lot
+of ram, according to the space used by the read-only media.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+union=<emphasis role="strong">aufs</emphasis>|<emphasis role="strong">unionfs</emphasis>
+</term>
+<listitem>
+<simpara>
+By default, live-initramfs uses aufs. With this parameter, you can switch to
+unionfs.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+utc=<emphasis role="strong">yes</emphasis>|<emphasis role="strong">no</emphasis>
+</term>
+<listitem>
+<simpara>
+By default, Debian systems do assume that the hardware clock is set to UTC. You
+can change or explicitly set it with this parameter.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+xdebconf
+</term>
+<listitem>
+<simpara>
+Uses xdebconfigurator, if present on the rootfs, to configure X instead of the
+standard procedure (experimental).
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+xvideomode=<emphasis role="strong">RESOLUTION</emphasis>
+</term>
+<listitem>
+<simpara>
+Doesn't do xorg autodetection, but enforces a given resolution.
+</simpara>
+</listitem>
+</varlistentry>
+</variablelist>
+</refsect1>
+<refsect1 id="_files">
+<title>Files</title>
+<literallayout class="monospaced">/etc/live.conf</literallayout>
+<simpara>Some variables can be configured via this config file (inside the live system).</simpara>
+
+<literallayout class="monospaced">/live/filesystem.module</literallayout>
+<simpara>This optional file (inside the live media) contains a list of white-space or
+carriage-return-separated file names corresponding to disk images in the "/live"
+directory. If this file exists, only images listed here will be merged into the
+root aufs, and they will be loaded in the order listed here. The first entry
+in this file will be the "lowest" point in the aufs, and the last file in
+this list will be on the "top" of the aufs, directly below /cow. Without
+this file, any images in the "/live" directory are loaded in alphanumeric order.</simpara>
+
+<literallayout class="monospaced">/etc/live-persistence.binds</literallayout>
+<simpara>This optional file (which resides in the rootfs system, not in the live media)
+is used as a list of directories which not need be persistent: ie. their
+content does not need to survive reboots when using the persistence features.</simpara>
+
+<simpara>This saves expensive writes and speeds up operations on volatile data such as
+web caches and temporary files (like e.g. /tmp and .mozilla) which are
+regenerated each time. This is achieved by bind mounting each listed directory
+with a tmpfs on the original path.</simpara>
+
+</refsect1>
+<refsect1 id="_see_also">
+<title>See also</title>
+<simpara>live-snapshot(1), initramfs-tools(8), live-helper(7), live-initscripts(7),
+live-webhelper(7)</simpara>
+
+</refsect1>
+<refsect1 id="_bugs">
+<title>Bugs</title>
+<simpara>Report bugs against live-initramfs
+<ulink url="http://packages.qa.debian.org/live-initramfs">http://packages.qa.debian.org/live-initramfs</ulink>.</simpara>
+
+</refsect1>
+<refsect1 id="_homepage">
+<title>Homepage</title>
+<simpara>More information about the Debian Live project can be found at
+<ulink url="http://debian-live.alioth.debian.org/">http://debian-live.alioth.debian.org/</ulink> and
+<ulink url="http://wiki.debian.org/DebianLive/">http://wiki.debian.org/DebianLive/</ulink>.</simpara>
+
+</refsect1>
+<refsect1 id="_authors">
+<title>Authors</title>
+<simpara>live-initramfs is maintained by Daniel Baumann <daniel@debian.org>
+for the Debian project.</simpara>
+
+<simpara>live-initramfs is a fork of <ulink url="http://packages.ubuntu.com/casper/">casper</ulink>.
+casper was originally written by Tollef Fog Heen <tfheen@canonical.com>
+and Matt Zimmerman <mdz@canonical.com>.</simpara>
+
+</refsect1>
+</refentry>
diff --git a/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1 b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1 new file mode 100644 index 0000000000..4bc99b5219 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1 @@ -0,0 +1,116 @@ +.\" Title: live-snapshot +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 <http://docbook.sf.net/> +.\" Date: 06/29/2009 +.\" Manual: +.\" Source: +.\" +.TH "LIVE\-SNAPSHOT" "1" "06/29/2009" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +live-snapshot \- a simple script to ease persistence usage +.SH "SYNOPSIS" +live\-snapshot [\-c|\-\-cow \fBDIRECTORY\fRs] [\-d|\-\-device \fBDEVICE\fR] [\-e|\-\-exclude\-list \fBFILE\fR] [\-o|\-\-output \fBFILE\fR] [\-t|\-\-type \fBTYPE\fR] +.sp +live\-snapshot [\-r|\-\-resync\-string \fBSTRING\fR] +.sp +live\-snapshot [\-h|\-\-help] +.sp +live\-snapshot [\-u|\-\-usage] +.sp +live\-snapshot [\-v|\-\-version] +.sp +.SH "DESCRIPTION" +live\-snapshot is a script which can be used to build the right types of persistent image files supported by live\-initramfs(7)\&. It is also used on exit by the live\-initramfs init script to resync the boot\-found snapshots devices\&. +.sp +.SH "OPTIONS" +.PP +\-c, \-\-cow \fBDIRECTORY\fR +.RS 4 +specifies the input directory to be cloned in the image file\&. Its default value "/live/cow" should be right for most uses\&. However it could be handy to specify "/home" and type ext2 for the type to prepare an image file suited to be directly mounted by live\-initramfs as home\&. +.RE +.PP +\-d, \-\-device \fBDEVICE\fR +.RS 4 +sets the device where the media which the snapshot/persistence file/partition will be put\&. If it is not specified, a tmpfs will be used and linked to the user\'s desktop to move it where it is needed\&. If the device has no filesystem, an ext2 fs will be automatically created and labelled according to the values specified after the "\-\-output" value or with a sane default\&. +.RE +.PP +\-e, \-\-exclude\-list \fBFILE\fR +.RS 4 +a file containing a list of filenames/paths that should not be saved\&. This exclude list will be remebered on the target snapshot media for reuse\&. +.RE +.PP +\-o, \-\-output \fBFILE\fR +.RS 4 +the filename/label used for the output file/partition\&. If left blank, live\-snapshot will search for a proper file on the device or use the whole partition\&. +.RE +.PP +\-r, \-\-resync\-string \fBSTRING\fR +.RS 4 +internally used on resyncs\&. +.RE +.PP +\-f, \-\-refresh +.RS 4 +try to do the same operation that should be done at reboot or halt, resyncing boot\-time auto discovered snapshots\&. Useful to prevent a crash or surge power\-off\&. +.RE +.PP +\-t, \-\-type \fBTYPE\fR +.RS 4 +Type could be one of "cpio", "squashfs", "ext2", "ext3", "ext4", or "jffs2"\&. +.RE +.PP +\-h, \-\-help +.RS 4 +display help and exit +.RE +.PP +\-u, \-\-usage +.RS 4 +show usage and exit +.RE +.PP +\-v, \-\-version +.RS 4 +output version information and exit +.RE +.SH "FILES" +.sp +.RS 4 +.nf +/etc/live\-snapshot\&.list +.fi +.RE +This optional file, if present changes the behaviour of live\-snapshot, only files and directories listed there are included (integrally) in the snapshot\&. It works only for cpio and whole partition targets\&. +.sp +.sp +.RS 4 +.nf +/etc/live\-snapshot\&.exclude_list +.fi +.RE +This optional file, if present will filter the files that will be saved by live\-snapshot removing (as in "grep \-F \-v") all filenames that will be matched by strings listed in it\&. It works for cpio, whole partition and squashfs snapshot types only; it is pretty useful for filtering temporary files and disk caches\&. +.sp +.SH "SEE ALSO" +live\-initramfs(8) +.sp +This program is a part of live\-initramfs\&. +.sp +.SH "BUGS" +Report bugs against live\-initramfs \fIhttp://packages\&.qa\&.debian\&.org/live\-initramfs\fR\&. +.sp +.SH "HOMEPAGE" +More information about the Debian Live project can be found at \fIhttp://debian\-live\&.alioth\&.debian\&.org/\fR and \fIhttp://wiki\&.debian\&.org/DebianLive/\fR\&. +.sp +.SH "AUTHORS" +live\-initramfs is maintained by Daniel Baumann <daniel@debian\&.org> for the Debian project\&. live\-initramfs is a fork of \fIcasper\fR\&[1]\&. casper was originally written by Tollef Fog Heen <tfheen@canonical\&.com> and Matt Zimmerman <mdz@canonical\&.com>\&. +.sp +.SH "NOTES" +.IP " 1." 4 +casper +.RS 4 +\%http://packages.ubuntu.com/casper/ +.RE diff --git a/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.html b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.html new file mode 100644 index 0000000000..f40b94aa75 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.html @@ -0,0 +1,487 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.2.6" />
+<style type="text/css">
+/* Debug borders */
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
+/*
+ border: 1px solid red;
+*/
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+tt {
+ color: navy;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ font-family: sans-serif;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+
+div.sectionbody {
+ font-family: serif;
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+span#author {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+span#email {
+}
+span#revision {
+ font-family: sans-serif;
+}
+
+div#footer {
+ font-family: sans-serif;
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+div#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+div#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+div#preamble,
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-right: 10%;
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.5em;
+ margin-bottom: 2.5em;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+
+div.listingblock {
+ margin-right: 0%;
+}
+div.listingblock > div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock > div.content {
+ padding-left: 2.0em;
+}
+
+div.attribution {
+ text-align: right;
+}
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 2px solid silver;
+}
+
+div.exampleblock > div.content {
+ border-left: 2px solid silver;
+ padding: 0.5em;
+}
+
+div.verseblock div.content {
+ white-space: pre;
+}
+
+div.imageblock div.content { padding-left: 0; }
+div.imageblock img { border: 1px solid silver; }
+span.image img { border-style: none; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+div.olist > ol {
+ list-style-type: decimal;
+}
+div.olist2 > ol {
+ list-style-type: lower-alpha;
+}
+
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead {
+ font-family: sans-serif;
+ font-weight: bold;
+}
+tfoot {
+ font-weight: bold;
+}
+
+div.hlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hlist td {
+ padding-bottom: 15px;
+}
+td.hlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+}
+td.hlist2 {
+ vertical-align: top;
+}
+
+@media print {
+ div#footer-badges { display: none; }
+}
+
+div#toctitle {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+/* Workarounds for IE6's broken and incomplete CSS2. */
+
+div.sidebar-content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+div.sidebar-title, div.image-title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ margin-top: 0.0em;
+ margin-bottom: 0.5em;
+}
+
+div.listingblock div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock-content {
+ padding-left: 2.0em;
+}
+
+div.exampleblock-content {
+ border-left: 2px solid silver;
+ padding-left: 0.5em;
+}
+
+/* IE6 sets dynamically generated links as visited. */
+div#toc a:visited { color: blue; }
+
+/* Because IE6 child selector is broken. */
+div.olist2 ol {
+ list-style-type: lower-alpha;
+}
+div.olist2 div.olist ol {
+ list-style-type: decimal;
+}
+</style>
+<title>live-snapshot(1)</title>
+</head>
+<body>
+<div id="header">
+<h1>live-snapshot(1)</h1>
+</div>
+<h2 id="_name">Name</h2>
+<div class="sectionbody">
+<div class="para"><p>live-snapshot - a simple script to ease persistence usage</p></div>
+</div>
+<h2 id="_synopsis">Synopsis</h2>
+<div class="sectionbody">
+<div class="para"><p>live-snapshot [-c|—cow <strong>DIRECTORY</strong>s] [-d|—device <strong>DEVICE</strong>] [-e|—exclude-list <strong>FILE</strong>] [-o|—output <strong>FILE</strong>] [-t|—type <strong>TYPE</strong>]</p></div>
+<div class="para"><p>live-snapshot [-r|—resync-string <strong>STRING</strong>]</p></div>
+<div class="para"><p>live-snapshot [-h|—help]</p></div>
+<div class="para"><p>live-snapshot [-u|—usage]</p></div>
+<div class="para"><p>live-snapshot [-v|—version]</p></div>
+</div>
+<h2 id="_description">Description</h2>
+<div class="sectionbody">
+<div class="para"><p>live-snapshot is a script which can be used to build the right types of
+persistent image files supported by live-initramfs(7). It is also used on
+exit by the live-initramfs init script to resync the boot-found snapshots
+devices.</p></div>
+</div>
+<h2 id="_options">Options</h2>
+<div class="sectionbody">
+<div class="vlist"><dl>
+<dt>
+-c, —cow <strong>DIRECTORY</strong>
+</dt>
+<dd>
+<p>
+specifies the input directory to be cloned in the image file. Its default value
+"/live/cow" should be right for most uses. However it could be handy to specify
+"/home" and type ext2 for the type to prepare an image file suited to be
+directly mounted by live-initramfs as home.
+</p>
+</dd>
+<dt>
+-d, —device <strong>DEVICE</strong>
+</dt>
+<dd>
+<p>
+sets the device where the media which the snapshot/persistence file/partition
+will be put. If it is not specified, a tmpfs will be used and linked to the
+user's desktop to move it where it is needed. If the device has no filesystem,
+an ext2 fs will be automatically created and labelled according to the values
+specified after the "—output" value or with a sane default.
+</p>
+</dd>
+<dt>
+-e, —exclude-list <strong>FILE</strong>
+</dt>
+<dd>
+<p>
+a file containing a list of filenames/paths that should not be saved. This exclude list will be remebered on the target snapshot media for reuse.
+</p>
+</dd>
+<dt>
+-o, —output <strong>FILE</strong>
+</dt>
+<dd>
+<p>
+the filename/label used for the output file/partition. If left blank, live-snapshot will search for a proper file on the device or use the whole partition.
+</p>
+</dd>
+<dt>
+-r, —resync-string <strong>STRING</strong>
+</dt>
+<dd>
+<p>
+internally used on resyncs.
+</p>
+</dd>
+<dt>
+-f, —refresh
+</dt>
+<dd>
+<p>
+try to do the same operation that should be done at reboot or halt, resyncing
+boot-time auto discovered snapshots. Useful to prevent a crash or surge
+power-off.
+</p>
+</dd>
+<dt>
+-t, —type <strong>TYPE</strong>
+</dt>
+<dd>
+<p>
+Type could be one of "cpio", "squashfs", "ext2", "ext3", "ext4", or "jffs2".
+</p>
+</dd>
+<dt>
+-h, —help
+</dt>
+<dd>
+<p>
+display help and exit
+</p>
+</dd>
+<dt>
+-u, —usage
+</dt>
+<dd>
+<p>
+show usage and exit
+</p>
+</dd>
+<dt>
+-v, —version
+</dt>
+<dd>
+<p>
+output version information and exit
+</p>
+</dd>
+</dl></div>
+</div>
+<h2 id="_files">Files</h2>
+<div class="sectionbody">
+<div class="literalblock">
+<div class="content">
+<pre><tt>/etc/live-snapshot.list</tt></pre>
+</div></div>
+<div class="para"><p>This optional file, if present changes the behaviour of live-snapshot, only files and directories listed there are included (integrally) in the snapshot. It works only for cpio and whole partition targets.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>/etc/live-snapshot.exclude_list</tt></pre>
+</div></div>
+<div class="para"><p>This optional file, if present will filter the files that will be saved by live-snapshot removing (as in "grep -F -v") all filenames that will be matched by strings listed in it.
+It works for cpio, whole partition and squashfs snapshot types only; it is pretty useful for filtering temporary files and disk caches.</p></div>
+</div>
+<h2 id="_see_also">See also</h2>
+<div class="sectionbody">
+<div class="para"><p>live-initramfs(8)</p></div>
+<div class="para"><p>This program is a part of live-initramfs.</p></div>
+</div>
+<h2 id="_bugs">Bugs</h2>
+<div class="sectionbody">
+<div class="para"><p>Report bugs against live-initramfs
+<a href="http://packages.qa.debian.org/live-initramfs">http://packages.qa.debian.org/live-initramfs</a>.</p></div>
+</div>
+<h2 id="_homepage">Homepage</h2>
+<div class="sectionbody">
+<div class="para"><p>More information about the Debian Live project can be found at
+<a href="http://debian-live.alioth.debian.org/">http://debian-live.alioth.debian.org/</a> and
+<a href="http://wiki.debian.org/DebianLive/">http://wiki.debian.org/DebianLive/</a>.</p></div>
+</div>
+<h2 id="_authors">Authors</h2>
+<div class="sectionbody">
+<div class="para"><p>live-initramfs is maintained by Daniel Baumann <daniel@debian.org> for the
+Debian project. live-initramfs is a fork of
+<a href="http://packages.ubuntu.com/casper/">casper</a>. casper was originally written
+by Tollef Fog Heen <tfheen@canonical.com> and Matt Zimmerman <mdz@canonical.com>.</p></div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2009-06-29 14:34:56 CEST
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.txt b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.txt new file mode 100644 index 0000000000..4f53e7ebcd --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.txt @@ -0,0 +1,119 @@ +live-snapshot(1) +================ + +Name +---- +live-snapshot - a simple script to ease persistence usage + +Synopsis +-------- +live-snapshot [-c|--cow **DIRECTORY**s] [-d|--device **DEVICE**] [-e|--exclude-list **FILE**] [-o|--output **FILE**] [-t|--type **TYPE**] + +live-snapshot [-r|--resync-string **STRING**] + +live-snapshot [-h|--help] + +live-snapshot [-u|--usage] + +live-snapshot [-v|--version] + +Description +----------- + +live-snapshot is a script which can be used to build the right types of +persistent image files supported by live-initramfs(7). It is also used on +exit by the live-initramfs init script to resync the boot-found snapshots +devices. + +Options +------- + + -c, --cow **DIRECTORY**:: + +specifies the input directory to be cloned in the image file. Its default value +"/live/cow" should be right for most uses. However it could be handy to specify +"/home" and type ext2 for the type to prepare an image file suited to be +directly mounted by live-initramfs as home. + + -d, --device **DEVICE**:: + +sets the device where the media which the snapshot/persistence file/partition +will be put. If it is not specified, a tmpfs will be used and linked to the +user's desktop to move it where it is needed. If the device has no filesystem, +an ext2 fs will be automatically created and labelled according to the values +specified after the "--output" value or with a sane default. + + -e, --exclude-list **FILE**:: + +a file containing a list of filenames/paths that should not be saved. This exclude list will be remebered on the target snapshot media for reuse. + + -o, --output **FILE**:: + +the filename/label used for the output file/partition. If left blank, live-snapshot will search for a proper file on the device or use the whole partition. + + -r, --resync-string **STRING**:: + +internally used on resyncs. + + -f, --refresh:: + +try to do the same operation that should be done at reboot or halt, resyncing +boot-time auto discovered snapshots. Useful to prevent a crash or surge +power-off. + + -t, --type **TYPE**:: + +Type could be one of "cpio", "squashfs", "ext2", "ext3", "ext4", or "jffs2". + + -h, --help:: + +display help and exit + + -u, --usage:: + +show usage and exit + + -v, --version:: + +output version information and exit + +Files +----- + + /etc/live-snapshot.list + +This optional file, if present changes the behaviour of live-snapshot, only files and directories listed there are included (integrally) in the snapshot. It works only for cpio and whole partition targets. + + /etc/live-snapshot.exclude_list + +This optional file, if present will filter the files that will be saved by live-snapshot removing (as in "grep -F -v") all filenames that will be matched by strings listed in it. +It works for cpio, whole partition and squashfs snapshot types only; it is pretty useful for filtering temporary files and disk caches. + + +See also +-------- + +live-initramfs(8) + +This program is a part of live-initramfs. + +Bugs +---- + +Report bugs against live-initramfs +link:http://packages.qa.debian.org/live-initramfs[http://packages.qa.debian.org/live-initramfs]. + +Homepage +-------- + +More information about the Debian Live project can be found at +link:http://debian-live.alioth.debian.org/[http://debian-live.alioth.debian.org/] and +link:http://wiki.debian.org/DebianLive/[http://wiki.debian.org/DebianLive/]. + +Authors +------- + +live-initramfs is maintained by Daniel Baumann <daniel@debian.org> for the +Debian project. live-initramfs is a fork of +link:http://packages.ubuntu.com/casper/[casper]. casper was originally written +by Tollef Fog Heen <tfheen@canonical.com> and Matt Zimmerman <mdz@canonical.com>. diff --git a/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.xml b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.xml new file mode 100644 index 0000000000..8276c9b81f --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.en.1.xml @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<refentry lang="en">
+<refmeta>
+<refentrytitle>live-snapshot</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+<refnamediv>
+ <refname>live-snapshot</refname>
+ <refpurpose>a simple script to ease persistence usage</refpurpose>
+</refnamediv>
+<refsynopsisdiv>
+<simpara>live-snapshot [-c|--cow <emphasis role="strong">DIRECTORY</emphasis>s] [-d|--device <emphasis role="strong">DEVICE</emphasis>] [-e|--exclude-list <emphasis role="strong">FILE</emphasis>] [-o|--output <emphasis role="strong">FILE</emphasis>] [-t|--type <emphasis role="strong">TYPE</emphasis>]</simpara>
+
+<simpara>live-snapshot [-r|--resync-string <emphasis role="strong">STRING</emphasis>]</simpara>
+
+<simpara>live-snapshot [-h|--help]</simpara>
+
+<simpara>live-snapshot [-u|--usage]</simpara>
+
+<simpara>live-snapshot [-v|--version]</simpara>
+
+</refsynopsisdiv>
+<refsect1 id="_description">
+<title>Description</title>
+<simpara>live-snapshot is a script which can be used to build the right types of
+persistent image files supported by live-initramfs(7). It is also used on
+exit by the live-initramfs init script to resync the boot-found snapshots
+devices.</simpara>
+
+</refsect1>
+<refsect1 id="_options">
+<title>Options</title>
+<variablelist>
+<varlistentry>
+<term>
+-c, --cow <emphasis role="strong">DIRECTORY</emphasis>
+</term>
+<listitem>
+<simpara>
+specifies the input directory to be cloned in the image file. Its default value
+"/live/cow" should be right for most uses. However it could be handy to specify
+"/home" and type ext2 for the type to prepare an image file suited to be
+directly mounted by live-initramfs as home.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-d, --device <emphasis role="strong">DEVICE</emphasis>
+</term>
+<listitem>
+<simpara>
+sets the device where the media which the snapshot/persistence file/partition
+will be put. If it is not specified, a tmpfs will be used and linked to the
+user's desktop to move it where it is needed. If the device has no filesystem,
+an ext2 fs will be automatically created and labelled according to the values
+specified after the "--output" value or with a sane default.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-e, --exclude-list <emphasis role="strong">FILE</emphasis>
+</term>
+<listitem>
+<simpara>
+a file containing a list of filenames/paths that should not be saved. This exclude list will be remebered on the target snapshot media for reuse.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-o, --output <emphasis role="strong">FILE</emphasis>
+</term>
+<listitem>
+<simpara>
+the filename/label used for the output file/partition. If left blank, live-snapshot will search for a proper file on the device or use the whole partition.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-r, --resync-string <emphasis role="strong">STRING</emphasis>
+</term>
+<listitem>
+<simpara>
+internally used on resyncs.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-f, --refresh
+</term>
+<listitem>
+<simpara>
+try to do the same operation that should be done at reboot or halt, resyncing
+boot-time auto discovered snapshots. Useful to prevent a crash or surge
+power-off.
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-t, --type <emphasis role="strong">TYPE</emphasis>
+</term>
+<listitem>
+<simpara>
+Type could be one of "cpio", "squashfs", "ext2", "ext3", "ext4", or "jffs2".
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-h, --help
+</term>
+<listitem>
+<simpara>
+display help and exit
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-u, --usage
+</term>
+<listitem>
+<simpara>
+show usage and exit
+</simpara>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+-v, --version
+</term>
+<listitem>
+<simpara>
+output version information and exit
+</simpara>
+</listitem>
+</varlistentry>
+</variablelist>
+</refsect1>
+<refsect1 id="_files">
+<title>Files</title>
+<literallayout class="monospaced">/etc/live-snapshot.list</literallayout>
+<simpara>This optional file, if present changes the behaviour of live-snapshot, only files and directories listed there are included (integrally) in the snapshot. It works only for cpio and whole partition targets.</simpara>
+
+<literallayout class="monospaced">/etc/live-snapshot.exclude_list</literallayout>
+<simpara>This optional file, if present will filter the files that will be saved by live-snapshot removing (as in "grep -F -v") all filenames that will be matched by strings listed in it.
+It works for cpio, whole partition and squashfs snapshot types only; it is pretty useful for filtering temporary files and disk caches.</simpara>
+
+</refsect1>
+<refsect1 id="_see_also">
+<title>See also</title>
+<simpara>live-initramfs(8)</simpara>
+
+<simpara>This program is a part of live-initramfs.</simpara>
+
+</refsect1>
+<refsect1 id="_bugs">
+<title>Bugs</title>
+<simpara>Report bugs against live-initramfs
+<ulink url="http://packages.qa.debian.org/live-initramfs">http://packages.qa.debian.org/live-initramfs</ulink>.</simpara>
+
+</refsect1>
+<refsect1 id="_homepage">
+<title>Homepage</title>
+<simpara>More information about the Debian Live project can be found at
+<ulink url="http://debian-live.alioth.debian.org/">http://debian-live.alioth.debian.org/</ulink> and
+<ulink url="http://wiki.debian.org/DebianLive/">http://wiki.debian.org/DebianLive/</ulink>.</simpara>
+
+</refsect1>
+<refsect1 id="_authors">
+<title>Authors</title>
+<simpara>live-initramfs is maintained by Daniel Baumann <daniel@debian.org> for the
+Debian project. live-initramfs is a fork of
+<ulink url="http://packages.ubuntu.com/casper/">casper</ulink>. casper was originally written
+by Tollef Fog Heen <tfheen@canonical.com> and Matt Zimmerman <mdz@canonical.com>.</simpara>
+
+</refsect1>
+</refentry>
diff --git a/tools/XBMCLive/live-initramfs/manpages/live-snapshot.it.1.txt b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.it.1.txt new file mode 100644 index 0000000000..1beb7918fd --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/live-snapshot.it.1.txt @@ -0,0 +1,126 @@ +live-snapshot(1) +================ + +Name +---- +live-snapshot - uno script per facilitare l'uso della persistenza sui sistemi live + +Synopsis +-------- +live-snapshot [-c|--cow **DIRECTORY**s] [-d|--device **DEVICE**] [-e|--exclude-list **FILE**] [-o|--output **FILE**] [-t|--type **TYPE**] + +live-snapshot [-r|--resync-string **STRING**] + +live-snapshot [-h|--help] + +live-snapshot [-u|--usage] + +live-snapshot [-v|--version] + +Description +----------- + +live-snapshot `e uno script che pu`o essere usato per costruire un file immagine formattato +correttamente per essere usato da live-initramfs(7); viene inoltre usato dallo script di +init di live-initramfs in uscita per sincronizzare i device di snapshot riconosciuti al boot. + +Options +------- + + -c, --cow **DIRECTORY**:: + +specifica la directory da clonare nel file immagine. Il valore di default `e +lo stesso default usato da live-initramfs per la sua directory COW (copy on +write, un tempo situata in "/live/cow") ed `e sufficiente per gli usi comuni. +Pu`o essere utile tuttavia specificare "/home" e come tipo "ext2" per +preparare un file immagine adatto per essere montato da live-initramfs come +"/home" al boot. + + -d, --device **DEVICE**:: + +seleziona il device dove il file/partizione di snapshot o persistenza dovr`a +essere sistemato. Se il device non ha un filesystem, ne verr`a creato uno +automaticamente, di tipo ext2 ed etichettato (label) in base al valore +specificato nell'opzione "--output" o con un default. Se non viene specificato +nessun device, verr`a usato un "tmpfs" linkato sul desktop dell'utente, in +modo che port`a essere mosso dove si vuole. + + -e, --exclude-list **FILE**:: + +un file contenente una lista di file e percorsi che NON devono essere salvati. +Questa lista verr`a inclusa nello snapshot per essere riutilizzata. + + -o, --output **FILE**:: + +il nome del file o l'etichetta (label) da usare per il file o la partizione di +snapshot. Se non specificata, live-snapshot cercher\`a un file all'interno +del device oppure user`a l'intera partizione. + + -r, --resync-string **STRING**:: + +usato internamente nelle sincronizzazioni dallo script di init di +live-initramfs. Il formato pu\`o cambiare, usatelo a vostro rischio. + + -f, --refresh:: + +scatena la stessa operazione che verrebbe fatta al reboot o all'halt della +macchina, provando a fare il resync degli snapshot trovati al boot, usabile +per salvare le modifiche in vista di un crash o di una mancanza di corrente. + + -t, --type **TYPE**:: + +il tipo pu`o essere "cpio", "squashfs" o "ext2". + + -h, --help:: + +mostra l'aiuto ed esce + + -u, --usage:: + +mostra l'utilizzo ed esce + + -v, --version:: + +da informazioni sulla versione ed esce + +Files +----- + + /etc/live-snapshot.list + +Facoltativo, se presente cambia completamente il funzionamento di live-snapshot; solo i files e le directory elencate verranno effettivamente inclusi nello snapshot. +Funziona attualmente solo con gli snapshot di tipo "cpio" e "partizione intera". + + /etc/live-snapshot.exclude_list + +Facoltativo, se presente verrà utilizzato per filtrare i file da includere negli snapshot. Tutte i file che conterranno le stringhe elecate (come "grep -F -v") non verranno salvati da live-snapshot. +Funziona attualmente solo con gli snapshot di tipo "cpio", "partizione intera" e "squashfs"; è utile per filtrare contenuti poco significativi come i file temporanei e la cache. + +See also +-------- + +live-initramfs(8) + +Questo programma fa parte di live-initramfs. + +Bugs +---- + +Riportate i bug sul pacchetto live-initramfs +link:http://packages.qa.debian.org/live-initramfs[http://packages.qa.debian.org/live-initramfs]. + +Homepage +-------- + +Ulteriori informazioni su progetto Debian Live possono essere trovate su +link:http://debian-live.alioth.debian.org/[http://debian-live.alioth.debian.org/] e +link:http://wiki.debian.org/DebianLive/[http://wiki.debian.org/DebianLive/]. + +Authors +------- + +live-initramfs `e mantenuto da Daniel Baumann <daniel@debian.org> per il +progetto Debian. live-initramfs `e un fork di +link:http://packages.ubuntu.com/casper[casper]. casper `e stato scritto +originariamente da Tollef Fog Heen <tfheen@canonical.com> e Matt Zimmerman +<mdz@canonical.com>. diff --git a/tools/XBMCLive/live-initramfs/manpages/man-stamp b/tools/XBMCLive/live-initramfs/manpages/man-stamp new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/manpages/man-stamp diff --git a/tools/XBMCLive/live-initramfs/scripts/live b/tools/XBMCLive/live-initramfs/scripts/live new file mode 100755 index 0000000000..4472f2ad6d --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live @@ -0,0 +1,1725 @@ +#!/bin/sh + +# set -e + +export PATH="/root/usr/bin:/root/usr/sbin:/root/bin:/root/sbin:/usr/bin:/usr/sbin:/bin:/sbin" + +echo "/root/lib" >> /etc/ld.so.conf +echo "/root/usr/lib" >> /etc/ld.so.conf + +mountpoint="/live/image" +LIVE_MEDIA_PATH="live" + +root_persistence="live-rw" +home_persistence="home-rw" +root_snapshot_label="live-sn" +home_snapshot_label="home-sn" + +USERNAME="user" +USERFULLNAME="Live user" +HOSTNAME="host" + +mkdir -p "${mountpoint}" + +# Create /etc/mtab for debug purpose and future syncs +if [ ! -d /etc ] +then + mkdir /etc/ +fi + +if [ ! -f /etc/mtab ] +then + touch /etc/mtab +fi + +[ -f /etc/live.conf ] && . /etc/live.conf +export USERNAME USERFULLNAME HOSTNAME + +. /scripts/live-helpers + +if [ ! -f /live.vars ] +then + touch /live.vars +fi + +Arguments () +{ + PRESEEDS="" + + for ARGUMENT in $(cat /proc/cmdline) + do + case "${ARGUMENT}" in + access=*) + ACCESS="${ARGUMENT#access=}" + export ACCESS + ;; + + console=*) + DEFCONSOLE="${ARGUMENT#*=}" + export DEFCONSOLE + ;; + + debug) + DEBUG="Yes" + export DEBUG + + set -x + ;; + + fetch=*) + FETCH="${ARGUMENT#fetch=}" + export FETCH + ;; + + hook=*) + HOOK="${ARGUMENT#hook=}" + export HOOK + ;; + + ftpfs=*) + FTPFS="${ARGUMENT#ftpfs=}" + export FTPFS + ;; + + httpfs=*) + HTTPFS="${ARGUMENT#httpfs=}" + export HTTPFS + ;; + + hostname=*) + HOSTNAME="${ARGUMENT#hostname=}" + LIVECONF="changed" + export HOSTNAME LIVECONF + ;; + + username=*) + USERNAME="${ARGUMENT#username=}" + LIVECONF="changed" + export USERNAME LIVECONF + ;; + + userfullname=*) + USERFULLNAME="${ARGUMENT#userfullname=}" + LIVECONF="changed" + export USERFULLNAME LIVECONF + ;; + + ignore_uuid) + IGNORE_UUID="Yes" + export IGNORE_UUID + ;; + + integrity-check) + INTEGRITY_CHECK="Yes" + export INTEGRITY_CHECK + ;; + + ip=*) + STATICIP="${ARGUMENT#ip=}" + + if [ -z "${STATICIP}" ] + then + STATICIP="frommedia" + fi + + export STATICIP + ;; + + keyb=*|kbd-chooser/method=*) + KBD="${ARGUMENT#*=}" + export KBD + ;; + + klayout=*|console-setup/layoutcode=*) + KLAYOUT="${ARGUMENT#*=}" + export KLAYOUT + ;; + + kvariant=*|console-setup/variantcode=*) + KVARIANT="${ARGUMENT#*=}" + export KVARIANT + ;; + + kmodel=*|console-setup/modelcode=*) + KMODEL="${ARGUMENT#*=}" + export KMODEL + ;; + + koptions=*) + KOPTIONS="${ARGUMENT#koptions=}" + export KOPTIONS + ;; + + live-getty) + LIVE_GETTY="1" + export LIVE_GETTY + ;; + + live-media=*|bootfrom=*) + LIVE_MEDIA="${ARGUMENT#*=}" + export LIVE_MEDIA + ;; + + live-media-encryption=*|encryption=*) + LIVE_MEDIA_ENCRYPTION="${ARGUMENT#*=}" + export LIVE_MEDIA_ENCRYPTION + ;; + + live-media-offset=*) + LIVE_MEDIA_OFFSET="${ARGUMENT#live-media-offset=}" + export LIVE_MEDIA_OFFSET + ;; + + live-media-path=*) + LIVE_MEDIA_PATH="${ARGUMENT#live-media-path=}" + export LIVE_MEDIA_PATH + ;; + + live-media-timeout=*) + LIVE_MEDIA_TIMEOUT="${ARGUMENT#live-media-timeout=}" + export LIVE_MEDIA_TIMEOUT + ;; + + language=*|debian-installer/language=*) + language=${x#debian-installer/language=} + locale="$(lang2locale "$language")" + set_locale="true" + ;; + + locale=*|debian-installer/locale=*) + LOCALE="${ARGUMENT#*=}" + export LOCALE + ;; + + module=*) + MODULE="${ARGUMENT#module=}" + export MODULE + ;; + + netboot=*) + NETBOOT="${ARGUMENT#netboot=}" + export NETBOOT + ;; + + nfsopts=*) + NFSOPTS="${ARGUMENT#nfsopts=}" + export NFSOPTS + ;; + + nfscow=*) + NFS_COW="${ARGUMENT#nfscow=}" + export NFS_COW + ;; + + noaccessibility) + NOACCESSIBILITY="Yes" + export NOACCESSIBILITY + ;; + + noapparmor) + NOAPPARMOR="Yes" + export NOAPPARMOR + ;; + + noaptcdrom) + NOAPTCDROM="Yes" + export NOAPTCDROM + ;; + + noautologin) + NOAUTOLOGIN="Yes" + export NOAUTOLOGIN + ;; + + noxautologin) + NOXAUTOLOGIN="Yes" + export NOXAUTOLOGIN + ;; + + noconsolekeyboard) + NOCONSOLEKEYBOARD="Yes" + export NOCONSOLEKEYBOARD + ;; + + nofastboot) + NOFASTBOOT="Yes" + export NOFASTBOOT + ;; + + nofstab) + NOFSTAB="Yes" + export NOFSTAB + ;; + + nognomepanel) + NOGNOMEPANEL="Yes" + export NOGNOMEPANEL + ;; + + nohosts) + NOHOSTS="Yes" + export NOHOSTS + ;; + + nokpersonalizer) + NOKPERSONALIZER="Yes" + export NOKPERSONALIZER + ;; + + nolanguageselector) + NOLANGUAGESELECTOR="Yes" + export NOLANGUAGESELECTOR + ;; + + nolocales) + NOLOCALES="Yes" + export NOLOCALES + ;; + + nonetworking) + NONETWORKING="Yes" + export NONETWORKING + ;; + + nopowermanagement) + NOPOWERMANAGEMENT="Yes" + export NOPOWERMANAGEMENT + ;; + + noprogramcrashes) + NOPROGRAMCRASHES="Yes" + export NOPROGRAMCRASHES + ;; + + nojockey) + NOJOCKEY="Yes" + export NOJOCKEY + ;; + + nosudo) + NOSUDO="Yes" + export NOSUDO + ;; + + swapon) + SWAPON="Yes" + export SWAPON + ;; + + noupdatenotifier) + NOUPDATENOTIFIER="Yes" + export NOUPDATENOTIFIER + ;; + + nouser) + NOUSER="Yes" + export NOUSER + ;; + + nopolkitconf) + NOPOLKITCONF="Yes" + export NOPOLKITCONF + ;; + + noxautoconfig) + NOXAUTOCONFIG="Yes" + export NOXAUTOCONFIG + ;; + + noxscreensaver) + NOXSCREENSAVER="Yes" + export NOXSCREENSAVER + ;; + + persistent) + PERSISTENT="Yes" + export PERSISTENT + ;; + + persistent=*) + PERSISTENT="${ARGUMENT#persistent=}" + if [ -z "${PERSISTENT}" ] + then + PERSISTENT="Yes" + fi + export PERSISTENT + ;; + + persistent-path=*) + PERSISTENT_PATH="${ARGUMENT#persistent-path=}" + export PERSISTENT_PATH + ;; + + nopersistent) + NOPERSISTENT="Yes" + export NOPERSISTENT + ;; + + quickusbmodules) + QUICKUSBMODULES="Yes" + export QUICKUSBMODULES + ;; + + preseed/file=*|file=*) + LOCATION="${ARGUMENT#*=}" + export LOCATION + ;; + + nopreseed) + NOPRESEED="Yes" + export NOPRESEED + ;; + + url=*) + location="${ARGUMENT#url=}" + + mount -o bind /sys /root/sys + mount -o bind /proc /root/proc + mount -o bind /dev /root/dev + + mkdir -p /root/var/run/network + chroot /root dhclient eth0 + chroot /root wget -P /tmp "${location}" + chroot /root ifconfig eth0 down + + umount /root/sys + umount /root/proc + umount /root/dev + + LOCATION="/tmp/$(basename "${location}")" + ;; + + skipconfig) + NOTIMEZONE="Yes" + export NOTIMEZONE + NOACCESSIBILITY="Yes" + export NOACCESSIBILITY + NOAPPARMOR="Yes" + export NOAPPARMOR + NOAPTCDROM="Yes" + export NOAPTCDROM + NOAUTOLOGIN="Yes" + export NOAUTOLOGIN + NOXAUTOLOGIN="Yes" + export NOXAUTOLOGIN + NOCONSOLEKEYBOARD="Yes" + export NOCONSOLEKEYBOARD + NOFASTBOOT="Yes" + export NOFASTBOOT + NOFSTAB="Yes" + export NOFSTAB + NOGNOMEPANEL="Yes" + export NOGNOMEPANEL + NOHOSTS="Yes" + export NOHOSTS + NOKPERSONALIZER="Yes" + export NOKPERSONALIZER + NOLANGUAGESELECTOR="Yes" + export NOLANGUAGESELECTOR + NOLOCALES="Yes" + export NOLOCALES + NONETWORKING="Yes" + export NONETWORKING + NOPOWERMANAGEMENT="Yes" + export NOPOWERMANAGEMENT + NOPROGRAMCRASHES="Yes" + export NOPROGRAMCRASHES + NOJOCKEY="Yes" + export NOJOCKEY + NOSUDO="Yes" + export NOSUDO + NOUPDATENOTIFIER="Yes" + export NOUPDATENOTIFIER + NOUSER="Yes" + export NOUSER + NOPOLKITCONF="Yes" + export NOPOLKITCONF + NOXAUTOCONFIG="Yes" + export NOXAUTOCONFIG + NOXSCREENSAVER="Yes" + export NOXSCREENSAVER + ;; + + */*=*) + question="${ARGUMENT%%=*}" + value="${ARGUMENT#*=}" + PRESEEDS="${PRESEEDS}\"${question}=${value}\" " + export PRESEEDS + ;; + + showmounts) + SHOWMOUNTS="Yes" + export SHOWMOUNTS + ;; + + silent) + SILENT="Yes" + export SILENT + ;; + + textonly) + TEXTONLY="Yes" + export TEXTONLY + ;; + + timezone=*) + TIMEZONE="${ARGUMENT#timezone=}" + export TIMEZONE + ;; + + notimezone) + NOTIMEZONE="Yes" + export NOTIMEZONE + ;; + + todisk=*) + TODISK="${ARGUMENT#todisk=}" + export TODISK + ;; + + toram) + TORAM="Yes" + export TORAM + ;; + + toram=*) + TORAM="Yes" + MODULETORAM="${ARGUMENT#toram=}" + export TORAM MODULETORAM + ;; + + exposedroot) + EXPOSED_ROOT="Yes" + export EXPOSED_ROOT + ;; + + plainroot) + PLAIN_ROOT="Yes" + export PLAIN_ROOT + ;; + + skipunion) + SKIP_UNION_MOUNTS="Yes" + export SKIP_UNION_MOUNTS + ;; + + root=*) + ROOT="${ARGUMENT#root=}" + export ROOT + ;; + + union=*) + UNIONTYPE="${ARGUMENT#union=}" + export UNIONTYPE + ;; + + utc=*) + UTC="${ARGUMENT#utc=}" + export UTC + ;; + + xdebconf) + XDEBCONF="Yes" + export XDEBCONF + ;; + + xdriver=*) + XDRIVER="${ARGUMENT#xdriver=}" + export XDRIVER + ;; + + xvideomode=*) + XVIDEOMODE="${ARGUMENT#xvideomode=}" + export XVIDEOMODE + ;; + esac + done + + # sort of compatibility with netboot.h from linux docs + if [ -z "${NETBOOT}" ] + then + if [ "${ROOT}" = "/dev/nfs" ] + then + NETBOOT="nfs" + export NETBOOT + elif [ "${ROOT}" = "/dev/cifs" ] + then + NETBOOT="cifs" + export NETBOOT + fi + fi + + if [ -z "${MODULE}" ] + then + MODULE="filesystem" + export MODULE + fi + + if [ -z "${UNIONTYPE}" ] + then + UNIONTYPE="aufs" + export UNIONTYPE + fi +} + +is_live_path () +{ + DIRECTORY="${1}" + + if [ -d "${DIRECTORY}"/"${LIVE_MEDIA_PATH}" ] + then + for FILESYSTEM in squashfs ext2 ext3 ext4 xfs dir jffs2 + do + if [ "$(echo ${DIRECTORY}/${LIVE_MEDIA_PATH}/*.${FILESYSTEM})" != "${DIRECTORY}/${LIVE_MEDIA_PATH}/*.${FILESYSTEM}" ] + then + return 0 + fi + done + fi + + return 1 +} + +matches_uuid () +{ + if [ "${IGNORE_UUID}" ] || [ ! -e /conf/uuid.conf ] + then + return 0 + fi + + path="${1}" + uuid="$(cat /conf/uuid.conf)" + + for try_uuid_file in "${path}/.disk/live-uuid"* + do + [ -e "${try_uuid_file}" ] || continue + + try_uuid="$(cat "${try_uuid_file}")" + + if [ "${uuid}" = "${try_uuid}" ] + then + return 0 + fi + done + + return 1 +} + +get_backing_device () +{ + case "${1}" in + *.squashfs|*.ext2|*.ext3|*.ext4|*.jffs2) + echo $(setup_loop "${1}" "loop" "/sys/block/loop*" '0' "${LIVE_MEDIA_ENCRYPTION}" "${2}") + ;; + + *.dir) + echo "directory" + ;; + + *) + panic "Unrecognized live filesystem: ${1}" + ;; + esac +} + +match_files_in_dir () +{ + # Does any files match pattern ${1} ? + local pattern="${1}" + + if [ "$(echo ${pattern})" != "${pattern}" ] + then + return 0 + fi + + return 1 +} + +mount_images_in_directory () +{ + directory="${1}" + rootmnt="${2}" + mac="${3}" + + + if match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.squashfs" || + match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext2" || + match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext3" || + match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext4" || + match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.jffs2" || + match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.dir" + then + [ -n "${mac}" ] && adddirectory="${directory}/${LIVE_MEDIA_PATH}/${mac}" + setup_unionfs "${directory}/${LIVE_MEDIA_PATH}" "${rootmnt}" "${adddirectory}" + else + panic "No supported filesystem images found at /${LIVE_MEDIA_PATH}." + fi +} + +is_nice_device () +{ + sysfs_path="${1#/sys}" + + if /lib/udev/path_id "${sysfs_path}" | grep -E -q "ID_PATH=(usb|pci-[^-]*-(ide|scsi|usb))" + then + return 0 + elif echo "${sysfs_path}" | grep -q '^/block/vd[a-z]$' + then + return 0 + fi + + return 1 +} + +copy_live_to () +{ + copyfrom="${1}" + copytodev="${2}" + copyto="${copyfrom}_swap" + + if [ -z "${MODULETORAM}" ] + then + size=$(fs_size "" ${copyfrom} "used") + else + MODULETORAMFILE="${copyfrom}/${LIVE_MEDIA_PATH}/${MODULETORAM}" + + if [ -f "${MODULETORAMFILE}" ] + then + size=$( expr $(ls -la ${MODULETORAMFILE} | awk '{print $5}') / 1024 + 5000 ) + else + log_warning_msg "Error: toram-module ${MODULETORAM} (${MODULETORAMFILE}) could not be read." + return 1 + fi + fi + + if [ "${copytodev}" = "ram" ] + then + # copying to ram: + freespace=$( expr $(awk '/MemFree/{print $2}' /proc/meminfo) + $( awk '/\<Cached/{print $2}' /proc/meminfo ) ) + mount_options="-o size=${size}k" + free_string="memory" + fstype="tmpfs" + dev="/dev/shm" + else + # it should be a writable block device + if [ -b "${copytodev}" ] + then + dev="${copytodev}" + free_string="space" + fstype=$(get_fstype "${dev}") + freespace=$(fs_size "${dev}") + else + log_warning_msg "${copytodev} is not a block device." + return 1 + fi + fi + + if [ "${freespace}" -lt "${size}" ] + then + log_warning_msg "Not enough free ${free_string} (${freespace}k free, ${size}k needed) to copy live media in ${copytodev}." + return 1 + fi + + # begin copying (or uncompressing) + mkdir "${copyto}" + echo "mount -t ${fstype} ${mount_options} ${dev} ${copyto}" + mount -t "${fstype}" ${mount_options} "${dev}" "${copyto}" + + if [ "${extension}" = "tgz" ] + then + cd "${copyto}" + tar zxf "${copyfrom}/${LIVE_MEDIA_PATH}/$(basename ${FETCH})" + rm -f "${copyfrom}/${LIVE_MEDIA_PATH}/$(basename ${FETCH})" + mount -r -o move "${copyto}" "${rootmnt}" + cd "${OLDPWD}" + else + if [ -n "${MODULETORAMFILE}" ] + then + cp ${MODULETORAMFILE} ${copyto} # copy only the filesystem module + else + cp -a ${copyfrom}/* ${copyto} # "cp -a" from busybox also copies hidden files + fi + + umount ${copyfrom} + mount -r -o move ${copyto} ${copyfrom} + fi + + rmdir ${copyto} + return 0 +} + +do_netmount () +{ + rc=1 + + modprobe -q af_packet # For DHCP + + if [ -x /sbin/udevadm ] + then + # lenny + udevadm trigger + udevadm settle + else + # etch + udevtrigger + udevsettle + fi + + ipconfig ${DEVICE} | tee /netboot.config + + # source relevant ipconfig output + OLDHOSTNAME=${HOSTNAME} + . /tmp/net-${DEVICE}.conf + [ -z ${HOSTNAME} ] && HOSTNAME=${OLDHOSTNAME} + export HOSTNAME + + # Check if we have a network device at all + if ! ls /sys/class/net/eth0 > /dev/null 2>&1 && \ + ! ls /sys/class/net/wlan0 > /dev/null 2>&1 && \ + ! ls /sys/class/net/ath0 > /dev/null 2>&1 && \ + ! ls /sys/class/net/ra0 > /dev/null 2>&1 + then + panic "No supported network device found, maybe a non-mainline driver is required." + fi + + if [ "${NFSROOT}" = "auto" ] + then + NFSROOT=${ROOTSERVER}:${ROOTPATH} + fi + + if ( [ -n "${FETCH}" ] || [ -n "${HTTPFS}" ] || [ -n "${FTPFS}" ] ) && do_httpmount + then + rc=0 + return ${rc} + fi + + if [ "${NFSROOT#*:}" = "${NFSROOT}" ] && [ "$NETBOOT" != "cifs" ] + then + NFSROOT=${ROOTSERVER}:${NFSROOT} + fi + + log_begin_msg "Trying netboot from ${NFSROOT}" + + if [ "${NETBOOT}" != "nfs" ] && do_cifsmount + then + rc=0 + elif do_nfsmount + then + NETBOOT="nfs" + export NETBOOT + rc=0 + fi + + log_end_msg + return ${rc} +} + +do_httpmount () +{ + rc=1 + dest="${mountpoint}/${LIVE_MEDIA_PATH}" + mount -t ramfs ram "${mountpoint}" + mkdir -p "${dest}" + + for webfile in HTTPFS FTPFS FETCH + do + url="$(eval echo \"\$\{${webfile}\}\")" + extension="$(echo "${url}" | sed 's/\(.*\)\.\(.*\)/\2/')" + + if [ -n "$url" ] + then + case "${extension}" in + squashfs|tgz|tar) + if [ "${webfile}" = "FETCH" ] + then + case "$url" in + tftp*) + ip="$(dirname $url | sed -e 's|tftp://||g' -e 's|/.*$||g')" + rfile="$(echo $url | sed -e "s|tftp://$ip||g")" + lfile="$(basename $url)" + log_begin_msg "Trying tftp -g -b 10240 -r $rfile -l ${dest}/$lfile $ip" + tftp -g -b 10240 -r $rfile -l ${dest}/$lfile $ip + ;; + + *) + log_begin_msg "Trying wget ${url} -O ${dest}/$(basename ${url})" + wget "${url}" -O "${dest}/$(basename ${url})" + ;; + esac + else + log_begin_msg "Trying to mount ${url} on ${dest}/$(basename ${url})" + if [ "${webfile}" = "FTPFS" ] + then + FUSE_MOUNT="curlftpfs" + url="$(dirname ${url})" + else + FUSE_MOUNT="httpfs" + fi + modprobe fuse + $FUSE_MOUNT "${url}" "${dest}" + fi + [ ${?} -eq 0 ] && rc=0 + [ "${extension}" = "tgz" ] && live_dest="ram" + break + ;; + + *) + log_begin_msg "Unrecognized archive extension for ${url}" + ;; + esac + fi + done + + if [ ${rc} != 0 ] + then + umount "${mountpoint}" + fi + + return ${rc} +} + +do_nfsmount () +{ + rc=1 + + modprobe -q nfs + + if [ -z "${NFSOPTS}" ] + then + NFSOPTS="" + fi + + log_begin_msg "Trying nfsmount -o nolock -o ro ${NFSOPTS} ${NFSROOT} ${mountpoint}" + + # FIXME: This while loop is an ugly HACK round an nfs bug + i=0 + while [ "$i" -lt 60 ] + do + nfsmount -o nolock -o ro ${NFSOPTS} "${NFSROOT}" "${mountpoint}" && rc=0 && break + sleep 1 + i="$(($i + 1))" + done + + return ${rc} +} + +do_cifsmount () +{ + rc=1 + + if [ -x "/sbin/mount.cifs" ] + then + if [ -z "${NFSOPTS}" ] + then + CIFSOPTS="-ouser=root,password=" + else + CIFSOPTS="${NFSOPTS}" + fi + + log_begin_msg "Trying mount.cifs ${NFSROOT} ${mountpoint} ${CIFSOPTS}" + modprobe -q cifs + + if mount.cifs "${NFSROOT}" "${mountpoint}" "${CIFSOPTS}" + then + rc=0 + fi + fi + + return ${rc} +} + +do_snap_copy () +{ + fromdev="${1}" + todir="${2}" + snap_type="${3}" + size=$(fs_size "${fromdev}" "" "used") + + if [ -b "${fromdev}" ] + then + # look for free mem + if [ -n "${HOMEMOUNTED}" -a "${snap_type}" = "HOME" ] + then + todev=$(awk -v pat="$(base_path ${todir})" '$2 == pat { print $1 }' /proc/mounts) + freespace=$(df -k | awk '/'${todev}'/{print $4}') + else + freespace=$( expr $(awk '/MemFree/{print $2}' /proc/meminfo) + $( awk '/\<Cached/{print $2}' /proc/meminfo)) + fi + + tomount="/mnt/tmpsnap" + + if [ ! -d "${tomount}" ] + then + mkdir -p "${tomount}" + fi + + fstype=$(get_fstype "${fromdev}") + + if [ -n "${fstype}" ] + then + # Copying stuff... + mount -o ro -t "${fstype}" "${fromdev}" "${tomount}" || log_warning_msg "Error in mount -t ${fstype} -o ro ${fromdev} ${tomount}" + cp -a "${tomount}"/* ${todir} + umount "${tomount}" + else + log_warning_msg "Unrecognized fstype: ${fstype} on ${fromdev}:${snap_type}" + fi + + rmdir "${tomount}" + + if echo ${fromdev} | grep -qs loop + then + losetup -d "${fromdev}" + fi + + return 0 + else + return 1 + + log_warning_msg "Unable to find the snapshot ${snap_type} medium" + fi +} + +find_snap () +{ + # Look for ${snap_label}.* in block devices + snap_label="${1}" + + if [ "${PERSISTENT}" != "nofiles" ] + then + # search for image files + snapdata=$(find_files "${snap_label}.squashfs ${snap_label}.cpio.gz ${snap_label}.ext2 ${snap_label}.ext3 ${snap_label}.ext4 ${snap_label}.jffs2") + fi + + if [ -z "${snapdata}" ] + then + snapdata=$(find_cow_device "${snap_label}") + fi + echo "${snapdata}" +} + +try_snap () +{ + # copy the contents of previously found snapshot to ${snap_mount} + # and remember the device and filename for resync on exit in live-initramfs.init + + snapdata="${1}" + snap_mount="${2}" + snap_type="${3}" + + if [ -n "${snapdata}" ] && [ ! -b "${snapdata}" ] + then + log_success_msg "found snapshot: ${snapdata}" + snapdev="$(echo ${snapdata} | cut -f1 -d ' ')" + snapback="$(echo ${snapdata} | cut -f2 -d ' ')" + snapfile="$(echo ${snapdata} | cut -f3 -d ' ')" + + RES="" + if ! try_mount "${snapdev}" "${snapback}" "ro" + then + break + fi + + if echo "${snapfile}" | grep -qs '\(squashfs\|ext2\|ext3\|ext4\|jffs2\)' + then + # squashfs, jffs2 or ext2/ext3/ext4 snapshot + dev=$(get_backing_device "${snapback}/${snapfile}") + + do_snap_copy "${dev}" "${snap_mount}" "${snap_type}" + RES=$? + else + # cpio.gz snapshot + cd "${snap_mount}" + zcat "${snapback}/${snapfile}" | /bin/cpio --extract --preserve-modification-time --no-absolute-filenames --sparse --unconditional --make-directories > /dev/null 2>&1 + RES=$? + if [ "${RES}" != "0" ] + then + log_warning_msg "failure to \"zcat ${snapback}/${snapfile} | /bin/cpio --extract --preserve-modification-time --no-absolute-filenames --sparse --unconditional --make-directories\"" + fi + cd "${OLDPWD}" + fi + + umount "${snapback}" || log_warning_msg "failure to \"umount ${snapback}\"" + + if [ "${RES}" != "0" ] + then + log_warning_msg "Impossible to include the ${snapfile} Snapshot file" + fi + + elif [ -b "${snapdata}" ] + then + # Try to find if it could be a snapshot partition + dev="${snapdata}" + log_success_msg "found snapshot ${snap_type} device on ${dev}" + if echo "${dev}" | grep -qs loop + then + # strange things happens, user confused? + snaploop=$( losetup ${dev} | awk '{print $3}' | tr -d '()' ) + snapfile=$(basename ${snaploop}) + snapdev=$(awk -v pat="$( dirname ${snaploop})" '$2 == pat { print $1 }' /proc/mounts) + else + snapdev="${dev}" + fi + + if ! do_snap_copy "${dev}" "${snap_mount}" "${snap_type}" + then + log_warning_msg "Impossible to include the ${snap_type} Snapshot" + return 1 + else + if [ -n "${snapfile}" ] + then + # it was a loop device, user confused + umount ${snapdev} + fi + fi + else + log_warning_msg "Impossible to include the ${snap_type} Snapshot" + return 1 + fi + + echo "export ${snap_type}SNAP="${snap_mount}":${snapdev}:${snapfile}" >> /etc/live.conf # for resync on reboot/halt + return 0 +} + +setup_unionfs () +{ + image_directory="${1}" + rootmnt="${2}" + addimage_directory="${3}" + modprobe -q -b ${UNIONTYPE} + + # run-init can't deal with images in a subdir, but we're going to + # move all of these away before it runs anyway. No, we're not, + # put them in / since move-mounting them into / breaks mono and + # some other apps. + + croot="/" + + # Let's just mount the read-only file systems first + rofsstring="" + rofslist="" + minor_kernel_version=$(uname -r|cut -c 5-|sed 's/[^0-9].*//') + + if [ "${NETBOOT}" = "nfs" ] && [ "${minor_kernel_version}" -lt 22 ] + then + # go aroung a bug in nfs-unionfs locking for unionfs <= 1.4 + roopt="nfsro" + elif [ "${UNIONTYPE}" = "aufs" ] + then + roopt="rr" + else + roopt="ro" + fi + + if [ -z "${PLAIN_ROOT}" ] + then + # Read image names from ${MODULE}.module if it exists + if [ -e "${image_directory}/filesystem.${MODULE}.module" ] + then + for IMAGE in $(cat ${image_directory}/filesystem.${MODULE}.module) + do + image_string="${image_string} ${image_directory}/${IMAGE}" + done + elif [ -e "${image_directory}/${MODULE}.module" ] + then + for IMAGE in $(cat ${image_directory}/${MODULE}.module) + do + image_string="${image_string} ${image_directory}/${IMAGE}" + done + else + # ${MODULE}.module does not exist, create a list of images + for FILESYSTEM in squashfs ext2 ext3 ext4 xfs jffs2 dir + do + for IMAGE in "${image_directory}"/*."${FILESYSTEM}" + do + if [ -e "${IMAGE}" ] + then + image_string="${image_string} ${IMAGE}" + fi + done + done + + if [ -n "${addimage_directory}" ] && [ -d "${addimage_directory}" ] + then + for FILESYSTEM in squashfs ext2 ext3 ext4 xfs jffs2 dir + do + for IMAGE in "${addimage_directory}"/*."${FILESYSTEM}" + do + if [ -e "${IMAGE}" ] + then + image_string="${image_string} ${IMAGE}" + fi + done + done + fi + + # Now sort the list + image_string="$(echo ${image_string} | sed -e 's/ /\n/g' | sort )" + fi + + [ -n "${MODULETORAMFILE}" ] && image_string="${image_directory}/$(basename ${MODULETORAMFILE})" + + mkdir -p "${croot}" + + for image in ${image_string} + do + imagename=$(basename "${image}") + + export image devname + maybe_break live-realpremount + log_begin_msg "Running /scripts/live-realpremount" + run_scripts /scripts/live-realpremount + log_end_msg + + if [ -d "${image}" ] + then + # it is a plain directory: do nothing + rofsstring="${image}=${roopt}:${rofsstring}" + rofslist="${image} ${rofslist}" + elif [ -f "${image}" ] + then + if losetup --help 2>&1 | grep -q -- "-r\b" + then + backdev=$(get_backing_device "${image}" "-r") + else + backdev=$(get_backing_device "${image}") + fi + fstype=$(get_fstype "${backdev}") + + if [ "${fstype}" = "unknown" ] + then + panic "Unknown file system type on ${backdev} (${image})" + fi + + if [ -z "${fstype}" ] + then + fstype="${imagename##*.}" + log_warning_msg "Unknown file system type on ${backdev} (${image}), assuming ${fstype}." + fi + + mkdir -p "${croot}/${imagename}" + log_begin_msg "Mounting \"${image}\" on \"${croot}${imagename}\" via \"${backdev}\"" + mount -t "${fstype}" -o ro,noatime "${backdev}" "${croot}/${imagename}" || panic "Can not mount ${backdev} (${image}) on ${croot}/${imagename}" && rofsstring="${croot}/${imagename}=${roopt}:${rofsstring}" && rofslist="${croot}/${imagename} ${rofslist}" + log_end_msg + fi + done + else + # we have a plain root system + mkdir -p "${croot}/filesystem" + log_begin_msg "Mounting \"${image_directory}\" on \"${croot}/filesystem\"" + mount -t $(get_fstype "${image_directory}") -o ro,noatime "${image_directory}" "${croot}/filesystem" || panic "Can not mount ${image_directory} on ${croot}/filesystem" && rofsstring="${croot}/filesystem=${roopt}:${rofsstring}" && rofslist="${croot}/filesystem ${rofslist}" + # probably broken: + mount -o bind ${croot}/filesystem $mountpoint + log_end_msg + fi + + rofsstring=${rofsstring%:} + + mkdir -p /cow + + # Looking for "${root_persistence}" device or file + if [ -n "${PERSISTENT}" ] && [ -z "${NOPERSISTENT}" ] + then + if [ -z "${QUICKUSBMODULES}" ] + then + # Load USB modules + num_block=$(wordCount "ls /sys/block") + + for module in sd_mod uhci-hcd ehci-hcd ohci-hcd usb-storage + do + modprobe -q -b ${module} + done + + if [ -x /sbin/udevadm ] + then + # lenny + udevadm trigger + udevadm settle + else + # etch + udevtrigger + udevsettle + fi + + # For some reason, udevsettle does not block in this scenario, + # so we sleep for a little while. + # + # See https://bugs.launchpad.net/ubuntu/+source/casper/+bug/84591 + for timeout in 5 4 3 2 1 + do + sleep 1 + + num_curr_block=$(wordCount "ls /sys/block") + + if [ ${num_curr_block} -gt ${num_block} ] + then + break + fi + done + fi + + # search for label and files (this could be hugely optimized) + cowprobe=$(find_cow_device "${root_persistence}") + if [ -b "${cowprobe}" ] + then + # Blacklist /cow device, to avoid inconsistent setups for overlapping snapshots + # makes sense to have both persistence for /cow and /home mounted, maybe also with + # snapshots to be sure to really store some e.g key config files, + # but not on the same media + blacklistdev="${cowprobe}" + PERSISTENCE_IS_ON="1" + export PERSISTENCE_IS_ON + fi + # homecow just mount something on /home, this should be generalized some way + homecow=$(find_cow_device "${home_persistence}" "${blacklistdev}") + if [ -b "${homecow}" ] + then + PERSISTENCE_IS_ON="1" + export PERSISTENCE_IS_ON + fi + root_snapdata=$(find_snap "${root_snapshot_label}" "${blacklistdev}") + # This second type should be removed when snapshot will get smarter, + # hence when "/etc/live-snapshot*list" will be supported also by + # ext2|ext3|ext4|jffs2 snapshot types. + home_snapdata=$(find_snap "${home_snapshot_label}" "${blacklistdev}") + + if [ -b "${cowprobe}" ] + then + cowdevice=${cowprobe} + cow_fstype=$(get_fstype "${cowprobe}") + cow_mountopt="rw,noatime" + else + log_warning_msg "Unable to find the persistent medium" + cowdevice="tmpfs" + cow_fstype="tmpfs" + cow_mountopt="rw,noatime,mode=755" + fi + elif [ -n "${NFS_COW}" ] && [ -z "${NOPERSISTENT}" ] + then + # check if there are any nfs options + if echo ${NFS_COW}|grep -q ',' + then + nfs_cow_opts="-o nolock,$(echo ${NFS_COW}|cut -d, -f2-)" + nfs_cow=$(echo ${NFS_COW}|cut -d, -f1) + else + nfs_cow_opts="-o nolock" + nfs_cow=${NFS_COW} + fi + mac="$(get_mac)" + if [ -n "${mac}" ] + then + cowdevice=$(echo ${nfs_cow}|sed "s/client_mac_address/${mac}/") + cow_fstype="nfs" + else + panic "unable to determine mac address" + fi + else + cowdevice="tmpfs" + cow_fstype="tmpfs" + cow_mountopt="rw,noatime,mode=755" + fi + + if [ "${cow_fstype}" = "nfs" ] + then + log_begin_msg \ + "Trying nfsmount ${nfs_cow_opts} ${cowdevice} /cow" + nfsmount ${nfs_cow_opts} ${cowdevice} /cow || \ + panic "Can not mount ${cowdevice} (n: ${cow_fstype}) on /cow" + else + mount -t ${cow_fstype} -o ${cow_mountopt} ${cowdevice} /cow || \ + panic "Can not mount ${cowdevice} (o: ${cow_fstype}) on /cow" + fi + + rofscount=$(wordCount "echo ${rofslist}") + + if [ -n "${EXPOSED_ROOT}" ] + then + if [ ${rofscount} -ne 1 ] + then + panic "only one RO file system supported with exposedroot: ${rofslist}" + fi + exposedrootfs=${rofslist%% } + + mount --bind ${exposedrootfs} ${rootmnt} || \ + panic "bind mount of ${exposedrootfs} failed" + + if [ -z "${SKIP_UNION_MOUNTS}" ] + then + cow_dirs='/var/tmp /var/lock /var/run /var/log /var/spool /home /var/lib/live' + else + cow_dirs='' + fi + + for dir in ${cow_dirs}; do + mkdir -p /cow${dir} + mount -t ${UNIONTYPE} \ + -o rw,noatime,dirs=/cow${dir}=rw:${exposedrootfs}${dir}=ro \ + ${UNIONTYPE} "${rootmnt}${dir}" || \ + panic "mount ${UNIONTYPE} on ${rootmnt}${dir} failed with option \ + rw,noatime,dirs=/cow${dir}=rw:${exposedrootfs}${dir}=ro" + done + else + mount -t ${UNIONTYPE} -o noatime,dirs=/cow=rw:${rofsstring} \ + ${UNIONTYPE} "${rootmnt}" || panic "mount ${UNIONTYPE} on \ + ${rootmnt} failed with option noatime,dirs=/cow=rw:${rofsstring}" + fi + + # Correct the permissions of /: + chmod 0755 "${rootmnt}" + + # tmpfs file systems + touch /etc/fstab + mkdir -p "${rootmnt}/live" + mount -t tmpfs tmpfs ${rootmnt}/live + + # Adding other custom mounts + if [ -n "${PERSISTENT}" ] && [ -z "${NOPERSISTENT}" ] + then + # directly mount /home + # FIXME: add a custom mounts configurable system + + if [ -b "${homecow}" ] + then + mount -t $(get_fstype "${homecow}") -o rw,noatime "${homecow}" "${rootmnt}/home" + export HOMEMOUNTED=1 # used to proper calculate free space in do_snap_copy() + else + log_warning_msg "Unable to find the persistent home medium" + fi + + # Look for other snapshots to copy in + try_snap "${root_snapdata}" "${rootmnt}" "ROOT" + # This second type should be removed when snapshot grow smarter + try_snap "${home_snapdata}" "${rootmnt}/home" "HOME" + fi + + if [ -n "${SHOWMOUNTS}" ] + then + for d in ${rofslist} + do + mkdir -p "${rootmnt}/live/${d##*/}" + + case d in + *.dir) + # do nothing # mount -o bind "${d}" "${rootmnt}/live/${d##*/}" + ;; + + *) + mount -o move "${d}" "${rootmnt}/live/${d##*/}" + ;; + esac + done + fi + + # shows cow fs on /cow for use by live-snapshot + mkdir -p "${rootmnt}/live/cow" + mount -o move /cow "${rootmnt}/live/cow" >/dev/null 2>&1 || mount -o bind /cow "${rootmnt}/live/cow" || log_warning_msg "Unable to move or bind /cow to ${rootmnt}/live/cow" +} + +check_dev () +{ + sysdev="${1}" + devname="${2}" + skip_uuid_check="${3}" + + if [ -z "${devname}" ] + then + devname=$(sys2dev "${sysdev}") + fi + + if [ -d "${devname}" ] + then + mount -o bind "${devname}" $mountpoint || continue + + if is_live_path $mountpoint + then + echo $mountpoint + return 0 + else + umount $mountpoint + fi + fi + + if [ -n "${LIVE_MEDIA_OFFSET}" ] + then + loopdevname=$(setup_loop "${devname}" "loop" "/sys/block/loop*" "${LIVE_MEDIA_OFFSET}" '') + devname="${loopdevname}" + fi + + fstype=$(get_fstype "${devname}") + + if is_supported_fs ${fstype} + then + mountOpt="rw,noatime" + test "$fstype" = "vfat" && mountOpt="$mountOpt,umask=000" + mount -t ${fstype} -o ${mountOpt} "${devname}" ${mountpoint} || continue + + if is_live_path ${mountpoint} && \ + ([ "${skip_uuid_check}" ] || matches_uuid ${mountpoint}) + then + echo ${mountpoint} + return 0 + else + umount ${mountpoint} + fi + fi + + if [ -n "${LIVE_MEDIA_OFFSET}" ] + then + losetup -d "${loopdevname}" + fi + + return 1 +} + +find_livefs () +{ + timeout="${1}" + + # don't start autodetection before timeout has expired + if [ -n "${LIVE_MEDIA_TIMEOUT}" ] + then + if [ "${timeout}" -lt "${LIVE_MEDIA_TIMEOUT}" ] + then + return 1 + fi + fi + + # first look at the one specified in the command line + case "${LIVE_MEDIA}" in + removable-usb) + for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)") + do + if [ "$(cat ${sysblock}/removable)" = "1" ] + then + if readlink ${sysblock} | grep -q usb || + readlink ${sysblock}/device | grep -q usb # linux < 2.6.29 + then + for dev in $(subdevices "${sysblock}") + do + if check_dev "${dev}" + then + return 0 + fi + done + fi + fi + done + ;; + + removable) + for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)") + do + if [ "$(cat ${sysblock}/removable)" = "1" ] + then + for dev in $(subdevices "${sysblock}") + do + if check_dev "${dev}" + then + return 0 + fi + done + fi + done + ;; + + *) + if [ ! -z "${LIVE_MEDIA}" ] + then + if check_dev "null" "${LIVE_MEDIA}" "skip_uuid_check" + then + return 0 + fi + fi + ;; + esac + + # or do the scan of block devices + for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)") + do + devname=$(sys2dev "${sysblock}") + fstype=$(get_fstype "${devname}") + + cdrom="1" + if [ -x /lib/udev/cdrom_id ] + then + /lib/udev/cdrom_id ${devname} > /dev/null + cdrom=$? + fi + + if [ "$cdrom" -eq "0" ] + then + if check_dev "null" "${devname}" + then + return 0 + fi + elif is_nice_device "${sysblock}" + then + for dev in $(subdevices "${sysblock}") + do + if check_dev "${dev}" + then + return 0 + fi + done + elif [ "${fstype}" = "squashfs" -o \ + "${fstype}" = "ext2" -o \ + "${fstype}" = "ext3" -o \ + "${fstype}" = "ext4" -o \ + "${fstype}" = "jffs2" ] + then + # This is an ugly hack situation, the block device has + # an image directly on it. It's hopefully + # live-initramfs, so take it and run with it. + ln -s "${devname}" "${devname}.${fstype}" + echo "${devname}.${fstype}" + return 0 + fi + done + + return 1 +} + +set_usplash_timeout () +{ + if [ -x /sbin/usplash_write ] + then + /sbin/usplash_write "TIMEOUT 120" + else if [ -x /sbin/splashy_update ] ; then + /sbin/splashy_update "TIMEOUT 120" + fi ; fi +} + +integrity_check () +{ + media_mountpoint="${1}" + + log_begin_msg "Checking media integrity" + + cd ${media_mountpoint} + /bin/md5sum -c md5sum.txt < /dev/tty8 > /dev/tty8 + RC="${?}" + + log_end_msg + + if [ "${RC}" -eq 0 ] + then + log_success_msg "Everything ok, will reboot in 10 seconds." + sleep 10 + cd / + umount ${media_mountpoint} + sync + echo u > /proc/sysrq-trigger + echo b > /proc/sysrq-trigger + else + panic "Not ok, a media defect is likely, switch to VT8 for details." + fi +} + +mountroot () +{ + if [ -x /scripts/local-top/cryptroot ]; then + /scripts/local-top/cryptroot + fi + + exec 6>&1 + exec 7>&2 + exec > live.log + exec 2>&1 + tail -f live.log >&7 & + tailpid="${!}" + + # Ensure 'panic' function is overridden + . /scripts/live-functions + + Arguments + + set_usplash_timeout + + maybe_break live-premount + log_begin_msg "Running /scripts/live-premount" + run_scripts /scripts/live-premount + log_end_msg + + # Needed here too because some things (*cough* udev *cough*) + # changes the timeout + + set_usplash_timeout + + if [ ! -z "${NETBOOT}" ] || [ ! -z "${FETCH}" ] || [ ! -z "${HTTPFS}" ] || [ ! -z "${FTPFS}" ] + then + if do_netmount + then + livefs_root="${mountpoint}" + else + panic "Unable to find a live file system on the network" + fi + else + if [ -n "${PLAIN_ROOT}" ] && [ -n "${ROOT}" ] + then + # Do a local boot from hd + livefs_root=${ROOT} + else + # Scan local devices for the image + i=0 + while [ "$i" -lt 60 ] + do + livefs_root=$(find_livefs ${i}) + + if [ -n "${livefs_root}" ] + then + break + fi + + sleep 1 + i="$(($i + 1))" + done + fi + fi + + if [ -z "${livefs_root}" ] + then + panic "Unable to find a medium containing a live file system" + fi + + if [ "${INTEGRITY_CHECK}" ] + then + integrity_check "${livefs_root}" + fi + + if [ "${TORAM}" ] + then + live_dest="ram" + elif [ "${TODISK}" ] + then + live_dest="${TODISK}" + fi + + if [ "${live_dest}" ] + then + log_begin_msg "Copying live media to ${live_dest}" + copy_live_to "${livefs_root}" "${live_dest}" + log_end_msg + fi + + if [ -n "${MODULETORAMFILE}" ] || [ -n "${PLAIN_ROOT}" ] + then + setup_unionfs "${livefs_root}" "${rootmnt}" + else + mac="$(get_mac)" + mac="$(echo ${mac} | sed 's/-//g')" + mount_images_in_directory "${livefs_root}" "${rootmnt}" "${mac}" + fi + + log_end_msg + + maybe_break live-bottom + log_begin_msg "Running /scripts/live-bottom\n" + + run_scripts /scripts/live-bottom + log_end_msg + + exec 1>&6 6>&- + exec 2>&7 7>&- + kill ${tailpid} + [ -w "${rootmnt}/var/log/" ] && cp live.log "${rootmnt}/var/log/" 2>/dev/null +} diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/02etc_live_conf b/tools/XBMCLive/live-initramfs/scripts/live-bottom/02etc_live_conf new file mode 100755 index 0000000000..815e37971a --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/02etc_live_conf @@ -0,0 +1,51 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +. /scripts/live-functions + +log_begin_msg "Copying config on real root fs" + +# live-initramfs script + +if [ -f /etc/live.conf ] +then + if [ ! -z "${LIVECONF}" ] + then + # Updating live.conf + sed -i -e 's/\(USERNAME="\).*"/\1'"${USERNAME}"'"/g' \ + -e 's/\(USERFULLNAME="\).*"/\1'"${USERFULLNAME}"'"/g' \ + -e 's/\(HOSTNAME="\).*"/\1'"${HOSTNAME}"'"/g' \ + /etc/live.conf + fi + + cp -p /etc/live.conf /root/etc/live.conf +else + +cat > /root/etc/live.conf << EOF +export USERNAME="${USERNAME}" +export USERFULLNAME="${USERFULLNAME}" +export HOSTNAME="${HOSTNAME}" +EOF + +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/02timezone b/tools/XBMCLive/live-initramfs/scripts/live-bottom/02timezone new file mode 100755 index 0000000000..64faf3b8de --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/02timezone @@ -0,0 +1,60 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOTIMEZONE}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Setting timezone" + +# live-initramfs script + +if [ -n "${TIMEZONE}" ] +then + area="$(echo ${TIMEZONE} | cut -f1 -d '/')" + zone="$(echo ${TIMEZONE} | cut -f2 -d '/')" + +chroot /root debconf-communicate -fnoninteractive live-initramfs > /dev/null << EOF +set tzdata/Areas ${area} +set tzdata/Zones/${area} ${zone} +EOF + + cp -f /root/usr/share/zoneinfo/${area}/${zone} /root/etc/localtime +else + +chroot /root debconf-communicate -fnoninteractive live-initramfs > /dev/null << EOF +set tzdata/Areas Etc +set tzdata/Zones/Etc UTC +EOF + + cp -f /root/usr/share/zoneinfo/UTC /root/etc/localtime +fi + +if [ -n "${UTC}" ] +then + sed -i -e "s/UTC=.*/UTC=${UTC}/" /root/etc/default/rcS +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/05mountpoints b/tools/XBMCLive/live-initramfs/scripts/live-bottom/05mountpoints new file mode 100755 index 0000000000..ce151e19e8 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/05mountpoints @@ -0,0 +1,36 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +. /scripts/live-functions + +log_begin_msg "Moving mount points" + +# live-initramfs script + +# Move to the new root filesystem so that programs there can get at it. +if [ ! -d /root/live/image ] +then + mkdir -p /root/live/image + mount --move /live/image /root/live/image +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/06hostname b/tools/XBMCLive/live-initramfs/scripts/live-bottom/06hostname new file mode 100755 index 0000000000..b14703a98c --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/06hostname @@ -0,0 +1,62 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOHOSTS}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Setting hostname" + +# live-initramfs script + +# Change hostname only if it is not set +if [ ! -f /root/etc/hostname ] || grep -qs localhost\.localdomain /root/etc/hostname +then + echo "${HOSTNAME}" > /root/etc/hostname +else + HOSTNAME="$(cat /root/etc/hostname)" + really_export HOSTNAME +fi + +# Create /etc/hosts only if it is not present or empty +if [ ! -s /root/etc/hosts ] +then + cat > /root/etc/hosts << EOF +127.0.0.1 localhost +127.0.1.1 ${HOSTNAME} + +# The following lines are desirable for IPv6 capable hosts +::1 ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +ff02::3 ip6-allhosts +EOF +fi + +hostname "${HOSTNAME}" + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/08persistence_excludes b/tools/XBMCLive/live-initramfs/scripts/live-bottom/08persistence_excludes new file mode 100755 index 0000000000..b7aac9226e --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/08persistence_excludes @@ -0,0 +1,77 @@ +#!/bin/sh + +# Persistence enhancer script +# This script saves precious time on slow persistence devices/image files +# and writes on flash based device. +# a tmpfs on $PERSTMP is mounted and directories listed in +# /etc/live-persistence.binds will be copied there and then bind mounted back. + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -z "${PERSISTENT}" ] || [ -n "${NOPERSISTENT}" ] || [ -z "${PERSISTENCE_IS_ON}" ] || [ ! -f /root/etc/live-persistence.binds ] +then + exit 0 +fi + +. /scripts/live-functions + +# live-initramfs script + +dirs="$(sed -e '/^ *$/d' -e '/^#.*$/d' /root/etc/live-persistence.binds | tr '\n' '\0')" +if [ -z "${dirs}" ] +then + exit 0 +fi + +log_begin_msg "Moving persistence bind mounts" + +PERSTMP="/root/live/persistence-binds" +CPIO="/bin/cpio" + +if [ ! -d "${PERSTMP}" ] +then + mkdir -p "${PERSTMP}" +fi + +mount -t tmpfs tmpfs "${PERSTMP}" + +for dir in $(echo "${dirs}" | tr '\0' '\n') +do + if [ ! -e "/root/${dir}" ] && [ ! -L "/root/${dir}" ] + then + # directory do not exists, create it + mkdir -p "/root/${dir}" + elif [ ! -d "/root/${dir}" ] + then + # it is not a directory, skip it + break + fi + + # Copy previous content if any + cd "/root/${dir}" + find . -print0 | ${CPIO} -pumd0 "${PERSTMP}/${dir}" + cd "${OLDPWD}" + + # Bind mount it to origin + mount -o bind "${PERSTMP}/${dir}" "/root/${dir}" +done + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/10adduser b/tools/XBMCLive/live-initramfs/scripts/live-bottom/10adduser new file mode 100755 index 0000000000..92950707e7 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/10adduser @@ -0,0 +1,120 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOUSER}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Adding live session user" + +# live-initramfs script + +user_crypted="8Ab05sVQ4LLps" # as in $(echo "live" | mkpasswd -s) + +# U6aMy0wojraho is just a blank password +chroot /root debconf-communicate -fnoninteractive live-initramfs > /dev/null << EOF +set passwd/make-user true +set passwd/root-password-crypted * +set passwd/user-password-crypted ${user_crypted} +set passwd/user-fullname ${USERFULLNAME} +set passwd/username ${USERNAME} +set passwd/user-uid 1000 +EOF + +chroot /root /usr/bin/env -i HOME="/root" \ + TERM="${TERM}" PATH="/usr/sbin:/usr/bin:/sbin:/bin" \ + /usr/lib/user-setup/user-setup-apply 2>&1 \ + | grep -v "Shadow passwords are now on" + +# Clear out debconf database again to avoid confusing ubiquity later. +chroot /root debconf-communicate -fnoninteractive live-initramfs > /dev/null << EOF +set passwd/make-user +set passwd/root-password-crypted +set passwd/user-password-crypted +set passwd/user-fullname +set passwd/username +set passwd/user-uid +EOF + +if ! grep -qs "${USERNAME}" /root/etc/passwd +then + echo "The default user (${USERNAME}) is not present," + first_user=$(grep '^[^:]*:[^:]*:[12]\?[0-9][0-9][0-9][0-9]:' /root/etc/passwd | head -1 | cut -f1 -d ':') + if [ -n "${first_user}" ]; + then + echo "setting default user to: ${first_user}." + USERNAME="${first_user}" + really_export USERNAME + else + echo "no other valid users found, disabling autologin." + NOAUTOLOGIN="Yes" + NOXAUTOLOGIN="Yes" + USERNAME="" + really_export NOAUTOLOGIN + really_export NOXAUTOLOGIN + really_export USERNAME + log_end_msg + exit 0 + fi +fi + +if [ -z "${NOSUDO}" ] +then + if ! grep -q "${USERNAME}" /root/etc/sudoers + then + echo "${USERNAME} ALL=(ALL) NOPASSWD: ALL" >> /root/etc/sudoers + + chroot /root sudo -u "${USERNAME}" sh -c "echo 'SU_TO_ROOT_SU=sudo' >> /home/${USERNAME}/.su-to-rootrc" + + if [ -x /root/usr/bin/gconftool-2 ] + then + chroot /root sudo -u "${USERNAME}" gconftool-2 -s -t bool /apps/gksu/sudo-mode true + chroot /root sudo -u "${USERNAME}" gconftool-2 -s -t bool /apps/gksu/display-no-pass-info false + fi + +chroot /root sudo -u "${USERNAME}" sh -c "umask 0077 && mkdir -p /home/${USERNAME}/.kde/share/config && cat > /home/${USERNAME}/.kde/share/config/kdesurc" << EOF +[super-user-command] +super-user-command=sudo +EOF + + if [ -f /root/usr/share/apps/konsole/sumc.desktop ] + then + chroot /root sudo -u "${USERNAME}" sh -c "umask 0077 && mkdir -p /home/${USERNAME}/.kde/share/apps/konsole && sed -e's/Exec=su.*$/Exec=sudo mc -c/' /usr/share/apps/konsole/sumc.desktop > /home/${USERNAME}/.kde/share/apps/konsole/sumc.desktop" + fi + + if [ -f /root/usr/share/apps/konsole/su.desktop ] + then + chroot /root sudo -u "${USERNAME}" sh -c "umask 0077 && mkdir -p /home/${USERNAME}/.kde/share/apps/konsole && sed -e's/Exec=su.*$/Exec=sudo -i/' /usr/share/apps/konsole/su.desktop > /home/${USERNAME}/.kde/share/apps/konsole/su.desktop" + fi + fi +fi + +if [ -L /root/home/${USERNAME}/Examples ] +then + chroot /root install -o ${USERNAME} -g ${USERNAME} -d /home/${USERNAME}/Desktop/ + mv /root/home/${USERNAME}/Examples /root/home/${USERNAME}/Desktop/ +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/12fstab b/tools/XBMCLive/live-initramfs/scripts/live-bottom/12fstab new file mode 100755 index 0000000000..701ed1edeb --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/12fstab @@ -0,0 +1,102 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" +FSTAB=/root/etc/fstab + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +. /scripts/live-functions + +if [ -n "${NOFSTAB}" ] +then + exit 0 +fi + +log_begin_msg "Configuring fstab" + +# live-initramfs script + +# Create a fake fstab only if it doesn't exist or if its the debootstrap template +if [ ! -f "${FSTAB}" ] || grep -qs 'UNCONFIGURED FSTAB FOR BASE SYSTEM' "${FSTAB}" +then + +cat > ${FSTAB} << EOF +# /etc/fstab: static file system information. +# +# <file system> <mount point> <type> <options> <dump> <pass> + +EOF + +fi + +if ! grep -qs "^${UNIONTYPE}" "${FSTAB}" +then + echo "${UNIONTYPE} / ${UNIONTYPE} rw 0 0" >> "${FSTAB}" +fi + +if ! grep -qs "^tmpfs /tmp" "${FSTAB}" +then + echo "tmpfs /tmp tmpfs nosuid,nodev 0 0" >> "${FSTAB}" +fi + +if [ -z "${NOSWAP}" ] +then + devices="" + + for device in /dev/[hs]d[a-z][0-9]* + do + if ! [ -b "${device}" ] + then + continue + fi + + /lib/udev/blkid ${device%%[0-9]*} 2>/dev/null | grep -q "^ID_FS_USAGE=raid" && continue + + magic=$(/bin/dd if="${device}" bs=4086 skip=1 count=1 2>/dev/null | /bin/dd bs=10 count=1 2>/dev/null) || continue + + if [ "${magic}" = "SWAPSPACE2" -o "${magic}" = "SWAP-SPACE" ] + then + #log "Found ${device}" + devices="${devices} ${device}" + fi + done + + # Remove all auto swap entries + if grep -qs "swap swap" "${FSTAB}" + then + grep -v "swap swap" "${FSTAB}" > "${FSTAB}".tmp + mv "${FSTAB}".tmp "${FSTAB}" + fi + + # Add new swap entries + for device in ${devices} + do + echo "${device} swap swap defaults 0 0" >> "${FSTAB}" + done +fi + +# disabled for now +#rm -f /root/etc/rcS.d/S*checkroot.sh + +if [ "${NOFASTBOOT}" != "Yes" ] +then + touch root/fastboot +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/14locales b/tools/XBMCLive/live-initramfs/scripts/live-bottom/14locales new file mode 100755 index 0000000000..022a605626 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/14locales @@ -0,0 +1,131 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOLOCALES}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Setting up locales" + +# Cosmetic line wrapping for output of local-gen +echo + +# live-initramfs script + +if [ -e /root/etc/default/locale ] +then + grep_file=/root/etc/default/locale +elif [ -e /root/etc/environment ] +then + # Old locales policy + grep_file=/root/etc/environment +fi + +if [ -n "${grep_file}" ] +then + # use rootfs configured locale + locale=$(grep -s 'LANG=' ${grep_file} | sed s/'LANG='// | tr -d '"' ) +fi + +if [ -n "${LOCALE}" ] +then + locale="${LOCALE}" + set_locale="true" +fi + +if [ -z "${locale}" ] +then + # Set a default one + locale=en_US.UTF-8 + set_locale="true" +fi + +if [ "${set_locale}" ] +then + if echo "${locale}" | grep -sqE '^[[:lower:]]{2}$' + then + # input is like "locale=it", so we will convert and setup also the keyboard if not already set + if [ -z "${KBD}" ] + then + # FIXME: look if this keyb is supported + KBD="${locale}" + really_export KBD + fi + + uploc=$(echo "${locale}" | tr '[a-z]' '[A-Z]') + locale="${locale}_${uploc}.UTF-8" + fi + + LANG= + language="$(echo ${locale} | cut -d. -f1)" + eval $(awk '/^'"${locale}"'/ { print "LANG=" $1 " codepage=" $2; exit; }' /root/usr/share/i18n/SUPPORTED) + + if [ -z "${LANG}" ] + then + # Try and fallback to another codepage for this language. + eval $(awk '/^'"${language}"'/ { print "LANG=" $1 " codepage=" $2; exit; }' /root/usr/share/i18n/SUPPORTED) + + if [ -n "${LANG}" ] + then + log_warning_msg "Choosing locale '${LANG}' as '${locale}' is unsupported." + fi + fi + + if [ -z "${LANG}" ] + then + log_warning_msg "Locale '${locale}' is unsupported." + codepage="UTF-8" + language="en_US" + locale="${language}.${codepage}" + LANG="${language}.${codepage}" + fi + + if [ -d /root/etc/default/kdm.d/ ] + then + if ! grep -qs "^LANGUAGE" "${LANG}" + then + printf 'LANGUAGE=%s\n' "${LANG}" >> /root/etc/default/kdm.d/live-autologin + fi + elif [ -f /root/etc/kde3/kdm/kdmrc ] + then + sed -i -r -e "s/#Language=.*/Language=${language}/" \ + /root/etc/kde3/kdm/kdmrc + fi + + really_export LANG + + printf 'LANG="%s"\n' "${LANG}" > /root/etc/default/locale + printf 'LANG="%s"\n' "${LANG}" > /root/etc/environment + printf '%s %s\n' "${LANG}" "${codepage}" > /root/etc/locale.gen + + if [ -z "${SILENT}" ] + then + chroot /root /usr/sbin/locale-gen + else + chroot /root /usr/sbin/locale-gen > /dev/null 2>&1 + fi +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/15autologin b/tools/XBMCLive/live-initramfs/scripts/live-bottom/15autologin new file mode 100755 index 0000000000..38c3a8f32d --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/15autologin @@ -0,0 +1,89 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +. /live.vars + +if [ -n "${NOXAUTOLOGIN}" ] || [ -z "${USERNAME}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Setting up automatic login" + +# live-initramfs script + +# chroot needed to handle symlinks correctly +if chroot /root [ -f /etc/gdm/gdm-cdd.conf ] +then + GDMCONF=/etc/gdm/gdm-cdd.conf +else + GDMCONF=/etc/gdm/gdm.conf +fi + +# chroot needed to handle symlinks correctly +if chroot /root [ -f ${GDMCONF} ] +then + # true hack ! -- nohar + chroot /root cp /usr/share/gdm/defaults.conf /etc/gdm/gdm.conf + + # Configure GDM autologin + chroot /root \ + sed -i -e "s/^AutomaticLoginEnable=.*\$/AutomaticLoginEnable=true/" \ + -e "s/^AutomaticLogin=.*\$/AutomaticLogin=${USERNAME}/" \ + -e "s/^TimedLoginEnable=.*\$/TimedLoginEnable=true/" \ + -e "s/^TimedLogin=.*\$/TimedLogin=${USERNAME}/" \ + -e "s/^TimedLoginDelay=.*\$/TimedLoginDelay=10/" \ + ${GDMCONF} +fi + +if [ -d /root/etc/default/kdm.d/ ] +then + if ! grep -qs "^AUTOLOGIN" /root/etc/default/kdm.d/live-autologin + then + +cat >> /root/etc/default/kdm.d/live-autologin << EOF +AUTOLOGINUSER=${USERNAME} +AUTOLOGINAGAIN=true +AUTOLOGINDELAY=0 +EOF + + fi + +elif [ -f /root/etc/kde3/kdm/kdmrc ] +then + # Configure KDM autologin + sed -i -r -e "s/^#?AutoLoginEnable=.*\$/AutoLoginEnable=true/" \ + -e "s/^#?AutoLoginUser=.*\$/AutoLoginUser=${USERNAME}/" \ + -e "s/^#?AutoReLogin=.*\$/AutoReLogin=true/" \ + /root/etc/kde3/kdm/kdmrc +elif [ -f /root/etc/kde4/kdm/kdmrc ] +then + # Configure KDM-KDE4 autologin + sed -i -r -e "s/^#?AutoLoginEnable=.*\$/AutoLoginEnable=true/" \ + -e "s/^#?AutoLoginUser=.*\$/AutoLoginUser=$USERNAME/" \ + -e "s/^#?AutoReLogin=.*\$/AutoReLogin=true/" \ + /root/etc/kde4/kdm/kdmrc +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/16umountfs b/tools/XBMCLive/live-initramfs/scripts/live-bottom/16umountfs new file mode 100755 index 0000000000..64ad99da0a --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/16umountfs @@ -0,0 +1,38 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +. /live.vars + +. /scripts/live-functions + +log_begin_msg "Disabling umountfs for live specific filesystems" + +# live-initramfs script + +if [ -e /root/etc/init.d/umountfs ] +then + sed -i -e 's#pioodl $TMPFS_MTPTS)#pioodl $TMPFS_MTPTS | sed -e "s@\\ @\\n@" | grep -v ^/live)#' \ + -e 's#pioodl $REG_MTPTS)#pioodl $REG_MTPTS | sed -e "s@\\ @\\n@" | grep -v ^/live | grep -v ^/filesystem) /#' \ + /root/etc/init.d/umountfs +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/19keyboard b/tools/XBMCLive/live-initramfs/scripts/live-bottom/19keyboard new file mode 100755 index 0000000000..d465698da8 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/19keyboard @@ -0,0 +1,103 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOCONSOLEKEYBOARD}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Setting up console keyboard" + +# live-initramfs script + +kbd= +cslayout= +csvariant= +csmodel= + +# commandline +if [ -n "${KBD}" ] +then + kbd="${KBD}" +else + kbd=us +fi + +really_export kbd + +if [ -n "${KLAYOUT}" ] +then + cslayout="${KLAYOUT}" +fi + +if [ -n "${KVARIANT}" ] +then + csvariant="${KVARIANT}" +fi + +if [ -n "${KMODEL}" ] +then + csmodel="${KMODEL}" +fi + +if [ -x /root/bin/setupcon ] && [ -f /root/etc/default/console-setup ] +then + if [ "${cslayout}" ] + then + chroot /root sed -i "s/^XKBLAYOUT=.*/XKBLAYOUT=\"${cslayout}\"/" \ + /etc/default/console-setup + + if [ "${csvariant}" ] + then + chroot /root sed -i "s/^XKBVARIANT=.*/XKBVARIANT=\"${csvariant}\"/" \ + /etc/default/console-setup + else + live-preseed /root console-setup/variantcode '' false + fi + + if [ "${csmodel}" ] + then + chroot /root sed -i "s/^XKBMODEL=.*/XKBMODEL=\"${csmodel}\"/" \ + /etc/default/console-setup + else + live-preseed /root console-setup/modelcode '' false + fi + else + live-preseed /root console-setup/layoutcode '' false + live-preseed /root console-setup/variantcode '' false + live-preseed /root console-setup/modelcode '' false + fi + + live-preseed /root console-setup/optionscode '' false + live-preseed /root console-setup/codesetcode '' false + + sed -i 's/CONSOLE_SCREEN=$/CONSOLE_SCREEN=setupcon/; t END; b; : END; n; b END' /root/etc/init.d/usplash +elif [ -e /root/usr/sbin/install-keymap ] +then + chroot /root /usr/sbin/install-keymap ${kbd} + live-preseed /root debian-installer/keymap "${kbd}" + live-preseed /root kbd-chooser/method "${kbd}" +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/20xconfig b/tools/XBMCLive/live-initramfs/scripts/live-bottom/20xconfig new file mode 100755 index 0000000000..f6a3f8d58c --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/20xconfig @@ -0,0 +1,92 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOXAUTOCONFIG}" ] +then + exit 0 +fi + +. /scripts/live-functions + +# live-initramfs script + +if [ "${TERM_TYPE}" = "serial" ] +then + # Don't bother trying to configure or start X on a serial console + rm -f /root/etc/rc?.d/S??[gkx]dm + exit 0 +fi + +if [ -n "${TEXTONLY}" ] +then + exit 0 +fi + +if [ ! -x /root/usr/bin/X ] +then + exit 0 +fi + +log_begin_msg "Configuring X" + +locale=en_US.UTF-8 + +mount -o bind /sys /root/sys +mount -o bind /proc /root/proc +mount -o bind /dev /root/dev + +if [ -n "${XDEBCONF}" -a -x /root/usr/sbin/xdebconfigurator ] +then + # xdebconfigurator + chroot /root /usr/sbin/xdebconfigurator +fi + +if [ -n "${KOPTIONS}" ] +then + setoptions="set xserver-xorg/config/inputdevice/keyboard/options ${KOPTIONS}" +fi + +if [ -n "${KVARIANT}" ] +then + setvariant="set xserver-xorg/config/inputdevice/keyboard/variant ${KVARIANT}" +fi + +if [ -n "${KMODEL}" ] +then + setmodel="set xserver-xorg/config/inputdevice/keyboard/model ${KMODEL}" +fi + +chroot /root debconf-communicate -fnoninteractive live-initramfs > /dev/null << EOF +set xserver-xorg/config/inputdevice/keyboard/layout ${kbd} +${setvariant} +${setmodel} +${setoptions} +EOF + +live-reconfigure /root xserver-xorg 2>&1 \ + | grep -v "overwriting possibly-customised configuration" \ + | grep -v "file; backup in /etc/X11/xorg.conf" +umount /root/sys +umount /root/proc +umount /root/dev + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/21xdriver b/tools/XBMCLive/live-initramfs/scripts/live-bottom/21xdriver new file mode 100755 index 0000000000..105f5b24d3 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/21xdriver @@ -0,0 +1,51 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOXAUTOCONFIG}" ] || [ ! -x /root/usr/bin/X ] || [ -z "${XDRIVER}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Configuring X video driver" + +# live-initramfs script + +. /live.vars + +mount -o bind /sys /root/sys +mount -o bind /proc /root/proc +mount -o bind /dev /root/dev + +chroot /root debconf-communicate -fnoninteractive live-initramfs > /dev/null << EOF +set xserver-xorg/autodetect_video_card false +set xserver-xorg/config/device/driver ${XDRIVER} +EOF + +chroot /root dexconf + +umount /root/sys +umount /root/proc +umount /root/dev + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/21xvidemode b/tools/XBMCLive/live-initramfs/scripts/live-bottom/21xvidemode new file mode 100755 index 0000000000..489fc5c6ac --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/21xvidemode @@ -0,0 +1,68 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOXAUTOCONFIG}" ] +then + exit 0 +fi + +if [ ! -x /root/usr/bin/X ] +then + exit 0 +fi + +[ -n "$XVIDEOMODE" ] || exit + +. /scripts/live-functions + +log_begin_msg "Configuring X video modes" + +# live-initramfs script + +. /live.vars + +if [ $(cat /root/etc/debian_version | sed 's|\..*$||') -ge 4 ] +then + # lenny or newer + if [ -x "$(which xrandr 2>/dev/null)" ] + then + echo "xrandr -s ${XVIDEOMODE} || /bin/true" >> /root/etc/X11/Xsession.d/21xvidemode + fi +else + # etch + mount -o bind /sys /root/sys + mount -o bind /proc /root/proc + mount -o bind /dev /root/dev + +chroot /root debconf-communicate -fnoninteractive live-initramfs > /dev/null << EOF +set xserver-xorg/config/monitor/mode-list ${XVIDEOMODE} +set xserver-xorg/config/display/modes ${XVIDEOMODE} +EOF + + chroot /root dexconf + + umount /root/sys + umount /root/proc + umount /root/dev +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/22gnome_panel_data b/tools/XBMCLive/live-initramfs/scripts/live-bottom/22gnome_panel_data new file mode 100755 index 0000000000..bd0be26d9b --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/22gnome_panel_data @@ -0,0 +1,49 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOGNOMEPANEL}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Configuring gnome-panel-data" + +# live-initramfs script + +if [ -x /root/usr/sbin/laptop-detect ] +then + if chroot /root laptop-detect + then + live-reconfigure /root gnome-panel-data + fi +fi + +panel_version=$(chroot /root /usr/bin/dpkg-query -W --showformat='${Version}' gnome-panel-data 2>/dev/null) || panel_version="" + +if [ -n "${panel_version}" ] && [ -n "${USERNAME}" ] +then + chroot /root sudo -u "${USERNAME}" gconftool-2 -s -t bool /apps/panel/global/disable_lock_screen true +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/22screensaver b/tools/XBMCLive/live-initramfs/scripts/live-bottom/22screensaver new file mode 100755 index 0000000000..584d234c45 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/22screensaver @@ -0,0 +1,43 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOXSCREENSAVER}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Configuring screensaver" + +# live-initramfs script + +gnome_screensaver_version=$(chroot /root dpkg-query -W --showformat='${Version}' gnome-screensaver 2>/dev/null) || gnome_screensaver_version="" + +if [ -n "${gnome_screensaver_version}" ] +then + # Support legacy gconf value + chroot /root sudo -u "${USERNAME}" gconftool-2 -t bool -s /apps/gnome-screensaver/lock false + chroot /root sudo -u "${USERNAME}" gconftool-2 -t bool -s /apps/gnome-screensaver/lock_enabled false +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/23etc_modules b/tools/XBMCLive/live-initramfs/scripts/live-bottom/23etc_modules new file mode 100755 index 0000000000..2240a1bab5 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/23etc_modules @@ -0,0 +1,36 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +. /scripts/live-functions + +log_begin_msg "Preconfiguring /etc/modules" + +# live-initramfs script + +# load the right modules +case "${DPKG_ARCH}" in + powerpc|ppc64) + echo snd_powermac >> /root/etc/modules + ;; +esac + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/23networking b/tools/XBMCLive/live-initramfs/scripts/live-bottom/23networking new file mode 100755 index 0000000000..72aaf12e25 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/23networking @@ -0,0 +1,157 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NONETWORKING}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Preconfiguring networking" + +# live-initramfs script + +IFFILE="/root/etc/network/interfaces" + +if [ "${STATICIP}" = "frommedia" -a -e "${IFFILE}" ] +then + # will use existent /etc/network/interfaces + log_end_msg + exit 0 +fi + +cat > "${IFFILE}" << EOF +auto lo +iface lo inet loopback + +EOF + +if [ -x /sbin/udevadm ] +then + # lenny + udevadm trigger + udevadm settle +else + # etch + udevtrigger + udevsettle +fi + +if [ -z "${NETBOOT}" -a -n "${STATICIP}" -a "${STATICIP}" != "frommedia" ] +then + parsed=$(echo "${STATICIP}" | sed -e 's/:/ /g') + + for ifline in ${parsed} + do + ifname="$(echo ${ifline} | cut -f1 -d ',')" + ifaddress="$(echo ${ifline} | cut -f2 -d ',')" + ifnetmask="$(echo ${ifline} | cut -f3 -d ',')" + ifgateway="$(echo ${ifline} | cut -f4 -d ',')" + +cat >> "${IFFILE}" << EOF +auto ${ifname} +iface ${ifname} inet static + address ${ifaddress} + netmask ${ifnetmask} + gateway ${ifgateway} + +EOF + + done +else + if [ -z "${NETBOOT}" ] + then + # default, dhcp assigned + method="dhcp" + else + # make sure that the preconfigured interface would not get reassigned by dhcp + # on startup by ifup script - otherwise our root fs might be disconnected! + method="manual" + fi + + # iterate the physical interfaces and add them to the interfaces list + if [ "${method}" != dhcp ] || ([ ! -x /root/usr/sbin/NetworkManager ] && [ ! -x /root/usr/sbin/wicd ]) + then + for interface in /sys/class/net/eth* /sys/class/net/ath* /sys/class/net/wlan* + do + [ -e ${interface} ] || continue + i="$(basename ${interface})" + +cat >> "${IFFILE}" << EOF +auto ${i} +iface ${i} inet ${method} + +EOF + + done + fi + + if [ ! -f /root/etc/resolv.conf ] || [ -z "$(cat /root/etc/resolv.conf)" ] + then + if [ -f /netboot.config ] + then + # create a resolv.conf if it is not present or empty + cp /netboot.config /root/var/log/netboot.config + + rc_search=$(cat netboot.config | awk '/domain/{print $3}') + rc_server0=$(cat netboot.config | awk '/dns0/{print $5}') + rc_server1=$(cat netboot.config | awk '/dns0/{print $8}') + rc_server0="nameserver ${rc_server0}" + + if [ "${rc_server1}" = "0.0.0.0" ] + then + rc_server1="" + else + rc_server1="nameserver ${rc_server1}" + fi + +cat > /root/etc/resolv.conf << EOF +# /etc/resolv.conf +# Autogenerated by live-initramfs +search ${rc_search} +domain ${rc_search} +${rc_server0} +${rc_server1} +EOF + + cat /root/etc/resolv.conf >> /root/var/log/netboot.config + fi + fi +fi + +#if [ ! -x /root/usr/sbin/NetworkManager ] +#then +# for i in eth0 eth1 eth2 ath0 wlan0 +# do +# grep -q "iface ${i}" ${IFFILE} && continue +# +#cat >> "${IFFILE}" << EOF +#auto ${i} +#iface ${i} inet dhcp +# +#EOF +# +# done +#fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/24preseed b/tools/XBMCLive/live-initramfs/scripts/live-bottom/24preseed new file mode 100755 index 0000000000..2536bd0a34 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/24preseed @@ -0,0 +1,68 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOPRESEED}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Loading preseed file" + +# live-initramfs script + +if [ -e /preseed.cfg ] +then + chroot /root debconf-set-selections < /preseed.cfg +fi + +if [ -f "/root/${LOCATION}" ] +then + chroot /root debconf-set-selections < "/root/${LOCATION}" +fi + +if [ -n "${PRESEEDS}" ] +then + for preseed in ${PRESEEDS} + do + question="${preseed%%=*}" + value="${preseed#*=}" + + live-preseed /root "${question}" "${value}" + done +fi + +reply="$(echo "GET preseed/early_command" | chroot /root debconf-communicate -fnoninteractive live-initramfs)" + +if [ "${reply#0 }" != "${reply}" ] +then + reply="${reply#0 }" + sh -c "${reply}" +fi + +# Clear out debconf database backup files to save memory. +rm -f /root/var/cache/debconf/*.dat-old + +log_end_msg + +exit 0 diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/25configure_init b/tools/XBMCLive/live-initramfs/scripts/live-bottom/25configure_init new file mode 100755 index 0000000000..f55dd0e0c7 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/25configure_init @@ -0,0 +1,114 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +. /scripts/live-functions + +log_begin_msg "Setting up init" + +# live-initramfs script + +# Arrange for shells on virtual consoles, rather than login prompts + +if [ -z "${NOAUTOLOGIN}" ] && [ -n "${USERNAME}" ] +then + if [ ! -z "${LIVE_GETTY}" ] + then + if echo "${DEFCONSOLE}" | grep -qs ttyS + then + # AUTOMATIC SERIAL CONSOLE # + PORT=$(echo "${DEFCONSOLE}" | \ + sed -e 's%,.*%%') + SPEED=$(echo "${DEFCONSOLE}" | \ + sed -e 's%ttyS[0-9]\+,%%' \ + -e's%\([0-9]\+\).*%\1%') + + if ! ( sed -n -e'/^[^#]/p' /root/etc/inittab | grep -qs ":respawn:/sbin/getty.*${PORT}" ) + then + IDs="A B C D E F G H I J K L M N O P Q R S T Q U V V X Y Z 0 1 2 3 4 5 6 7 8 9" + + for ID1 in ${IDs} + do + for ID2 in ${IDs} + do + ID="${ID1}${ID2}" + + if ! grep "^${ID}:" /etc/inittab + then + #make sure it is not already in use + break 2 + fi + done + done + + echo "${ID}:2345:respawn:/sbin/live-getty -L ${PORT} ${SPEED} vt100" >> /root/etc/inittab + fi + fi + + if [ -f /root/etc/inittab ] + then + sed -i -e'/^[^#]/s%respawn:/sbin/getty%respawn:/sbin/live-getty%' /root/etc/inittab + fi + else + if [ -f /root/etc/inittab ] + then + sed -i -e "s|^\([^:]*:[^:]*:[^:]*\):.*getty.*\<\(tty[0-9]*\).*$|\1:/bin/login -f ${USERNAME} </dev/\2 >/dev/\2 2>\&1|" /root/etc/inittab + fi + + if [ "/root/etc/event.d/tty*" != "$(echo /root/etc/event.d/tty*)" ] + then + for f in /root/etc/event.d/tty* + do + sed -i -e "/^respawn$/!s|^respawn.*|respawn /bin/login -f ${USERNAME} </dev/$(basename ${f}) > /dev/$(basename ${f}) 2>\&1|" ${f} + sed -i -e "s|^exec.*|exec /bin/login -f ${USERNAME} </dev/$(basename ${f}) > /dev/$(basename ${f}) 2>\&1|" ${f} + done + fi + fi + + # Since we use autologin, lastlog doesn't make sense on the console. + sed -i '/^[^#].*pam_lastlog\.so/s/^/# /' /root/etc/pam.d/login +fi + +# do not try to remove files if using file-rc +if [ -d /root/etc/rc0.d ] +then + # This has the nice side effect of the cron.{daily,weekly,monthly} jobs in + # /etc/crontab remaining disabled, yet also not run by anacron + if [ -x /root/usr/sbin/anacron ] + then + chroot /root dpkg-divert --add --rename --quiet /usr/sbin/anacron + ln -s /bin/true /root/usr/sbin/anacron + fi + + # Avoid clobbering the user's clock + rm -f /root/etc/rc?.d/K??hwclock.sh +fi + +# Disable readahead since it doesn't play well with squashfs + unionfs +# use chmod instead of mv to not trigger unionfs bugs. +if [ -e /root/sbin/readahead-list ] +then + chmod -x /root/sbin/readahead-list +fi + +log_end_msg + +exit 0 diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/30accessibility b/tools/XBMCLive/live-initramfs/scripts/live-bottom/30accessibility new file mode 100755 index 0000000000..3ff3fda0d8 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/30accessibility @@ -0,0 +1,181 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOACCESSIBILITY}" ] +then + exit 0 +fi + +. /scripts/live-functions + +if [ -z "${USERNAME}" ] +then + echo "No default user for accessibility options." + exit 0 +fi + +log_begin_msg "Configuring accessibility options" + +# live-initramfs script + +gconf_version=$(chroot /root /usr/bin/dpkg-query -W --showformat='${Version}' gconf2 2>/dev/null) || gconf_version="" + +gct () +{ + if [ "${gconf_version}" ] + then + chroot /root sudo -u "${USERNAME}" gconftool-2 "${@}" + fi +} + +laptop_detect () +{ + if chroot /root /usr/sbin/laptop-detect + then + echo "orca.settings.orcaModifierKeys = orca.settings.LAPTOP_MODIFIER_KEYS" >> /root/home/$USERNAME/.orca/user-settings.py + echo "orca.settings.keyboardLayout = orca.settings.GENERAL_KEYBOARD_LAYOUT_LAPTOP" >> /root/home/$USERNAME/.orca/user-settings.py + fi +} + +remove_applet () +{ + # Code to remove an applet from the default panel setup + # This is rather hacky, but I can't think of a one or two line regular + # expression to do this any more efficiently. Patches welcome. In + # addition, setting these via gconf also doesn't work for some reason. + + local line_no prior_line next_line + + line_no="$(grep -n "<string>$1</string>" /root/usr/share/gconf/defaults/05_panel-default-setup.entries | cut -f 1 -d :)" + prior_line="$((line_no-1))" + next_line="$((line_no+1))" + + sed -i -n "${prior_line},${next_line}!p" /root/usr/share/gconf/defaults/05_panel-default-setup.entries + + chroot /root update-gconf-defaults +} + +case ${ACCESS} in + access=v1) + # Lesser Visual Impairment + gct -s -t string /desktop/gnome/interface/gtk_theme HighContrastLargePrint + gct -s -t string /desktop/gnome/interface/icon_theme HighContrast + gct -s -t string /desktop/gnome/interface/monospace_font_name "monospace 18" + gct -s -t string /desktop/gnome/interface/font_name "sans 18" + gct -s -t string /apps/metacity/general/theme Atlanta + gct -s -t string /desktop/gnome/background/picture_filename "" + gct -s -t string /desktop/gnome/background/picture_options none + gct -s -t string /desktop/gnome/background/primary_color \#666666 + gct -s -t string /desktop/gnome/background/secondary_color \#7F7F7F + gct -s -t string /desktop/gnome/background/color_shading_type solid + gct -s -t int /desktop/gnome/peripherals/mouse/cursor_size 48 + gct -s -t string /desktop/gnome/peripherals/mouse/cursor_theme whiteglass + ;; + + access=v2) + # Moderate Visual Impairment + gct -s -t bool /desktop/gnome/interface/accessibility true + gct -s -t bool /desktop/gnome/applications/at/visual/startup true + gct -s -t string /desktop/gnome/applications/at/visual/exec orca + gct -s -t bool /apps/gksu/disable-grab true + gct -s -t string /desktop/gnome/applications/window_manager/default /usr/bin/metacity + + if [ -x /root/usr/bin/orca ] + then + mkdir -p /root/home/${USERNAME}/.orca + echo "import orca.settings" >> /root/home/${USERNAME}/.orca/user-settings.py + echo "orca.settings.enableSpeech = False" >> /root/home/${USERNAME}/.orca/user-settings.py + echo "orca.settings.enableMagnifier = True" >> /root/home/${USERNAME}/.orca/user-settings.py + laptop_detect + chroot /root chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.orca + fi + ;; + + access=v3) + # Blindness + # Disabled for now, until we know eSpeak works. + #gct -s -t bool /desktop/gnome/sound/enable_esd false + gct -s -t bool /desktop/gnome/interface/accessibility true + gct -s -t bool /desktop/gnome/applications/at/visual/startup true + gct -s -t string /desktop/gnome/applications/at/visual/exec orca + gct -s -t bool /apps/gksu/disable-grab true + gct -s -t string /desktop/gnome/applications/window_manager/default /usr/bin/metacity + + remove_applet fast_user_switch + ;; + + braille=ask) + # Braille + gct -s -t bool /desktop/gnome/interface/accessibility true + gct -s -t bool /desktop/gnome/applications/at/visual/startup true + gct -s -t string /desktop/gnome/applications/at/visual/exec orca + gct -s -t bool /apps/gksu/disable-grab true + gct -s -t string /desktop/gnome/applications/window_manager/default /usr/bin/metacity + + if [ -x /root/usr/bin/orca ] + then + mkdir -p /root/home/${USERNAME}/.orca + echo "import orca.settings" >> /root/home/${USERNAME}/.orca/user-settings.py + echo "orca.settings.enableSpeech = False" >> /root/home/${USERNAME}/.orca/user-settings.py + echo "orca.settings.enableBraille = True" >> /root/home/${USERNAME}/.orca/user-settings.py + laptop_detect + chroot /root chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.orca + fi + + remove_applet fast_user_switch + ;; + + access=m1) + # Minor Motor Difficulties + gct -s -t bool /desktop/gnome/accessibility/keyboard/enable true + gct -s -t bool /desktop/gnome/accessibility/keyboard/mousekeys_enable true + gct -s -t bool /desktop/gnome/accessibility/keyboard/stickykeys_enable true + gct -s -t bool /desktop/gnome/accessibility/keyboard/stickykeys_modifier_beep true + gct -s -t bool /desktop/accessibility/gnome/keyboard/stickykeys_two_key_off false + gct -s -t bool /desktop/gnome/peripherals/keyboard/repeat true + gct -s -t int /desktop/gnome/peripherals/keyboard/delay 700 + gct -s -t int /desktop/gnome/peripherals/keyboard/rate 10 + gct -s -t bool /apps/gksu/disable-grab true + + if [ -e /root/etc/xdg/xfce4/mcs_settings/keyboard.xml ] + then + sed -i 's/0/1/' /root/etc/xdg/xfce4/mcs_settings/keyboard.xml + fi + ;; + + access=m2) + # Motor Difficulties - pointing devices + gct -s -t bool /desktop/gnome/accessibility/keyboard/enable true + gct -s -t bool /desktop/gnome/interface/accessibility true + gct -s -t bool /desktop/gnome/accessibility/keyboard/stickykeys_enable true + gct -s -t bool /desktop/gnome/accessibility/keyboard/stickykeys_modifier_beep false + gct -s -t bool /desktop/accessibility/gnome/keyboard/stickykeys_two_key_off false + gct -s -t list --list-type=string /desktop/gnome/accessibility/startup/exec_ats [onboard] + + if [ -e /root/etc/xdg/xfce4/mcs_settings/keyboard.xml ] + then + sed -i '/Sticky/ s/0/1/' /root/etc/xdg/xfce4/mcs_settings/keyboard.xml + fi + ;; +esac + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/31disable_update_notifier b/tools/XBMCLive/live-initramfs/scripts/live-bottom/31disable_update_notifier new file mode 100755 index 0000000000..e3630495d8 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/31disable_update_notifier @@ -0,0 +1,49 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOUPDATENOTIFIER}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Disabling update-notifier" + +# live-initramfs script + +# For GNOME, we divert away apt-check to avoid a regular 'apt-get update' +# equivalent in the live session. We want to run update-notifier for crash +# report handling. +chroot /root dpkg-divert --add --rename --quiet \ + /usr/lib/update-notifier/apt-check + +if [ -e /root/usr/lib/update-notifier/apt-check ] +then + ln -s /bin/true /root/usr/lib/update-notifier/apt-check +fi + +# For KDE, adept_notifier's only useful function at the moment is an +# 'apt-get update' equivalent, so we disable it entirely. +rm -f /root/usr/share/autostart/adept_notifier_auto.desktop + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/32disable_hibernation b/tools/XBMCLive/live-initramfs/scripts/live-bottom/32disable_hibernation new file mode 100755 index 0000000000..f4960e645a --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/32disable_hibernation @@ -0,0 +1,45 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOPOWERMANAGEMENT}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Configuring power management" + +# live-initramfs script + +gpm_version=$(chroot /root /usr/bin/dpkg-query -W --showformat='${Version}' gnome-power-manager 2>/dev/null) || panel_version="" + +if [ -n "${gpm_version}" ] && [ -n "${USERNAME}" ] +then + #live-reconfigure /root gnome-power-manager + # Gnome < 2.20 + chroot /root sudo -u "${USERNAME}" gconftool-2 -s -t bool /apps/gnome-power-manager/can_hibernate false + # Gnome >= 2.20 + chroot /root sudo -u "${USERNAME}" gconftool-2 -s -t bool /apps/gnome-power-manager/general/can_hibernate false +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/33enable_apport_crashes b/tools/XBMCLive/live-initramfs/scripts/live-bottom/33enable_apport_crashes new file mode 100755 index 0000000000..47e650d2fc --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/33enable_apport_crashes @@ -0,0 +1,39 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOPROGRAMCRASHES}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Enabling detection of crashes" + +# live-initramfs script + +if [ -e /root/etc/default/apport ] +then + sed -i 's/enabled=0/enabled=1/' /root/etc/default/apport +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/34disable_kpersonalizer b/tools/XBMCLive/live-initramfs/scripts/live-bottom/34disable_kpersonalizer new file mode 100755 index 0000000000..d61c8798de --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/34disable_kpersonalizer @@ -0,0 +1,51 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOKPERSONALIZER}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Disabling kpersonalizer" + +# live-initramfs script + +if chroot /root /usr/bin/which kpersonalizer >/dev/null +then + # Disable first-login wizard for KDE + if [ ! -f /root/etc/kde3/kpersonalizerrc ] + then + +cat > /root/etc/kde3/kpersonalizerrc << EOF +[General] +FirstLogin=false +EOF + + else + echo "I'm not smart enough to disable kpersonalizer startup" >&2 + echo "Because kpersonalizerrc already exists" >&2 + fi +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/35fix_language_selector b/tools/XBMCLive/live-initramfs/scripts/live-bottom/35fix_language_selector new file mode 100755 index 0000000000..8452d12000 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/35fix_language_selector @@ -0,0 +1,44 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOLANGUAGESELECTOR}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Fixing language selector" + +# live-initramfs script + +if [ -e /root/usr/share/applications/language-selector.desktop ] +then + sed -i '/^Exec/ s|/usr/bin/gnome-language-selector|& -n|' /root/usr/share/applications/language-selector.desktop +fi + +if [ -x /root/usr/bin/fontconfig-voodoo ] +then + chroot /root fontconfig-voodoo --auto --quiet || true +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/36disable_trackerd b/tools/XBMCLive/live-initramfs/scripts/live-bottom/36disable_trackerd new file mode 100755 index 0000000000..667131d86d --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/36disable_trackerd @@ -0,0 +1,38 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOTIMEZONE}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Disabling trackerd" + +# live-initramfs script + +rm -f /root/etc/xdg/autostart/tracker-applet.desktop \ + /root/etc/xdg/autostart/trackerd.desktop \ + /root/usr/share/autostart/trackerd.desktop + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/38jockey_disable_check b/tools/XBMCLive/live-initramfs/scripts/live-bottom/38jockey_disable_check new file mode 100755 index 0000000000..1a642e195f --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/38jockey_disable_check @@ -0,0 +1,29 @@ +#!/bin/sh + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +# get pre-requisites +prereqs) + prereqs + exit 0 + ;; +esac + +if [ -n "${NOJOCKEY}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Disabling jockey driver check" + +rm -f /root/etc/xdg/autostart/jockey*.desktop + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/41apt_cdrom b/tools/XBMCLive/live-initramfs/scripts/live-bottom/41apt_cdrom new file mode 100755 index 0000000000..00606d5006 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/41apt_cdrom @@ -0,0 +1,39 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOAPTCDROM}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Adding APT-CDROM source" + +# live-initramfs script + +if [ -d /root/cdrom ] +then + chroot /root apt-cdrom -m add +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/42disable_apparmor b/tools/XBMCLive/live-initramfs/scripts/live-bottom/42disable_apparmor new file mode 100755 index 0000000000..f87cab4fdd --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/42disable_apparmor @@ -0,0 +1,39 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOAPPARMOR}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Disabling AppArmor (does not work with stacked file systems)" + +# live-initramfs script + +if [ -x /root/etc/init.d/apparmor ] +then + chroot /root update-rc.d -f apparmor remove +fi + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/43disable_updateinitramfs b/tools/XBMCLive/live-initramfs/scripts/live-bottom/43disable_updateinitramfs new file mode 100755 index 0000000000..0a434ed05b --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/43disable_updateinitramfs @@ -0,0 +1,41 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +. /scripts/live-functions + +log_begin_msg "Disabling update-initramfs" + +# live-initramfs script + +chroot /root dpkg-divert --add --rename --quiet \ + /usr/sbin/update-initramfs + +cat > /root/usr/sbin/update-initramfs <<EOF +#!/bin/sh + +echo "update-initramfs is disabled since running on a live CD" +exit 0 +EOF + +chmod 0755 /root/usr/sbin/update-initramfs + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/44pk_allow b/tools/XBMCLive/live-initramfs/scripts/live-bottom/44pk_allow new file mode 100755 index 0000000000..ccdd7cec5e --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/44pk_allow @@ -0,0 +1,65 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -n "${NOPOLKITCONF}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Grant administrative PolicyKit privilieges to default user" + +# live-initramfs script + +# configure PolicyKit in live session +mkdir -p /root/etc/PolicyKit +cat << EOF > /root/etc/PolicyKit/PolicyKit.conf +<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- --> + +<!DOCTYPE pkconfig PUBLIC "-//freedesktop//DTD PolicyKit Configuration 1.0//EN" +"http://hal.freedesktop.org/releases/PolicyKit/1.0/config.dtd"> + +<!-- See the manual page PolicyKit.conf(5) for file format --> + +<config version="0.1"> + <match user="root"> + <return result="yes"/> + </match> +EOF + +if [ -n "${USERNAME}" ] +then + cat << EOF >> /root/etc/PolicyKit/PolicyKit.conf + <!-- don't ask password for user in live session --> + <match user="$USERNAME"> + <return result="yes"/> + </match> +EOF +fi + +cat << EOF >> /root/etc/PolicyKit/PolicyKit.conf + <define_admin_auth group="admin"/> +</config> +EOF + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-bottom/99hook b/tools/XBMCLive/live-initramfs/scripts/live-bottom/99hook new file mode 100755 index 0000000000..17895ca103 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-bottom/99hook @@ -0,0 +1,43 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs header + +if [ -z "${HOOK}" ] +then + exit 0 +fi + +. /scripts/live-functions + +log_begin_msg "Executing custom hook script" + +# live-initramfs script + +cd /root +chroot /root wget "${HOOK}" + +FILE="$(basename ${HOOK})" + +chmod 0755 "${FILE}" +./"${FILE}" +rm -f "${FILE}" + +log_end_msg diff --git a/tools/XBMCLive/live-initramfs/scripts/live-functions b/tools/XBMCLive/live-initramfs/scripts/live-functions new file mode 100644 index 0000000000..8bf9c38e7a --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-functions @@ -0,0 +1,113 @@ + +. /scripts/functions +. /live.vars + +log_wait_msg () +{ + # Print a message and wait for enter + if [ -x /sbin/usplash_write ] + then + /sbin/usplash_write "INPUTENTER ${@}" + read nunya < /dev/.initramfs/usplash_outfifo + else if [ -x /sbin/splashy_update ] ; then + /sbin/splashy_update "getstring ${@}" | read nunya + fi ; fi + + _log_msg "Waiting: ${@} ... \n" +} + +really_export () +{ + STRING="${1}" + VALUE="$(eval echo -n \${$STRING})" + + if [ -f /live.vars ] && grep -sq "export ${STRING}" /live.vars + then + sed -i -e 's/\('${STRING}'=\).*$/\1'${VALUE}'/' /live.vars + else + echo "export ${STRING}=\"${VALUE}\"" >> /live.vars + fi + + eval export "${STRING}"="${VALUE}" +} + +lang2locale() { + langpart="${1%%_*}" + if [ "$1" != "C" ]; then + # Match the language code with 3rd field in languagelist + line=$(grep -v "^#" /root/usr/share/live-initramfs/languagelist | cut -f3,4,5 -d\; | grep -v ';C$' | grep "^$langpart;") + if [ -n "$line" ]; then + if [ "$(echo "$line" | grep -c '')" -gt 1 ]; then + # More than one match; try matching the + # country as well. + countrypart="${1#*_}" + if [ "$countrypart" = "$1" ]; then + countryline="$(echo "$line" | head -n1)" + echo "${countryline##*;}" + return + fi + countrypart="${countrypart%%[@.]*}" + countryline="$(echo "$line" | grep ";$countrypart;" | head -n1 || true)" + if [ "$countryline" ]; then + echo "${countryline##*;}" + return + fi + fi + echo "${line##*;}" + fi + else + echo "C" + fi +} + +# Override maybe_break from scripts/functions +maybe_break() +{ + if [ "${break}" = "$1" ]; then + # Call original panic + . /scripts/functions + panic "Spawning shell within the initramfs" + fi +} + +# Override panic from scripts/functions +panic() { + + DEB_1="\033[1;31m .''\`. \033[0m" + DEB_2="\033[1;31m: :' : \033[0m" + DEB_3="\033[1;31m\`. \`'\` \033[0m" + DEB_4="\033[1;31m \`- \033[0m" + + LIVELOG="\033[1;37m/live.log\033[0m" + DEBUG="\033[1;37mdebug\033[0m" + + # Reset redirections to avoid buffering + exec 1>&6 6>&- + exec 2>&7 7>&- + kill ${tailpid} + + printf "\n\n" + printf " ${DEB_1}\n" + printf " ${DEB_2} \033[1;37mBOOT FAILED!\033[0m\n" + printf " ${DEB_3}\n" + printf " ${DEB_4} This Debian Live image failed to boot.\n\n" + + printf " Please file a bug against the 'live-initramfs' package or email the Debian\n" + printf " Live mailing list at <debian-live@lists.debian.org>, making sure to note the\n" + printf " exact version, name and distribution of the image you were attempting to boot.\n\n" + + printf " The file ${LIVELOG} contains some debugging information but booting with the\n" + printf " ${DEBUG} command-line parameter will greatly increase its verbosity which is\n" + printf " extremely useful when diagnosing issues.\n\n" + + if [ -n "${panic}" ]; then + printf " live-initramfs will now restart your system. " + else + printf " live-initramfs will now start a shell. " + fi + printf "The error message was:\n\n " + + # Call original panic + . /scripts/functions + panic "$@" +} diff --git a/tools/XBMCLive/live-initramfs/scripts/live-helpers b/tools/XBMCLive/live-initramfs/scripts/live-helpers new file mode 100644 index 0000000000..8e1c0feaf3 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-helpers @@ -0,0 +1,501 @@ +# live-initramfs helper functions, used by live-initramfs on boot and by live-snapshot + +if [ ! -x "/bin/fstype" ] +then + # klibc not in path -> not in initramfs + export PATH="${PATH}:/usr/lib/klibc/bin" +fi + +# handle upgrade path from old udev (using udevinfo) to +# recent versions of udev (using udevadm info) +if [ -x /sbin/udevadm ] +then + udevinfo='/sbin/udevadm info' +else + udevinfo='udevinfo' +fi + +# handle cases with partial udev (Ubuntu) +if [ -x /lib/udev/vol_id ] +then + volume_label='/lib/udev/vol_id -l' + volume_fstype='/lib/udev/vol_id -t' +else + volume_label='/lib/udev/blkid -s LABEL -o value' + volume_fstype='/lib/udev/blkid -s TYPE -o value' +fi + +!(wc --version > /dev/null 2>&1) || wcIsAvailable=1 + +wordCount() +{ + cmdLine=${1} + if [ -n "${wcIsAvailable}" ]; + then + num=$($cmdLine | wc -w) + else + num=0 + for word in $($cmdLine); + do + num=$(( $num + 1 )) + done + fi + echo $num +} + + +sys2dev () +{ + sysdev=${1#/sys} + echo "/dev/$($udevinfo -q name -p ${sysdev} 2>/dev/null|| echo ${sysdev##*/})" +} + +subdevices () +{ + sysblock=${1} + r="" + + for dev in "${sysblock}" "${sysblock}"/* + do + if [ -e "${dev}/dev" ] + then + r="${r} ${dev}" + fi + done + + echo ${r} +} + +is_supported_fs () +{ + fstype="${1}" + + # Validate input first + if [ -z "${fstype}" ] + then + return 1 + fi + + # Try to look if it is already supported by the kernel + if grep -q ${fstype} /proc/filesystems + then + return 0 + else + # Then try to add support for it the gentle way using the initramfs capabilities + modprobe ${fstype} + if grep -q ${fstype} /proc/filesystems + then + return 0 + # Then try the hard way if /root is already reachable + else + kmodule="/root/lib/modules/`uname -r`/${fstype}/${fstype}.ko" + if [ -e "${kmodule}" ] + then + insmod "${kmodule}" + if grep -q ${fstype} /proc/filesystems + then + return 0 + fi + fi + fi + fi + + return 1 +} + +get_fstype () +{ + local FSTYPE + local FSSIZE + + # fstype misreports LUKS devices + if is_luks "${1}" + then + $volume_fstype ${1} 2>/dev/null + return + fi + + + eval $(fstype ${1} 2>/dev/null) + + if [ "${FSTYPE}" != "unknown" ] + then + echo ${FSTYPE} + return 0 + fi + + $volume_fstype ${1} +} + +where_is_mounted () +{ + device=${1} + + if grep -q "^${device} " /proc/mounts + then + # return the first found + grep -m1 "^${device} " /proc/mounts | cut -f2 -d ' ' + fi +} + +lastline () +{ + while read lines + do + line=${lines} + done + + echo "${line}" +} + +base_path () +{ + testpath="${1}" + mounts="$(awk '{print $2}' /proc/mounts)" + testpath="$(busybox realpath ${testpath})" + + while true + do + if echo "${mounts}" | grep -qs "^${testpath}" + then + set -- $(echo "${mounts}" | grep "^${testpath}" | lastline) + echo ${1} + break + else + testpath=$(dirname $testpath) + fi + done +} + +fs_size () +{ + # Returns used/free fs kbytes + 5% more + # You could pass a block device as ${1} or the mount point as ${2} + + dev="${1}" + mountp="${2}" + used="${3}" + + if [ -z "${mountp}" ] + then + mountp="$(where_is_mounted ${dev})" + + if [ -z "${mountp}" ] + then + mountp="/mnt/tmp_fs_size" + + mkdir -p "${mountp}" + mount -t $(get_fstype "${dev}") -o ro "${dev}" "${mountp}" || log_warning_msg "cannot mount -t $(get_fstype ${dev}) -o ro ${dev} ${mountp}" + + doumount=1 + fi + fi + + if [ "${used}" = "used" ] + then + size=$(du -ks ${mountp} | cut -f1) + size=$(expr ${size} + ${size} / 20 ) # FIXME: 5% more to be sure + else + # free space + size="$(df -k | grep -s ${mountp} | awk '{print $4}')" + fi + + if [ -n "${doumount}" ] + then + umount "${mountp}" || log_warning_msg "cannot umount ${mountp}" + rmdir "${mountp}" + fi + + echo "${size}" +} + +load_keymap () +{ + # Load custom keymap + if [ -x /bin/loadkeys -a -r /etc/boottime.kmap.gz ] + then + loadkeys /etc/boottime.kmap.gz + fi +} + +setup_loop () +{ + local fspath=${1} + local module=${2} + local pattern=${3} + local offset=${4} + local encryption=${5} + local readonly=${6} + + modprobe -q -b "${module}" + + if [ -x /sbin/udevadm ] + then + # lenny + udevadm settle + else + # etch + udevsettle + fi + + for loopdev in ${pattern} + do + if [ "$(cat ${loopdev}/size)" -eq 0 ] + then + dev=$(sys2dev "${loopdev}") + options='' + + if [ -n "${readonly}" ] + then + if losetup --help 2>&1 | grep -q -- "-r\b" + then + options="${options} -r" + fi + fi + + if [ 0 -lt "${offset}" ] + then + options="${options} -o ${offset}" + fi + + if [ -z "${encryption}" ] + then + losetup ${options} "${dev}" "${fspath}" + else + # Loop AES encryption + while true + do + load_keymap + + echo -n "Enter passphrase for root filesystem: " >&6 + read -s passphrase + echo "${passphrase}" > /tmp/passphrase + unset passphrase + exec 9</tmp/passphrase + /sbin/losetup ${options} -e "${encryption}" -p 9 "${dev}" "${fspath}" + error=${?} + exec 9<&- + rm -f /tmp/passphrase + + if [ 0 -eq ${error} ] + then + unset error + break + fi + + echo + echo -n "There was an error decrypting the root filesystem ... Retry? [Y/n] " >&6 + read answer + + if [ "$(echo "${answer}" | cut -b1 | tr A-Z a-z)" = "n" ] + then + unset answer + break + fi + done + fi + + echo "${dev}" + return 0 + fi + done + + panic "No loop devices available" +} + +try_mount () +{ + dev="${1}" + mountp="${2}" + opts="${3}" + fstype="${4}" + + old_mountp="$(where_is_mounted ${dev})" + + if [ -n "${old_mountp}" ] + then + if [ "${opts}" != "ro" ] + then + mount -o remount,"${opts}" "${dev}" "${old_mountp}" || panic "Remounting ${dev} ${opts} on ${old_mountp} failed" + fi + + mount -o bind "${old_mountp}" "${mountp}" || panic "Cannot bind-mount ${old_mountp} on ${mountp}" + else + if [ -z "${fstype}" ] + then + fstype=$(get_fstype "${dev}") + fi + mount -t "${fstype}" -o "${opts}" "${dev}" "${mountp}" || panic "Cannot mount ${dev} on ${mountp}, fstype=${fstype}, options=${opts}" + fi +} + +find_cow_device () +{ + # Returns a device containing a partition labeled "${pers_label}" or containing a file named the same way + # in the latter case the partition containing the file is left mounted + # if is not in black_listed_devices + pers_label="${1}" + cow_backing="/${pers_label}-backing" + black_listed_devices="${2}" + + if [ -z "${PERSISTENT_PATH}" ] + then + pers_fpath=${cow_backing}/${pers_label} + else + pers_fpath=${cow_backing}/${PERSISTENT_PATH}/${pers_label} + fi + + for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop | grep -v ram | grep -v fd) + do + for dev in $(subdevices "${sysblock}") + do + devname=$(sys2dev "${dev}") + + if echo "${black_listed_devices}" | grep -q "${devname}" + then + # skip this device enterely + break + fi + + # Checking for a luks device + if [ -e /sbin/cryptsetup ] && /sbin/cryptsetup isLuks ${devname} + then + while true + do + load_keymap + + /lib/cryptsetup/askpass "Enter passphrase for ${pers_label} on ${devname}: " /sbin/cryptsetup -T 1 luksOpen ${devname} $(basename ${devname}) --key-file=- + error=${?} + + devname="/dev/mapper/$(basename ${devname})" + + if [ 0 -eq ${error} ] + then + unset error + break + fi + + echo + echo -n "There was an error decrypting ${devname} ... Retry? [Y/n] " >&6 + read answer + + if [ "$(echo "${answer}" | cut -b1 | tr A-Z a-z)" = "n" ] + then + unset answer + break + fi + done + fi + + if [ "$($volume_label -l ${devname} 2>/dev/null)" = "${pers_label}" ] + then + echo "${devname}" + return 0 + fi + + if [ "${PERSISTENT}" = "nofiles" ] + then + # do not mount the device to find for image files + # just skip this + break + fi + + case "$(get_fstype ${devname})" in + vfat|ext2|ext3|ext4|jffs2) + mkdir -p "${cow_backing}" + if ! try_mount "${devname}" "${cow_backing}" "rw" + then + break + fi + + if [ -f "${pers_fpath}" ] + then + echo $(setup_loop "${pers_fpath}" "loop" "/sys/block/loop*") + return 0 + else + umount ${cow_backing} + fi + ;; + *) + ;; + esac + done + done + return 1 +} + +find_files () +{ + # return the a string composed by device name, mountpoint an the first of ${filenames} found on a supported partition + # FIXME: merge with above function + + filenames="${1}" + snap_backing="/snap-backing" + black_listed_devices="${2}" + + for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop | grep -v ram | grep -v fd) + do + for dev in $(subdevices "${sysblock}") + do + devname=$(sys2dev "${dev}") + devfstype="$(get_fstype ${devname})" + + if echo "${black_listed_devices}" | grep -q "${devname}" + then + # skip this device enterely + break + fi + + if is_supported_fs ${devfstype} + then + mkdir -p "${snap_backing}" + + if try_mount "${devname}" "${snap_backing}" "ro" "${devfstype}" + then + for filename in ${filenames} + do + if [ -f "${snap_backing}/${filename}" ] + then + echo "${devname} ${snap_backing} ${filename}" + umount ${snap_backing} + return 0 + fi + done + fi + + umount ${snap_backing} + fi + done + done +} + +get_mac () +{ + mac="" + + for adaptor in /sys/class/net/* + do + status="$(cat ${adaptor}/iflink)" + + if [ "${status}" -eq 2 ] + then + mac="$(cat ${adaptor}/address)" + mac="$(echo ${mac} | sed 's/:/-/g' | tr '[a-z]' '[A-Z]')" + fi + done + + echo ${mac} +} + +is_luks() +{ + devname="${1}" + if [ -x /sbin/cryptsetup ] + then + /sbin/cryptsetup isLuks "${devname}" 2>/dev/null || ret=${?} + return ${ret} + else + return 1 + fi + +} diff --git a/tools/XBMCLive/live-initramfs/scripts/live-premount/modules b/tools/XBMCLive/live-initramfs/scripts/live-premount/modules new file mode 100755 index 0000000000..408e873848 --- /dev/null +++ b/tools/XBMCLive/live-initramfs/scripts/live-premount/modules @@ -0,0 +1,32 @@ +#!/bin/sh + +#set -e + +# initramfs-tools header + +PREREQ="udev" + +prereqs() +{ + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +# live-initramfs script + +# The following modprobe entry is a workaround to live-initramfs not +# finding the root filesytem. +# +# See also: +# * http://lists.alioth.debian.org/pipermail/debian-live-devel/2007-May/001459.html +# * http://lists.alioth.debian.org/pipermail/debian-live-devel/2007-June/001517.html +# * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=363047 + +modprobe -q ide-generic +modprobe -q esp diff --git a/tools/XBMCLive/postinst b/tools/XBMCLive/postinst new file mode 100755 index 0000000000..25a5ca7e61 --- /dev/null +++ b/tools/XBMCLive/postinst @@ -0,0 +1,129 @@ +#!/bin/sh + +set -e + +case "$1" in + configure) + sed -i.bak-xbmc-live s/allowed_users=console/allowed_users=anybody/ /etc/X11/Xwrapper.config + + # Add the 'xbmc' user + if ! getent passwd xbmc >/dev/null; then + adduser \ + --gecos "XBMC Live User" \ + xbmc + fi + # Add 'xbmc' user to the appropriate groups + # Below is a listing of groups and their purpose + # adm - For reading system logs (minimal systems may have this user only) + # sudo - allow optional passwordless sudo (with trivial intervention on /etc/sudoers) + # cdrom - optical disc drive access + # floppy - floppy drive access + # audio - audio device access + # video - video device access + # plugdev - enable automatic notifications of new devices + # netdev - managing network connections via NetworkManager + # powerdev - to be able to hibernate/suspend + # fuse - to be able to mount filesystems as normal user + GROUPS="adm + sudo + cdrom + floppy + audio + video + plugdev + netdev + powerdev + fuse" + + # TODO: this probably isn't necessary anymore as PolicyKit is now being + # used + for GROUP in $GROUPS; do + if getent group $GROUP >/dev/null && \ + ! getent group $GROUP | grep -q xbmc; then + adduser xbmc $GROUP + fi + done + + # Add xbmc to the sudoers file + echo "#" >> /etc/sudoers + echo "# XBMC-specific configuration" >> /etc/sudoers + echo "#" >> /etc/sudoers + echo "Cmnd_Alias SHUTDOWN_CMDS = /sbin/shutdown, /sbin/reboot, /sbin/halt" >> /etc/sudoers + echo "Cmnd_Alias MOUNT_CMDS = /bin/mount, /bin/umount" >> /etc/sudoers + echo "xbmc ALL=(ALL) ALL" >> /etc/sudoers + echo "xbmc ALL=NOPASSWD: SHUTDOWN_CMDS, MOUNT_CMDS" >> /etc/sudoers + + # Our set of PolicyKit actions + + # This is a list of actions that the 'xbmc' user should be allowed to + # do. If we missed one, or we have one that's not necessary, please + # submit a bug report. + POLKIT_ACTIONS="org.freedesktop.hal.dockstation.undock + org.freedesktop.hal.wol.enabled + org.freedesktop.hal.wol.enable + org.freedesktop.hal.wol.supported + org.freedesktop.hal.leds.brightness + org.freedesktop.hal.device-access.audio-player + org.freedesktop.hal.device-access.camera + org.freedesktop.hal.device-access.cdrom + org.freedesktop.hal.device-access.dvb + org.freedesktop.hal.device-access.fingerprint-reader + org.freedesktop.hal.device-access.floppy + org.freedesktop.hal.device-access.ieee1394-avc + org.freedesktop.hal.device-access.ieee1394-iidc + org.freedesktop.hal.device-access.joystick + org.freedesktop.hal.device-access.mouse + org.freedesktop.hal.device-access.obex + org.freedesktop.hal.device-access.pda + org.freedesktop.hal.device-access.printer + org.freedesktop.hal.device-access.scanner + org.freedesktop.hal.device-access.sound + org.freedesktop.hal.device-access.video + org.freedesktop.hal.device-access.video4linux + org.freedesktop.hal.lock + org.freedesktop.hal.killswitch.bluetooth + org.freedesktop.hal.killswitch.wlan + org.freedesktop.hal.killswitch.wwan + org.freedesktop.hal.storage.mount-removable + org.freedesktop.hal.storage.eject + org.freedesktop.hal.storage.crypto-setup-removable + org.freedesktop.hal.power-management.shutdown + org.freedesktop.hal.power-management.reboot + org.freedesktop.hal.power-management.set-powersave + org.freedesktop.hal.power-management.suspend + org.freedesktop.hal.power-management.hibernate + org.freedesktop.hal.power-management.cpufreq + org.freedesktop.hal.power-management.lcd-panel + org.freedesktop.hal.power-management.light-sensor + org.freedesktop.hal.power-management.keyboard-backlight" + + # Grant the 'xbmc' user each action from the list if not done already + for ACTION in $POLKIT_ACTIONS; do + if polkit-auth --user xbmc --show-obtainable | \ + grep -q $ACTION; then + polkit-auth --user xbmc --grant $ACTION + fi + done + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# Automatically added by dh_installinit +if [ -x "/etc/init.d/xbmc-live" ]; then + update-rc.d xbmc-live defaults >/dev/null + if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then + invoke-rc.d xbmc-live start || exit $? + else + /etc/init.d/xbmc-live start || exit $? + fi +fi +# End automatically added section + +exit 0 diff --git a/tools/XBMCLive/runXBMC b/tools/XBMCLive/runXBMC new file mode 100755 index 0000000000..a6d3125b0f --- /dev/null +++ b/tools/XBMCLive/runXBMC @@ -0,0 +1,41 @@ +#!/bin/bash + +if [ "$(pidof X)" ] ; then + /usr/share/xbmc/xbmc.bin --standalone + exit +fi + +while true +do + echo "#!/bin/bash" > /home/xbmc/.xsession + echo "/usr/share/xbmc/xbmc.bin --standalone" >> /home/xbmc/.xsession + + echo "case \"\$?\" in" >> /home/xbmc/.xsession + echo " 0 ) # Quit" >> /home/xbmc/.xsession + echo " touch /tmp/noRestartXBMC" >> /home/xbmc/.xsession + echo " break ;;" >> /home/xbmc/.xsession + echo " 64 ) # Shutdown System" >> /home/xbmc/.xsession + echo " sleep 10 ;;" >> /home/xbmc/.xsession + echo " 65 ) # Warm Reboot" >> /home/xbmc/.xsession + echo " echo "Restarting XBMC ..." ;;" >> /home/xbmc/.xsession + echo " 66 ) # Reboot System" >> /home/xbmc/.xsession + echo " sleep 10 ;;" >> /home/xbmc/.xsession + echo " * ) ;;" >> /home/xbmc/.xsession + echo "esac" >> /home/xbmc/.xsession + + chown xbmc:xbmc /home/xbmc/.xsession + + if [ "$(whoami)" == "root" ] ; then + su xbmc -c "startx -- -br > /dev/null 2>&1" -l + else + startx -- -br > /dev/null 2>&1 + fi + + if [ -e /tmp/noRestartXBMC ] ; then + rm /tmp/noRestartXBMC + rm /home/xbmc/.xsession + break + fi + +# sleep 2 +done diff --git a/tools/XBMCLive/setAlsaVolumes b/tools/XBMCLive/setAlsaVolumes new file mode 100755 index 0000000000..6d24fbd5e7 --- /dev/null +++ b/tools/XBMCLive/setAlsaVolumes @@ -0,0 +1,35 @@ +#!/usr/bin/env python +""" + Set output volume for all amixer controls + V0.992 - 20090319 + Luigi Capriotti @2009 +""" + +import sys, subprocess + +gVolumeLevel = "100" + +def runSilent(aCmdline): + process = subprocess.Popen(aCmdline, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) + stdout_value, stderr_value = process.communicate() + return stdout_value + +if __name__ == '__main__': + if len(sys.argv) > 1: + gVolumeLevel = sys.argv[1] + + print "Setting volumes at " + gVolumeLevel + "%" + + mixerList = runSilent("amixer scontrols") + + arMixers = mixerList.split('\n') + for aMixer in arMixers: + nameStart = aMixer.find("'") + if nameStart>0: + # print "Mixer name=" + aMixer[nameStart:] + output = runSilent("amixer sget " + aMixer[nameStart:]) + if output.find("pvolume") > 0: + output = runSilent("amixer sset " + aMixer[nameStart:] + " " + gVolumeLevel + "% unmute") + if output.find("pswitch") > 0: + output = runSilent("amixer sset " + aMixer[nameStart:] + " unmute") + # runSilent("alsactl store") diff --git a/tools/XBMCLive/xbmc b/tools/XBMCLive/xbmc new file mode 100755 index 0000000000..9033473f58 --- /dev/null +++ b/tools/XBMCLive/xbmc @@ -0,0 +1,169 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: xbmc +# Required-Start: $local_fs $network $remote_fs +# Required-Stop: $local_fs $network $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop XBMC Live +# Description: XBMC Live is the XBMC media center software bundled with an +# embedded operating-system, for that set-top-box feeling. +### END INIT INFO + +# Do NOT "set -e" + +#/etc/init.d/xbmc + +. /lib/lsb/init-functions + +get_opt() { + echo "$@" | cut -d "=" -f 2 +} + +CMDLINE=$(cat /proc/cmdline) + +do_start() +{ + log_action_begin_msg "Configuring system and starting XBMC" + + #Process command line options + XBMC_PARAMS="" + for i in ${CMDLINE}; do + case "${i}" in + xbmc\=*) + XBMC_PARAMS=$(get_opt $i) + ;; + esac + done + + # Relies on init scripts to mount boot device on a specified directory + # TODO hardcode the already mounted directories (speed) + # XBMC Live V2 + BOOTMEDIADIRECTORY="image" + BOOTMEDIAMOUNTPOINT="$(mount | grep $BOOTMEDIADIRECTORY | cut -f 3 -d ' ')" + if [ ! -n "$BOOTMEDIAMOUNTPOINT" ]; then + # XBMC Live V1 + BOOTMEDIADIRECTORY="bootMedia" + BOOTMEDIAMOUNTPOINT="$(mount | grep $BOOTMEDIADIRECTORY | cut -f 3 -d ' ')" + fi + + # copy xorg.conf from "Config" directory + if [ -n "$BOOTMEDIAMOUNTPOINT" ]; then + if [ -f $BOOTMEDIAMNTPOINT/config/xorg.conf ]; then + cp $BOOTMEDIAMNTPOINT/config/xorg.conf /etc/X11 + fi + fi + + INSTALL="$( echo $XBMC_PARAMS | grep install)" + if [ -n "$INSTALL" ]; then + # if usplash is runing, make sure to stop it now, yes "start" kills it. + if pidof usplash > /dev/null; then + DO_NOT_SWITCH_VT=yes /etc/init.d/usplash start + fi + su -c "/usr/bin/installXBMC" -l + else + # Generates valid xorg.conf for proprietary drivers if missing + XBMC_NOGENXCONF="$( echo $XBMC_PARAMS | grep nogenxconf )" + if [ ! -e /etc/X11/xorg.conf ] && [ ! -n "$XBMC_NOGENXCONF" ]; then + NVIDIA="$(lspci -nn | grep 0300 | grep 10de)" + if [ ! -n "$NVIDIA" ]; then + AMD="$(lspci -nn | grep 0300 | grep 1002)" + if [ -n "$AMD" ]; then + # run aticonfig + log_warning_msg "Generating xorg.conf for ATI..." + /usr/bin/aticonfig --initial --sync-vsync=on -f + fi + else + # run nvidia-xconfig + log_warning_msg "Generating xorg.conf for NVIDIA..." + /usr/bin/nvidia-xconfig -s --no-logo --force-generate + fi + fi + + RUNX="$(echo $CMDLINE | grep splash)" + if [ ! -n "$RUNX" ]; then + log_warning_msg "Not starting X." + + if [ -f /home/xbmc/.xsession ]; then + rm /home/xbmc/.xsession + fi + else + BOOTFROMCD="$(mount | grep iso9660)" + if [ ! -n "$BOOTFROMCD" ]; then + NOREDIR="$(echo $XBMC_PARAMS | grep noredir)" + if [ ! -n "$NOREDIR" ]; then + if [ -n "$BOOTMEDIAMOUNTPOINT" ]; then + log_warning_msg "Redirect XBMC home folder and logfile to usb flash..." + if [ ! -d $BOOTMEDIAMOUNTPOINT/dotXBMC ]; then + mkdir $BOOTMEDIAMOUNTPOINT/dotXBMC + fi + + if [ -d /home/xbmc/.xbmc ]; then + if [ -L /home/xbmc/.xbmc ]; then + rm .xbmc + else + mv /home/xbmc/.xbmc /home/xbmc/.xbmc.previous + fi + fi + ln -s $BOOTMEDIAMOUNTPOINT/dotXBMC /home/xbmc/.xbmc + fi + fi + fi + + /usr/bin/runXBMC & + + XBMC_SETVOLUME="$(echo $XBMC_PARAMS | grep setvolume)" + if [ -n "$XBMC_SETVOLUME" ]; then + log_warning_msg "Increasing ALSA volumes..." + /usr/bin/setAlsaVolumes & + fi + + NOMOUNT="$(echo $XBMC_PARAMS | grep nodiskmount)" + if [ ! -n "$NOMOUNT" ]; then + log_warning_msg "Mounting local disks..." + /usr/bin/diskmounter & + fi + + # if usplash is running, make sure to stop it now, yes "start" kills it. + if pidof usplash > /dev/null; then + DO_NOT_SWITCH_VT=yes /etc/init.d/usplash start + fi + fi + fi + log_action_end_msg 0 +} + +do_stop() { + touch /tmp/noRestartXBMC + if [ -f /home/xbmc/.xsession ]; then + rm /home/xbmc/.xsession + fi + + if [ "$(pidof xbmc.bin)" ] ; then + killall xbmc.bin + sleep 1 + fi + + if [ -f /tmp/noRestartXBMC ]; then + rm /tmp/noRestartXBMC + fi +} + +case "$1" in +start) + do_start + ;; +stop) + do_stop + ;; +restart|force-reload) + do_stop + do_start + ;; +*) + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 + exit 3 + ;; +esac + +exit 0 diff --git a/tools/XBMCTex/AnimatedGif.cpp b/tools/XBMCTex/AnimatedGif.cpp new file mode 100644 index 0000000000..ffeba2befe --- /dev/null +++ b/tools/XBMCTex/AnimatedGif.cpp @@ -0,0 +1,649 @@ + +// **************************************************************************** +// +// WINIMAGE.CPP : Generic classes for raster images (MSWindows specialization) +// +// Content: Member definitions for: +// - class CAnimatedGif : Storage class for single images +// - class CAnimatedGifSet : Storage class for sets of images +// +// (Includes routines to Load and Save BMP files and to load GIF files into +// these classes). +// +// -------------------------------------------------------------------------- +// +// Copyright (c) 2000, Juan Soulie <jsoulie@cplusplus.com> +// +// Permission to use, copy, modify, distribute and sell this software or any +// part thereof and/or its documentation for any purpose is granted without fee +// provided that the above copyright notice and this permission notice appear +// in all copies. +// +// This software is provided "as is" without express or implied warranty of +// any kind. The author shall have no liability with respect to the +// infringement of copyrights or patents that any modification to the content +// of this file or this file itself may incur. +// +// **************************************************************************** + +#include "xbox.h" +#include "AnimatedGif.h" +#include "EndianSwap.h" + +#ifdef _WIN32PC +extern "C" FILE *fopen_utf8(const char *_Filename, const char *_Mode); +#else +#define fopen_utf8 fopen +#endif + +#pragma pack(1) +// Error processing macro (NO-OP by default): +#define ERRORMSG(PARAM) {} + +#ifndef BI_RGB + #define BI_RGB 0L + #define BI_RLE8 1L + #define BI_RLE4 2L + #define BI_BITFIELDS 3L +#endif + +// Macros to swap data endianness +#define SWAP16(X) X=Endian_SwapLE16(X) +#define SWAP32(X) X=Endian_SwapLE32(X) + +// pre-declaration: +int LZWDecoder (char*, char*, short, int, int, int, const int); + +// **************************************************************************** +// * CAnimatedGif Member definitions * +// **************************************************************************** + +CAnimatedGif::CAnimatedGif() +{ + Height = Width = 0; + Raster = NULL; + Palette = NULL; + pbmi = NULL; + BPP = Transparent = BytesPerRow = 0; + xPos = yPos = Delay = Transparency = 0; + nLoops = 1; //default=play animation 1 time +} + +CAnimatedGif::~CAnimatedGif() +{ + delete [] pbmi; + delete [] Raster; +} + +// Init: Allocates space for raster and palette in GDI-compatible structures. +void CAnimatedGif::Init(int iWidth, int iHeight, int iBPP, int iLoops) +{ + if (Raster) + { + delete[] Raster; + Raster = NULL; + } + + if (pbmi) + { + delete[] pbmi; + pbmi = NULL; + } + // Standard members setup + Transparent = -1; + BytesPerRow = Width = PadPow2(iWidth); + Height = PadPow2(iHeight); + BPP = iBPP; + // Animation Extra members setup: + xPos = yPos = Delay = Transparency = 0; + nLoops = iLoops; + + if (BPP == 24) + { + BytesPerRow *= 3; + pbmi = (GUIBITMAPINFO*)new char [sizeof(GUIBITMAPINFO)]; + } + else + { + pbmi = (GUIBITMAPINFO*)new char[sizeof(GUIBITMAPINFOHEADER) + (1 << BPP) * sizeof(COLOR)]; + Palette = (COLOR*)((char*)pbmi + sizeof(GUIBITMAPINFOHEADER)); + } + + BytesPerRow += (ALIGN - Width % ALIGN) % ALIGN; // Align BytesPerRow + int size = BytesPerRow * Height; + + Raster = new char [size]; + + pbmi->bmiHeader.biSize = sizeof (GUIBITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = Width; + pbmi->bmiHeader.biHeight = -Height; // negative means up-to-bottom + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biBitCount = (BPP < 8 ? 8 : BPP); // Our raster is byte-aligned + pbmi->bmiHeader.biCompression = BI_RGB; + pbmi->bmiHeader.biSizeImage = 0; + pbmi->bmiHeader.biXPelsPerMeter = 11811; + pbmi->bmiHeader.biYPelsPerMeter = 11811; + pbmi->bmiHeader.biClrUsed = 0; + pbmi->bmiHeader.biClrImportant = 0; +} + +// operator=: copies an object's content to another +CAnimatedGif& CAnimatedGif::operator = (CAnimatedGif& rhs) +{ + Init(rhs.Width, rhs.Height, rhs.BPP); // respects virtualization + memcpy(Raster, rhs.Raster, BytesPerRow*Height); + memcpy((char*)Palette, (char*)rhs.Palette, (1 << BPP)*sizeof(*Palette)); + return *this; +} + + + +CAnimatedGifSet::CAnimatedGifSet() +{ + FrameHeight = FrameWidth = 0; + nLoops = 1; //default=play animation 1 time +} + +CAnimatedGifSet::~CAnimatedGifSet() +{ + Release(); +} + +void CAnimatedGifSet::Release() +{ + FrameWidth = 0; + FrameHeight = 0; + for (int i = 0; i < (int)m_vecimg.size(); ++i) + { + CAnimatedGif* pImage = m_vecimg[i]; + delete pImage; + } + m_vecimg.erase(m_vecimg.begin(), m_vecimg.end()); + +} + +// **************************************************************************** +// * CAnimatedGifSet Member definitions * +// **************************************************************************** + +// AddImage: Adds an image object to the back of the img vector. +void CAnimatedGifSet::AddImage (CAnimatedGif* newimage) +{ + m_vecimg.push_back(newimage); +} + +int CAnimatedGifSet::GetImageCount() const +{ + return m_vecimg.size(); +} + +unsigned char CAnimatedGifSet::getbyte(FILE *fd) +{ + unsigned char uchar; + if (fread(&uchar, 1, 1, fd) == 1) + return uchar; + else + return 0; +} + +// **************************************************************************** +// * LoadGIF * +// * Load a GIF File into the CAnimatedGifSet object * +// * (c) Nov 2000, Juan Soulie <jsoulie@cplusplus.com> * +// **************************************************************************** +int CAnimatedGifSet::LoadGIF (const char * szFileName) +{ + int n; + // Global GIF variables: + int GlobalBPP; // Bits per Pixel. + COLOR * GlobalColorMap; // Global colormap (allocate) + + struct GIFGCEtag + { // GRAPHIC CONTROL EXTENSION + unsigned char BlockSize; // Block Size: 4 bytes + unsigned char PackedFields; // 3.. Packed Fields. Bits detail: + // 0: Transparent Color Flag + // 1: User Input Flag + // 2-4: Disposal Method + unsigned short Delay; // 4..5 Delay Time (1/100 seconds) + unsigned char Transparent; // 6.. Transparent Color Index + } + gifgce; + + struct GIFNetscapeTag + { + unsigned char comment[11]; //4...14 NETSCAPE2.0 + unsigned char SubBlockLength; //15 0x3 + unsigned char reserved; //16 0x1 + unsigned short iIterations ; //17..18 number of iterations (lo-hi) + } + gifnetscape; + + int GraphicExtensionFound = 0; + + // OPEN FILE + FILE *fd = fopen_utf8(szFileName, "rb"); + if (!fd) + { + return 0; + } + + // *1* READ HEADERBLOCK (6bytes) (SIGNATURE + VERSION) + char szSignature[6]; // First 6 bytes (GIF87a or GIF89a) + int iRead = fread(szSignature, 1, 6, fd); + if (iRead != 6) + { + fclose(fd); + return 0; + } + if ( memcmp(szSignature, "GIF", 2) != 0) + { + fclose(fd); + return 0; + } + // *2* READ LOGICAL SCREEN DESCRIPTOR + struct GIFLSDtag + { + unsigned short ScreenWidth; // Logical Screen Width + unsigned short ScreenHeight; // Logical Screen Height + unsigned char PackedFields; // Packed Fields. Bits detail: + // 0-2: Size of Global Color Table + // 3: Sort Flag + // 4-6: Color Resolution + // 7: Global Color Table Flag + unsigned char Background; // Background Color Index + unsigned char PixelAspectRatio; // Pixel Aspect Ratio + } + giflsd; + + iRead = fread(&giflsd, 1, sizeof(giflsd), fd); + if (iRead != sizeof(giflsd)) + { + fclose(fd); + return 0; + } + // endian swap + SWAP16(giflsd.ScreenWidth); + SWAP16(giflsd.ScreenHeight); + + GlobalBPP = (giflsd.PackedFields & 0x07) + 1; + + // fill some animation data: + FrameWidth = giflsd.ScreenWidth; + FrameHeight = giflsd.ScreenHeight; + nLoops = 1; //default=play animation 1 time + + // *3* READ/GENERATE GLOBAL COLOR MAP + GlobalColorMap = new COLOR [1 << GlobalBPP]; + if (giflsd.PackedFields & 0x80) // File has global color map? + for (n = 0;n < 1 << GlobalBPP;n++) + { + GlobalColorMap[n].r = getbyte(fd); + GlobalColorMap[n].g = getbyte(fd); + GlobalColorMap[n].b = getbyte(fd); + } + + else // GIF standard says to provide an internal default Palette: + for (n = 0;n < 256;n++) + GlobalColorMap[n].r = GlobalColorMap[n].g = GlobalColorMap[n].b = n; + + // *4* NOW WE HAVE 3 POSSIBILITIES: + // 4a) Get and Extension Block (Blocks with additional information) + // 4b) Get an Image Separator (Introductor to an image) + // 4c) Get the trailer Char (End of GIF File) + do + { + int charGot = getbyte(fd); + + if (charGot == 0x21) // *A* EXTENSION BLOCK + { + unsigned char extensionType = getbyte(fd); + switch (extensionType) + { + case 0xF9: // Graphic Control Extension + { + if (fread((char*)&gifgce, 1, sizeof(gifgce), fd) == sizeof(gifgce)) + SWAP16(gifgce.Delay); + GraphicExtensionFound++; + getbyte(fd); // Block Terminator (always 0) + } + break; + + case 0xFE: // Comment Extension: Ignored + { + while (int nBlockLength = getbyte(fd)) + for (n = 0;n < nBlockLength;n++) getbyte(fd); + } + break; + + case 0x01: // PlainText Extension: Ignored + { + while (int nBlockLength = getbyte(fd)) + for (n = 0;n < nBlockLength;n++) getbyte(fd); + } + break; + + case 0xFF: // Application Extension: Ignored + { + int nBlockLength = getbyte(fd); + if (nBlockLength == 0x0b) + { + struct GIFNetscapeTag tag; + if (fread((char*)&tag, 1, sizeof(gifnetscape), fd) == sizeof(gifnetscape)) + { + SWAP16(tag.iIterations); + nLoops = tag.iIterations; + } + else + nLoops = 0; + + if (nLoops) nLoops++; + getbyte(fd); + } + else + { + do + { + for (n = 0;n < nBlockLength;n++) getbyte(fd); + } + while ((nBlockLength = getbyte(fd)) != 0); + } + } + break; + + default: // Unknown Extension: Ignored + { + // read (and ignore) data sub-blocks + while (int nBlockLength = getbyte(fd)) + for (n = 0;n < nBlockLength;n++) getbyte(fd); + } + break; + } + } + else if (charGot == 0x2c) + { // *B* IMAGE (0x2c Image Separator) + // Create a new Image Object: + CAnimatedGif* NextImage = new CAnimatedGif(); + + // Read Image Descriptor + struct GIFIDtag + { + unsigned short xPos; // Image Left Position + unsigned short yPos; // Image Top Position + unsigned short Width; // Image Width + unsigned short Height; // Image Height + unsigned char PackedFields; // Packed Fields. Bits detail: + // 0-2: Size of Local Color Table + // 3-4: (Reserved) + // 5: Sort Flag + // 6: Interlace Flag + // 7: Local Color Table Flag + } + gifid; + + memset(&gifid, 0, sizeof(gifid)); + + int LocalColorMap = 0; + if (fread((char*)&gifid, 1, sizeof(gifid), fd) == sizeof(gifid)) + { + SWAP16(gifid.xPos); + SWAP16(gifid.yPos); + SWAP16(gifid.Width); + SWAP16(gifid.Height); + + LocalColorMap = (gifid.PackedFields & 0x08) ? 1 : 0; + } + + NextImage->Init(gifid.Width, gifid.Height, LocalColorMap ? (gifid.PackedFields&7) + 1 : GlobalBPP); + + // Fill NextImage Data + NextImage->xPos = gifid.xPos; + NextImage->yPos = gifid.yPos; + if (GraphicExtensionFound) + { + NextImage->Transparent = (gifgce.PackedFields & 0x01) ? gifgce.Transparent : -1; + NextImage->Transparency = (gifgce.PackedFields & 0x1c) > 1 ? 1 : 0; + NextImage->Delay = gifgce.Delay * 10; + } + + if (NextImage->Transparent != -1) + memset(NextImage->Raster, NextImage->Transparent, NextImage->BytesPerRow * NextImage->Height); + else + memset(NextImage->Raster, giflsd.Background, NextImage->BytesPerRow * NextImage->Height); + + // Read Color Map (if descriptor says so) + size_t palSize = sizeof(COLOR)*(1 << NextImage->BPP); + bool isPalRead = false; + if (LocalColorMap && fread((char*)NextImage->Palette, 1, palSize, fd) == palSize) + isPalRead = true; + + // Copy global, if no palette + if (!isPalRead) + memcpy(NextImage->Palette, GlobalColorMap, palSize); + + short firstbyte = getbyte(fd); // 1st byte of img block (CodeSize) + + // Calculate compressed image block size + // to fix: this allocates an extra byte per block + long ImgStart, ImgEnd; + ImgEnd = ImgStart = ftell(fd); + while ((n = getbyte(fd)) != 0) fseek (fd, ImgEnd += n + 1, SEEK_SET ); + fseek (fd, ImgStart, SEEK_SET); + + // Allocate Space for Compressed Image + char * pCompressedImage = new char [ImgEnd - ImgStart + 4]; + + // Read and store Compressed Image + char * pTemp = pCompressedImage; + while (int nBlockLength = getbyte(fd)) + { + if (fread(pTemp, 1, nBlockLength, fd) != (size_t)nBlockLength) + { + // Error? + } + pTemp += nBlockLength; + } + + // Call LZW/GIF decompressor + n = LZWDecoder( + (char*) pCompressedImage, + (char*) NextImage->Raster, + firstbyte, NextImage->BytesPerRow, //NextImage->AlignedWidth, + gifid.Width, gifid.Height, + ((gifid.PackedFields & 0x40) ? 1 : 0) //Interlaced? + ); + + if (n) + AddImage(NextImage); + else + { + delete NextImage; + ERRORMSG("GIF File Corrupt"); + } + + // Some cleanup + delete[] pCompressedImage; + GraphicExtensionFound = 0; + } + else if (charGot == 0x3b) + { + // *C* TRAILER: End of GIF Info + break; // Ok. Standard End. + } + + } + while ( !feof(fd) ); + + delete[] GlobalColorMap; + fclose(fd); + if ( GetImageCount() == 0) ERRORMSG("Premature End Of File"); + return GetImageCount(); +} + +// **************************************************************************** +// * LZWDecoder (C/C++) * +// * Codec to perform LZW (GIF Variant) decompression. * +// * (c) Nov2000, Juan Soulie <jsoulie@cplusplus.com> * +// **************************************************************************** +// +// Parameter description: +// - bufIn: Input buffer containing a "de-blocked" GIF/LZW compressed image. +// - bufOut: Output buffer where result will be stored. +// - InitCodeSize: Initial CodeSize to be Used +// (GIF files include this as the first byte in a picture block) +// - AlignedWidth : Width of a row in memory (including alignment if needed) +// - Width, Height: Physical dimensions of image. +// - Interlace: 1 for Interlaced GIFs. +// +int LZWDecoder (char * bufIn, char * bufOut, + short InitCodeSize, int AlignedWidth, + int Width, int Height, const int Interlace) +{ + int n; + int row = 0, col = 0; // used to point output if Interlaced + int nPixels, maxPixels; // Output pixel counter + + short CodeSize; // Current CodeSize (size in bits of codes) + short ClearCode; // Clear code : resets decompressor + short EndCode; // End code : marks end of information + + long whichBit; // Index of next bit in bufIn + long LongCode; // Temp. var. from which Code is retrieved + short Code; // Code extracted + short PrevCode; // Previous Code + short OutCode; // Code to output + + // Translation Table: + short Prefix[4096]; // Prefix: index of another Code + unsigned char Suffix[4096]; // Suffix: terminating character + short FirstEntry; // Index of first free entry in table + short NextEntry; // Index of next free entry in table + + unsigned char OutStack[4097]; // Output buffer + int OutIndex; // Characters in OutStack + + int RowOffset; // Offset in output buffer for current row + + // Set up values that depend on InitCodeSize Parameter. + CodeSize = InitCodeSize + 1; + ClearCode = (1 << InitCodeSize); + EndCode = ClearCode + 1; + NextEntry = FirstEntry = ClearCode + 2; + + whichBit = 0; + nPixels = 0; + maxPixels = Width * Height; + RowOffset = 0; + PrevCode = 0; + + while (nPixels < maxPixels) + { + OutIndex = 0; // Reset Output Stack + + // GET NEXT CODE FROM bufIn: + // LZW compression uses code items longer than a single byte. + // For GIF Files, code sizes are variable between 9 and 12 bits + // That's why we must read data (Code) this way: + LongCode = *((long*)(bufIn + whichBit / 8)); // Get some bytes from bufIn + SWAP32(LongCode); + LongCode >>= (whichBit&7); // Discard too low bits + Code = (short)((LongCode & ((1 << CodeSize) - 1) )); // Discard too high bits + whichBit += CodeSize; // Increase Bit Offset + + // SWITCH, DIFFERENT POSIBILITIES FOR CODE: + if (Code == EndCode) // END CODE + break; // Exit LZW Decompression loop + + if (Code == ClearCode) + { + // CLEAR CODE: + CodeSize = InitCodeSize + 1; // Reset CodeSize + NextEntry = FirstEntry; // Reset Translation Table + PrevCode = Code; // Prevent next to be added to table. + continue; // restart, to get another code + } + if (Code < NextEntry) // CODE IS IN TABLE + OutCode = Code; // Set code to output. + + else + { // CODE IS NOT IN TABLE: + OutIndex++; // Keep "first" character of previous output. + OutCode = PrevCode; // Set PrevCode to be output + } + + // EXPAND OutCode IN OutStack + // - Elements up to FirstEntry are Raw-Codes and are not expanded + // - Table Prefices contain indexes to other codes + // - Table Suffices contain the raw codes to be output + while (OutCode >= FirstEntry) + { + if (OutIndex > 4096 || OutCode >= 4096) + return 0; + OutStack[OutIndex++] = Suffix[OutCode]; // Add suffix to Output Stack + OutCode = Prefix[OutCode]; // Loop with preffix + } + + // NOW OutCode IS A RAW CODE, ADD IT TO OUTPUT STACK. + if (OutIndex > 4096) + return 0; + OutStack[OutIndex++] = (unsigned char) OutCode; + + // ADD NEW ENTRY TO TABLE (PrevCode + OutCode) + // (EXCEPT IF PREVIOUS CODE WAS A CLEARCODE) + if (PrevCode != ClearCode) + { + Prefix[NextEntry] = PrevCode; + Suffix[NextEntry] = (unsigned char) OutCode; + NextEntry++; + + // Prevent Translation table overflow: + if (NextEntry >= 4096) + return 0; + + // INCREASE CodeSize IF NextEntry IS INVALID WITH CURRENT CodeSize + if (NextEntry >= (1 << CodeSize)) + { + if (CodeSize < 12) CodeSize++; + else + { + ; + } // Do nothing. Maybe next is Clear Code. + } + } + + PrevCode = Code; + + // Avoid the possibility of overflow on 'bufOut'. + if (nPixels + OutIndex > maxPixels) OutIndex = maxPixels - nPixels; + + // OUTPUT OutStack (LAST-IN FIRST-OUT ORDER) + for (n = OutIndex - 1; n >= 0; n--) + { + if (col == Width) // Check if new row. + { + if (Interlace) + { + // If interlaced:: + if ((row&7) == 0) {row += 8; if (row >= Height) row = 4;} + else if ((row&3) == 0) {row += 8; if (row >= Height) row = 2;} + else if ((row&1) == 0) {row += 4; if (row >= Height) row = 1;} + else row += 2; + } + else // If not interlaced: + row++; + + RowOffset = row * AlignedWidth; // Set new row offset + col = 0; + } + bufOut[RowOffset + col] = OutStack[n]; // Write output + col++; nPixels++; // Increase counters. + } + + } // while (main decompressor loop) + + return whichBit; +} + +// Refer to WINIMAGE.TXT for copyright and patent notices on GIF and LZW. + +#pragma pack() diff --git a/tools/XBMCTex/AnimatedGif.h b/tools/XBMCTex/AnimatedGif.h new file mode 100644 index 0000000000..28bbe65c1d --- /dev/null +++ b/tools/XBMCTex/AnimatedGif.h @@ -0,0 +1,168 @@ +/*! +\file AnimatedGif.h +\brief +*/ + + +// **************************************************************************** +// +// WINIMAGE.H : Generic classes for raster images (MSWindows specialization) +// +// Content: Class declarations of: +// - class CAnimatedGif : Storage class for single images +// - class CAnimatedGifSet : Storage class for sets of images +// - class C_AnimationWindow : Window Class to display animations +// +// (Includes declarations of routines to Load and Save BMP files and to load +// GIF files into these classes). +// +// -------------------------------------------------------------------------- +// +// Copyright 2000, Juan Soulie <jsoulie@cplusplus.com> +// +// Permission to use, copy, modify, distribute and sell this software or any +// part thereof and/or its documentation for any purpose is granted without fee +// provided that the above copyright notice and this permission notice appear +// in all copies. +// +// This software is provided "as is" without express or implied warranty of +// any kind. The author shall have no liability with respect to the +// infringement of copyrights or patents that any modification to the content +// of this file or this file itself may incur. +// +// **************************************************************************** + +#ifdef _LINUX +#include "PlatformDefs.h" +#else +#include <windows.h> +#endif + +#include <vector> +#include <cstdio> + +#pragma pack(1) + +struct COLOR {unsigned char b,g,r,x;}; // Windows GDI expects 4bytes per color +#undef ALIGN +#define ALIGN sizeof(int) ///< Windows GDI expects all int-aligned + +/*! + \ingroup textures + \brief + */ +typedef struct tagGUIRGBQUAD +{ + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; +} +GUIRGBQUAD; + +/*! + \ingroup textures + \brief + */ +typedef struct tagGUIBITMAPINFOHEADER +{ + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} +GUIBITMAPINFOHEADER; + +/*! + \ingroup textures + \brief + */ +typedef struct tagGUIBITMAPINFO +{ + GUIBITMAPINFOHEADER bmiHeader; + GUIRGBQUAD bmiColors[1]; +} GUIBITMAPINFO; + + +// **************************************************************************** +// * CAnimatedGif * +// * Storage class for single images * +// **************************************************************************** +/*! + \ingroup textures + \brief Storage class for single images + */ +class CAnimatedGif +{ +public: + CAnimatedGif(); + virtual ~CAnimatedGif(); + + // standard members: + int Width, Height; ///< Dimensions in pixels + int BPP; // Bits Per Pixel + char* Raster; ///< Bits of Raster Data (Byte Aligned) + COLOR* Palette; ///< Color Map + int BytesPerRow; ///< Width (in bytes) including alignment! + int Transparent; ///< Index of Transparent color (-1 for none) + + // Extra members for animations: + int nLoops; + int xPos, yPos; ///< Relative Position + int Delay; ///< Delay after image in 1/1000 seconds. + int Transparency; ///< Animation Transparency. + // Windows GDI specific: + GUIBITMAPINFO* pbmi; ///< BITMAPINFO structure + + // constructor and destructor: + + // operator= (object copy) + CAnimatedGif& operator= (CAnimatedGif& rhs); + + /// \brief Image initializer (allocates space for raster and palette): + void Init (int iWidth, int iHeight, int iBPP, int iLoops = 0); + + inline char& Pixel (int x, int y) { return Raster[y*BytesPerRow + x];} + +}; + +// **************************************************************************** +// * CAnimatedGifSet * +// * Storage class for sets of images * +// **************************************************************************** +/*! + \ingroup textures + \brief Storage class for sets of images + */ +class CAnimatedGifSet +{ +public: + + // constructor and destructor: + CAnimatedGifSet(); + virtual ~CAnimatedGifSet(); + + int FrameWidth, FrameHeight; ///< Dimensions of ImageSet in pixels. + int nLoops; // Number of Loops (0 = infinite) + + std::vector<CAnimatedGif*> m_vecimg; ///< Images' Vector. + + void AddImage (CAnimatedGif*); ///< Append new image to vector (push_back) + + int GetImageCount() const; + // File Formats: + int LoadGIF (const char* szFile); + + void Release(); +protected: + unsigned char getbyte(FILE *fd); +}; + +#pragma pack() diff --git a/tools/XBMCTex/Bundler.cpp b/tools/XBMCTex/Bundler.cpp new file mode 100644 index 0000000000..9ba63451a5 --- /dev/null +++ b/tools/XBMCTex/Bundler.cpp @@ -0,0 +1,165 @@ +#include "Bundler.h" +#include "EndianSwap.h" + +#ifdef _LINUX +#include <lzo1x.h> +#else +#include "../../xbmc/lib/liblzo/LZO1X.H" +#endif + +// alignment of file blocks - should be a multiple of the sector size of the disk and a power of 2 +// HDD sector = 512 bytes, DVD/CD sector = 2048 bytes +// XBMC supports caching of texures on the HDD for DVD loads, so this can be 512 +#undef ALIGN +#define ALIGN (512) + +bool CBundler::StartBundle() +{ + DataSize = 0; + FileHeaders.clear(); + + lzo_init(); + + return true; +} + +// On big-endian systems, to generate the same bundle on little-endian systems, +// we need to swap all the values in the header + +int CBundler::WriteBundle(const char* Filename, int NoProtect) +{ + // calc data offset + DWORD headerSize = sizeof(XPR_FILE_HEADER) + FileHeaders.size() * sizeof(FileHeader_t); + + // setup header + XPRHeader.dwMagic = Endian_SwapLE32(XPR_MAGIC_HEADER_VALUE | ((2+(NoProtect << 7)) << 24)); // version 2 + XPRHeader.dwHeaderSize = Endian_SwapLE32(headerSize); + + headerSize = (headerSize + (ALIGN-1)) & ~(ALIGN-1); + XPRHeader.dwTotalSize = Endian_SwapLE32(headerSize + DataSize); + + // create our header in memory + BYTE *headerBuf = (BYTE *)malloc(headerSize); + if (!headerBuf) return -1; + + BYTE* buf = headerBuf; + memcpy(buf, &XPRHeader, sizeof(XPR_FILE_HEADER)); + buf += sizeof(XPR_FILE_HEADER); + + for (std::list<FileHeader_t>::iterator i = FileHeaders.begin(); i != FileHeaders.end(); ++i) + { + // Swap values on big-endian systems + i->Offset = Endian_SwapLE32(i->Offset + headerSize); + i->UnpackedSize = Endian_SwapLE32(i->UnpackedSize); + i->PackedSize = Endian_SwapLE32(i->PackedSize); + memcpy(buf, &(*i), sizeof(FileHeader_t)); + buf += sizeof(FileHeader_t); + } + memset(buf, 0, headerBuf + headerSize - buf); + + // write file + FILE *file = fopen(Filename, "wb"); + if (!file) + { + free(Data); + free(headerBuf); + return -1; + } + + size_t n = fwrite(headerBuf, 1, headerSize, file); + if (n != headerSize) + { + free(Data); + free(headerBuf); + fclose(file); + return -1; + } + + n = fwrite(Data, 1, DataSize, file); + if (n != DataSize) + { + free(Data); + free(headerBuf); + fclose(file); + return -1; + } + + free(Data); + free(headerBuf); + fclose(file); + + return DataSize + headerSize; +} + +bool CBundler::AddFile(const char* Filename, int nBuffers, const void** Buffers, DWORD* Sizes) +{ + FileHeader_t Header; + + memset(Header.Name, 0, sizeof(Header.Name)); + for (int i = 0; i < (int)sizeof(Header.Name) && Filename[i]; ++i) + Header.Name[i] = tolower(Filename[i]); + Header.Name[sizeof(Header.Name)-1] = 0; + + Header.Offset = DataSize; + Header.PackedSize = 0; + Header.UnpackedSize = 0; + for (int i = 0; i < nBuffers; ++i) + Header.UnpackedSize += Sizes[i]; + + // allocate enough memory for the total unpacked size + BYTE* buf = (BYTE*)malloc(Header.UnpackedSize); + if (!buf) return false; // failure to allocate memory + + BYTE* p = buf; + for (int i = 0; i < nBuffers; ++i) + { + memcpy(p, Buffers[i], Sizes[i]); + p += Sizes[i]; + } + + // grab a temporary buffer for unpacking into + BYTE *compressedBuf = (BYTE*)malloc(Header.UnpackedSize); + if (!compressedBuf) + { + free(buf); + return false; + } + + // and a working buffer for lzo + lzo_voidp workingBuf = malloc(LZO1X_999_MEM_COMPRESS); + if (!workingBuf) + { + free(buf); + free(compressedBuf); + return false; + } + + if (lzo1x_999_compress(buf, Header.UnpackedSize, compressedBuf, (lzo_uint*)&Header.PackedSize, workingBuf) != LZO_E_OK) + { + printf("Compression failure\n"); + free(buf); + free(compressedBuf); + free(workingBuf); + return false; + } + free(workingBuf); + + lzo_uint s = Header.UnpackedSize; + lzo1x_optimize(compressedBuf, Header.PackedSize, buf, &s, NULL); + free(buf); + + // now increase the size of our buffer + DWORD ExtraNeeded = (Header.PackedSize + (ALIGN-1)) & ~(ALIGN-1); + + // reallocate our data dump + Data = (BYTE*)realloc(Data, DataSize + ExtraNeeded); + + memcpy(Data + DataSize, compressedBuf, Header.PackedSize); + free(compressedBuf); + + memset(Data + DataSize + Header.PackedSize, 0, ExtraNeeded - Header.PackedSize); + DataSize += ExtraNeeded; + FileHeaders.push_back(Header); + + return true; +} diff --git a/tools/XBMCTex/Bundler.h b/tools/XBMCTex/Bundler.h new file mode 100644 index 0000000000..99db1a46c0 --- /dev/null +++ b/tools/XBMCTex/Bundler.h @@ -0,0 +1,32 @@ +#pragma once + +#include <cstdlib> +#include <ctype.h> +#include <cstdio> +#include <list> +#include "xbox.h" + +class CBundler +{ + XPR_FILE_HEADER XPRHeader; + struct FileHeader_t + { + // 128 bytes total + char Name[116]; + DWORD Offset; + DWORD UnpackedSize; + DWORD PackedSize; + }; + std::list<FileHeader_t> FileHeaders; + BYTE* Data; + DWORD DataSize; + +public: + CBundler() { Data = NULL; DataSize = 0; } + ~CBundler() {} + + bool StartBundle(); + int WriteBundle(const char* Filename, int NoProtect); + + bool AddFile(const char* Filename, int nBuffers, const void** Buffers, DWORD* Sizes); +}; diff --git a/tools/XBMCTex/Makefile.in b/tools/XBMCTex/Makefile.in new file mode 100644 index 0000000000..33042b5549 --- /dev/null +++ b/tools/XBMCTex/Makefile.in @@ -0,0 +1,31 @@ +ARCH=@ARCH@ + +INCLUDES = -I../../xbmc/linux -I../../guilib -I../../xbmc/ -I../../xbmc/utils +DEFINES = -DHAS_SDL +LIBS = @LIBS@ -lSDL_image +OBJS = \ + AnimatedGif.o \ + Bundler.o \ + SurfaceSDL.o \ + XBMCTex.o \ + xbox.o \ + xwinapi.o \ + XFileUtils.o \ + XHandle.o \ + XTimeUtils.o \ + sha.o + +TARGET = XBMCTex +CLEAN_FILES=$(TARGET) + +all: $(TARGET) + +include ../../Makefile.include + +$(TARGET): $(OBJS) +ifeq ($(findstring osx,$(ARCH)), osx) + $(MAKE) -f Makefile.osx +else + g++ $(OBJS) $(LDFLAGS) $(LIBS) -o $(TARGET) +endif + diff --git a/tools/XBMCTex/Makefile.osx b/tools/XBMCTex/Makefile.osx new file mode 100644 index 0000000000..8fc626497d --- /dev/null +++ b/tools/XBMCTex/Makefile.osx @@ -0,0 +1,45 @@ + +# To build an universal binary, uncomment out the "UNIVERSAL" variable below +# You need to have installed MacPorts for both arch (at least lzo libsdl libsdl_image and their dependencies) +# Follow the README.osx but keep both ppc and i386 for universal_archs in /opt/local/etc/macports/macports.conf: +# "universal_archs ppc i386" +#UNIVERSAL = -arch ppc -arch i386 + +DEFINES = -DHAS_SDL -D_LINUX +INCLUDES = -I../../xbmc/linux -I../../guilib -I../../xbmc/ -I../../xbmc/utils -I/opt/local/include +# To build with shared MacPorts libs +LIBS = -lSDL -lSDL_image -llzo +LDFLAGS = -L/opt/local/lib -lSDLmain -framework Foundation -framework Cocoa +# To build with static MacPorts libs +# You need to have used "+universal" when installing MacPorts! (see README.osx) +#LIBS = /opt/local/lib/liblzo.a /opt/local/lib/libSDL_image.a /opt/local/lib/libpng.a /opt/local/lib/libtiff.a /opt/local/lib/libjpeg.a /opt/local/lib/libz.a +# LDFLAGS is the output of `sdl-config --static-libs` +#LDFLAGS = -L/opt/local/lib /opt/local/lib/libSDLmain.a /opt/local/lib/libSDL.a -Wl,-framework,OpenGL -Wl,-framework,Cocoa -Wl,-framework,QuickTime -Wl,-framework,ApplicationServices -Wl,-framework,Carbon -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,IOKit +OBJS = \ + AnimatedGif.o \ + Bundler.o \ + SurfaceSDL.o \ + XBMCTex.o \ + xbox.o \ + xwinapi.o \ + XFileUtils.o \ + XHandle.o \ + XTimeUtils.o \ + sha.o \ + OSXGNUReplacements.o + +TARGET = XBMCTex + +all: $(TARGET) + +$(TARGET): $(OBJS) + g++ -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 $(UNIVERSAL) $(OBJS) $(LDFLAGS) $(LIBS) -o $(TARGET) + +.cpp.o: + g++ -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 $(UNIVERSAL) $(DEFINES) $(INCLUDES) -c -o $@ $< + +.c.o: + gcc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 $(UNIVERSAL) $(DEFINES) $(INCLUDES) -c -o $@ $< + +clean: + rm -f $(TARGET) *.o diff --git a/tools/XBMCTex/OSXGNUReplacements.c b/tools/XBMCTex/OSXGNUReplacements.c new file mode 100644 index 0000000000..c94b0fa429 --- /dev/null +++ b/tools/XBMCTex/OSXGNUReplacements.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2005-2009 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include <pthread.h> +#include <errno.h> + +#include "OSXGNUReplacements.h" + +size_t strnlen(const char *s, size_t n) +{ + size_t i; + for (i=0; i<n && s[i] != '\0'; i++) + /* noop */ ; + return i; +} + +char* strndup(char const *s, size_t n) +{ + size_t len = strnlen(s, n); + char *new_str = (char*)malloc(len + 1); + if (new_str == NULL) + return NULL; + new_str[len] = '\0'; + + return (char*)memcpy(new_str, s, len); +} + +/* +From http://svn.digium.com/view/asterisk/trunk/main/utils.c +GNU General Public License Version 2 +Brief Reentrant replacement for gethostbyname for BSD-based systems. Note This +routine is derived from code originally written and placed in the public +domain by Enzo Michelangeli <em@em.no-ip.com> +*/ +static pthread_mutex_t gethostbyname_r_mutex = PTHREAD_MUTEX_INITIALIZER; +// +int gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + int hsave; + struct hostent *ph; + pthread_mutex_lock(&gethostbyname_r_mutex); /* begin critical area */ + hsave = h_errno; + + ph = gethostbyname(name); + *h_errnop = h_errno; /* copy h_errno to *h_herrnop */ + if (ph == NULL) { + *result = NULL; + } else { + char **p, **q; + char *pbuf; + int nbytes = 0; + int naddr = 0, naliases = 0; + /* determine if we have enough space in buf */ + + /* count how many addresses */ + for (p = ph->h_addr_list; *p != 0; p++) { + nbytes += ph->h_length; /* addresses */ + nbytes += sizeof(*p); /* pointers */ + naddr++; + } + nbytes += sizeof(*p); /* one more for the terminating NULL */ + + /* count how many aliases, and total length of strings */ + for (p = ph->h_aliases; *p != 0; p++) { + nbytes += (strlen(*p)+1); /* aliases */ + nbytes += sizeof(*p); /* pointers */ + naliases++; + } + nbytes += sizeof(*p); /* one more for the terminating NULL */ + + /* here nbytes is the number of bytes required in buffer */ + /* as a terminator must be there, the minimum value is ph->h_length */ + if (nbytes > buflen) { + *result = NULL; + pthread_mutex_unlock(&gethostbyname_r_mutex); /* end critical area */ + return ERANGE; /* not enough space in buf!! */ + } + + /* There is enough space. Now we need to do a deep copy! */ + /* Allocation in buffer: + from [0] to [(naddr-1) * sizeof(*p)]: + pointers to addresses + at [naddr * sizeof(*p)]: + NULL + from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] : + pointers to aliases + at [(naddr+naliases+1) * sizeof(*p)]: + NULL + then naddr addresses (fixed length), and naliases aliases (asciiz). + */ + + *ret = *ph; /* copy whole structure (not its address!) */ + + /* copy addresses */ + q = (char **)buf; /* pointer to pointers area (type: char **) */ + ret->h_addr_list = q; /* update pointer to address list */ + pbuf = buf + ((naddr + naliases + 2) * sizeof(*p)); /* skip that area */ + for (p = ph->h_addr_list; *p != 0; p++) { + memcpy(pbuf, *p, ph->h_length); /* copy address bytes */ + *q++ = pbuf; /* the pointer is the one inside buf... */ + pbuf += ph->h_length; /* advance pbuf */ + } + *q++ = NULL; /* address list terminator */ + + /* copy aliases */ + ret->h_aliases = q; /* update pointer to aliases list */ + for (p = ph->h_aliases; *p != 0; p++) { + strcpy(pbuf, *p); /* copy alias strings */ + *q++ = pbuf; /* the pointer is the one inside buf... */ + pbuf += strlen(*p); /* advance pbuf */ + *pbuf++ = 0; /* string terminator */ + } + *q++ = NULL; /* terminator */ + + strcpy(pbuf, ph->h_name); /* copy alias strings */ + ret->h_name = pbuf; + pbuf += strlen(ph->h_name); /* advance pbuf */ + *pbuf++ = 0; /* string terminator */ + + *result = ret; /* and let *result point to structure */ + + } + h_errno = hsave; /* restore h_errno */ + pthread_mutex_unlock(&gethostbyname_r_mutex); /* end critical area */ + + return (*result == NULL); /* return 0 on success, non-zero on error */ +} + +/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> + +/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR + (and null-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'd as + necessary. Returns the number of characters read (not including the + null terminator), or -1 on error or EOF. */ + +ssize_t +getdelim (lineptr, n, terminator, stream) + char **lineptr; + size_t *n; + int terminator; + FILE *stream; +{ + char *line, *p; + size_t size, copy; + + if (stream == NULL || lineptr == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + if (ferror (stream)) + return -1; + + /* Make sure we have a line buffer to start with. */ + if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars. */ + { +#ifndef MAX_CANON +#define MAX_CANON 256 +#endif + line = realloc (*lineptr, MAX_CANON); + if (line == NULL) + return -1; + *lineptr = line; + *n = MAX_CANON; + } + + line = *lineptr; + size = *n; + + copy = size; + p = line; + + while (1) + { + size_t len; + + while (--copy > 0) + { + register int c = getc (stream); + if (c == EOF) + goto lose; + else if ((*p++ = c) == terminator) + goto win; + } + + /* Need to enlarge the line buffer. */ + len = p - line; + size *= 2; + line = realloc (line, size); + if (line == NULL) + goto lose; + *lineptr = line; + *n = size; + p = line + len; + copy = size - len; + } + + lose: + if (p == *lineptr) + return -1; + /* Return a partial line since we got an error in the middle. */ + win: + *p = '\0'; + return p - *lineptr; +} + +ssize_t +getline (char **lineptr, size_t *n, FILE *stream) +{ + return getdelim (lineptr, n, '\n', stream); +} diff --git a/tools/XBMCTex/OSXGNUReplacements.h b/tools/XBMCTex/OSXGNUReplacements.h new file mode 100644 index 0000000000..7209544140 --- /dev/null +++ b/tools/XBMCTex/OSXGNUReplacements.h @@ -0,0 +1,74 @@ +#ifndef __OSXPLATFORM_H__ +#define __OSXPLATFORM_H__ +/* + * Copyright (C) 2005-2009 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +// This is a catch all for GNU routines that do not exist under OSX. +#include <netdb.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +size_t strnlen(const char *s, size_t n); +char* strndup(char const *s, size_t n); +int gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/* getdelim.h --- Prototype for replacement getdelim function. + Copyright (C) 2005 Free Software Foundation, Inc. + + 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, 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. */ + +/* Written by Simon Josefsson. */ +# include <stddef.h> +# include <stdio.h> +# include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +ssize_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *stream); +ssize_t getline (char **lineptr, size_t *n, FILE *stream); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/tools/XBMCTex/README.osx b/tools/XBMCTex/README.osx new file mode 100644 index 0000000000..3ba8fce82b --- /dev/null +++ b/tools/XBMCTex/README.osx @@ -0,0 +1,24 @@ +To compile XBMCTex on Mac OS X, run make -f Makefile.osx + +I) By default it will build XBMCTex with shared MacPorts libs + +II) To build with static MacPorts libs +1) You need to have used "+universal" when installing MacPorts! (see XBMC/README.osx) +2) You need to force lzo to build a static lib + $ sudo nano /opt/local/var/macports/sources/rsync.macports.org/release/ports/devel/lzo/Portfile + change "--disable-static" to "--enable-static" + + $ sudo port install lzo +universal + (if lzo was previously installed, you will have to uninstall it first) + +3) Uncomment out the following variables in Makefile.osx +LIBS = /opt/local/lib/liblzo.a /opt/local/lib/libSDL_image.a /opt/local/lib/libpng.a /opt/local/lib/libtiff.a /opt/local/lib/libjpeg.a /opt/local/lib/libz.a +LDFLAGS = -L/opt/local/lib /opt/local/lib/libSDLmain.a /opt/local/lib/libSDL.a -Wl,-framework,OpenGL -Wl,-framework,Cocoa -Wl,-framework,QuickTime -Wl,-framework,ApplicationServices -Wl,-framework,Carbon -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,IOKit +(LDFLAGS is the output of `sdl-config --static-libs`) + +III) To build an universal binary, uncomment out the "UNIVERSAL" variable in Makefile.osx +You need to have installed MacPorts for both arch (at least lzo libsdl +libsdl_image and their dependencies) +Follow the XBMC/README.osx but keep both ppc and i386 for universal_archs +in /opt/local/etc/macports/macports.conf: + "universal_archs ppc i386" diff --git a/tools/XBMCTex/Surface.cpp b/tools/XBMCTex/Surface.cpp new file mode 100644 index 0000000000..c398c8f3ee --- /dev/null +++ b/tools/XBMCTex/Surface.cpp @@ -0,0 +1,188 @@ +// class CSurface +#include "Surface.h" + +#ifndef HAS_SDL + +#include <stdio.h> +#include "xbox.h" + +CGraphicsDevice g_device; + +CSurface::CSurface() +{ + m_surface = NULL; + m_width = 0; + m_height = 0; + m_bpp = 0; +} + +CSurface::~CSurface() +{ + if (m_surface) + m_surface->Release(); +} + +bool CSurface::Create(unsigned int width, unsigned int height, CSurface::FORMAT format) +{ + if (m_surface) + { + m_surface->Release(); + m_surface = NULL; + } + + m_info.width = width; + m_info.height = height; + m_info.format = format; + + if (format == FMT_LIN_ARGB) + { // round width to multiple of 64 pixels + m_width = (width + 63) & ~63; + m_height = height; + } + else + { // round up to nearest power of 2 + m_width = PadPow2(width); + m_height = PadPow2(height); + } + m_bpp = (format == FMT_PALETTED) ? 1 : 4; + + if (!g_device.CreateSurface(m_width, m_height, format, this)) + return false; + + Clear(); + return true; +} + +void CSurface::Clear() +{ + CSurfaceRect rect; + if (Lock(&rect)) + { + BYTE *pixels = rect.pBits; + for (unsigned int i = 0; i < m_height; i++) + { + memset(pixels, 0, rect.Pitch); + pixels += rect.Pitch; + } + Unlock(); + } +} + +bool CSurface::CreateFromFile(const char *Filename, FORMAT format) +{ + // get the info from the file + D3DXIMAGE_INFO info; + if (S_OK != D3DXGetImageInfoFromFile(Filename, &info)) + return false; + + if (!Create(info.Width, info.Height, format)) + return false; + + bool success = (S_OK == D3DXLoadSurfaceFromFile(m_surface, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL)); + ClampToEdge(); + return success; +} + + +void CSurface::ClampToEdge() +{ + // fix up the last row and column to simulate clamp_to_edge + if (!m_info.width || !m_info.height == 0) + return; // invalid texture + CSurfaceRect rect; + if (Lock(&rect)) + { + for (unsigned int y = 0; y < m_info.height; y++) + { + BYTE *src = rect.pBits + y * rect.Pitch; + for (unsigned int x = m_info.width; x < m_width; x++) + memcpy(src + x*m_bpp, src + (m_info.width - 1)*m_bpp, m_bpp); + } + BYTE *src = rect.pBits + (m_info.height - 1) * rect.Pitch; + for (unsigned int y = m_info.height; y < m_height; y++) + { + BYTE *dest = rect.pBits + y * rect.Pitch; + memcpy(dest, src, rect.Pitch); + } + Unlock(); + } +} + +bool CSurface::Lock(CSurfaceRect *rect) +{ + D3DLOCKED_RECT lr; + if (m_surface && rect) + { + m_surface->LockRect(&lr, NULL, 0); + rect->pBits = (BYTE *)lr.pBits; + rect->Pitch = lr.Pitch; + return true; + } + return false; +} + +bool CSurface::Unlock() +{ + if (m_surface) + { + m_surface->UnlockRect(); + return true; + } + return false; +} + +CGraphicsDevice::CGraphicsDevice() +{ + m_pD3D = NULL; + m_pD3DDevice = NULL; +} + +CGraphicsDevice::~CGraphicsDevice() +{ + if (m_pD3DDevice) + m_pD3DDevice->Release(); + if (m_pD3D) + m_pD3D->Release(); +} + +bool CGraphicsDevice::Create() +{ + m_pD3D = Direct3DCreate8(D3D_SDK_VERSION); + if (!m_pD3D) + { + printf("Cannot init D3D\n"); + return false; + } + + HRESULT hr; + D3DDISPLAYMODE dispMode; + D3DPRESENT_PARAMETERS presentParams; + + m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode); + + ZeroMemory(&presentParams, sizeof(presentParams)); + presentParams.Windowed = TRUE; + presentParams.hDeviceWindow = GetConsoleWindow(); + presentParams.SwapEffect = D3DSWAPEFFECT_COPY; + presentParams.BackBufferWidth = 8; + presentParams.BackBufferHeight = 8; + presentParams.BackBufferFormat = dispMode.Format; + + hr = m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &m_pD3DDevice); + if (FAILED(hr)) + { + printf("Cannot init D3D device: %08x\n", hr); + m_pD3D->Release(); + return false; + } + return true; +} + +bool CGraphicsDevice::CreateSurface(unsigned int width, unsigned int height, enum CSurface::FORMAT format, CSurface *surface) +{ + if (m_pD3DDevice) + return (S_OK == m_pD3DDevice->CreateImageSurface(width, height, (format == CSurface::FMT_PALETTED) ? D3DFMT_P8 : D3DFMT_A8R8G8B8, &surface->m_surface)); + return false; +} + +#endif
\ No newline at end of file diff --git a/tools/XBMCTex/Surface.h b/tools/XBMCTex/Surface.h new file mode 100644 index 0000000000..2a253fff9b --- /dev/null +++ b/tools/XBMCTex/Surface.h @@ -0,0 +1,79 @@ +// class CSurface - wraps the various interfaces (SDL/DirectX) +#pragma once + +#ifdef HAS_SDL +#include "SurfaceSDL.h" +#else + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define _WIN32_WINNT 0x500 // Win 2k/XP REQUIRED! +#include <windows.h> + +#include "D3D8.h" +#include "D3DX8.h" + +class CSurfaceRect +{ +public: + CSurfaceRect() + { + pBits = NULL; + Pitch = 0; + }; + BYTE *pBits; + DWORD Pitch; +}; + +class CSurface +{ +public: + CSurface(); + ~CSurface(); + + enum FORMAT { FMT_ARGB, FMT_LIN_ARGB, FMT_PALETTED }; + struct ImageInfo + { + unsigned int width; + unsigned int height; + FORMAT format; + }; + + bool CreateFromFile(const char *Filename, FORMAT format); + + bool Create(unsigned int width, unsigned int height, FORMAT format); + + bool Lock(CSurfaceRect *rect); + bool Unlock(); + + unsigned int Width() const { return m_width; }; + unsigned int Height() const { return m_height; }; + unsigned int BPP() const { return m_bpp; }; + unsigned int Pitch() const { return m_width * m_bpp; }; + + const ImageInfo &Info() const { return m_info; }; +private: + friend class CGraphicsDevice; + void Clear(); + void ClampToEdge(); + LPDIRECT3DSURFACE8 m_surface; + unsigned int m_width; + unsigned int m_height; + unsigned int m_bpp; + ImageInfo m_info; +}; + +class CGraphicsDevice +{ +public: + CGraphicsDevice(); + ~CGraphicsDevice(); + bool Create(); + bool CreateSurface(unsigned int width, unsigned int height, CSurface::FORMAT format, CSurface *surface); +private: + LPDIRECT3D8 m_pD3D; + LPDIRECT3DDEVICE8 m_pD3DDevice; +}; + +extern CGraphicsDevice g_device; +#endif + diff --git a/tools/XBMCTex/SurfaceSDL.cpp b/tools/XBMCTex/SurfaceSDL.cpp new file mode 100644 index 0000000000..2e29ae9831 --- /dev/null +++ b/tools/XBMCTex/SurfaceSDL.cpp @@ -0,0 +1,159 @@ +// class CSurface +#include "SurfaceSDL.h" + +#ifdef HAS_SDL +#include <stdio.h> +#include "xbox.h" + +CGraphicsDevice g_device; + +CSurface::CSurface() +{ + m_surface = NULL; + m_width = 0; + m_height = 0; + m_bpp = 0; +} + +CSurface::~CSurface() +{ + if (m_surface) + SDL_FreeSurface(m_surface); +} + +bool CSurface::Create(unsigned int width, unsigned int height, CSurface::FORMAT format) +{ + if (m_surface) + { + SDL_FreeSurface(m_surface); + m_surface = NULL; + } + + m_info.width = width; + m_info.height = height; + m_info.format = format; + + if (format == FMT_LIN_ARGB) + { // round width to multiple of 64 pixels + m_width = (width + 63) & ~63; + m_height = height; + } + else + { // round up to nearest power of 2 + m_width = PadPow2(width); + m_height = PadPow2(height); + } + m_bpp = (format == FMT_PALETTED) ? 1 : 4; + + m_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, m_width, m_height, m_bpp * 8, + RMASK, GMASK, BMASK, AMASK); + + if (0 == m_surface) + return false; + + Clear(); + return true; +} + +void CSurface::Clear() +{ + CSurfaceRect rect; + if (Lock(&rect)) + { + BYTE *pixels = rect.pBits; + for (unsigned int i = 0; i < m_height; i++) + { + memset(pixels, 0, rect.Pitch); + pixels += rect.Pitch; + } + Unlock(); + } +} + +bool CSurface::CreateFromFile(const char *Filename, FORMAT format) +{ + SDL_Surface *original = IMG_Load(Filename); + if (!original) + return false; + + if (!Create(original->w, original->h, format)) + { + SDL_FreeSurface(original); + return false; + } + + // copy into our surface + SDL_SetAlpha(original, 0, 255); + int ret = SDL_BlitSurface(original, NULL, m_surface, NULL); + SDL_FreeSurface(original); + + ClampToEdge(); + + return (0 == ret); +} + +void CSurface::ClampToEdge() +{ + // fix up the last row and column to simulate clamp_to_edge + if (!m_info.width || !m_info.height == 0) + return; // invalid texture + CSurfaceRect rect; + if (Lock(&rect)) + { + for (unsigned int y = 0; y < m_info.height; y++) + { + BYTE *src = rect.pBits + y * rect.Pitch; + for (unsigned int x = m_info.width; x < m_width; x++) + memcpy(src + x*m_bpp, src + (m_info.width - 1)*m_bpp, m_bpp); + } + BYTE *src = rect.pBits + (m_info.height - 1) * rect.Pitch; + for (unsigned int y = m_info.height; y < m_height; y++) + { + BYTE *dest = rect.pBits + y * rect.Pitch; + memcpy(dest, src, rect.Pitch); + } + Unlock(); + } +} + +bool CSurface::Lock(CSurfaceRect *rect) +{ + if (m_surface && rect) + { + SDL_LockSurface(m_surface); + rect->pBits = (BYTE *)m_surface->pixels; + rect->Pitch = m_surface->pitch; + return true; + } + return false; +} + +bool CSurface::Unlock() +{ + if (m_surface) + { + SDL_UnlockSurface(m_surface); + return true; + } + return false; +} + +CGraphicsDevice::CGraphicsDevice() +{ +} + +CGraphicsDevice::~CGraphicsDevice() +{ +} + +bool CGraphicsDevice::Create() +{ + return true; +} + +bool CGraphicsDevice::CreateSurface(unsigned int width, unsigned int height, enum CSurface::FORMAT format, CSurface *surface) +{ + return false; +} +#endif + diff --git a/tools/XBMCTex/SurfaceSDL.h b/tools/XBMCTex/SurfaceSDL.h new file mode 100644 index 0000000000..22bc7ed2c1 --- /dev/null +++ b/tools/XBMCTex/SurfaceSDL.h @@ -0,0 +1,90 @@ +// class CSurface - wraps the various interfaces (SDL/DirectX) +#pragma once + +#ifdef HAS_SDL + +#ifdef _LINUX +#include "PlatformDefs.h" +#else +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define _WIN32_WINNT 0x500 // Win 2k/XP REQUIRED! +#include <windows.h> +#endif + +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <SDL/SDL_endian.h> + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define RMASK 0x0000ff00 +#define GMASK 0x00ff0000 +#define BMASK 0xff000000 +#define AMASK 0x000000ff +#else +#define RMASK 0x00ff0000 +#define GMASK 0x0000ff00 +#define BMASK 0x000000ff +#define AMASK 0xff000000 +#endif + +class CSurfaceRect +{ +public: + CSurfaceRect() + { + pBits = NULL; + Pitch = 0; + }; + BYTE *pBits; + DWORD Pitch; +}; + +class CSurface +{ +public: + CSurface(); + ~CSurface(); + + enum FORMAT { FMT_ARGB, FMT_LIN_ARGB, FMT_PALETTED }; + struct ImageInfo + { + unsigned int width; + unsigned int height; + FORMAT format; + }; + + bool CreateFromFile(const char *Filename, FORMAT format); + + bool Create(unsigned int width, unsigned int height, FORMAT format); + + bool Lock(CSurfaceRect *rect); + bool Unlock(); + + unsigned int Width() const { return m_width; }; + unsigned int Height() const { return m_height; }; + unsigned int BPP() const { return m_bpp; }; + unsigned int Pitch() const { return m_width * m_bpp; }; + + const ImageInfo &Info() const { return m_info; }; +private: + void Clear(); + void ClampToEdge(); + friend class CGraphicsDevice; + SDL_Surface *m_surface; + unsigned int m_width; + unsigned int m_height; + unsigned int m_bpp; + ImageInfo m_info; +}; + +class CGraphicsDevice +{ +public: + CGraphicsDevice(); + ~CGraphicsDevice(); + bool Create(); + bool CreateSurface(unsigned int width, unsigned int height, CSurface::FORMAT format, CSurface *surface); +}; + +extern CGraphicsDevice g_device; +#endif diff --git a/tools/XBMCTex/XBMCTex.cpp b/tools/XBMCTex/XBMCTex.cpp new file mode 100644 index 0000000000..290e3af255 --- /dev/null +++ b/tools/XBMCTex/XBMCTex.cpp @@ -0,0 +1,716 @@ +// XBMCTex.cpp : Defines the entry point for the console application. +// + +#include "AnimatedGif.h" +#include "Bundler.h" +#include <stdio.h> +#include <algorithm> +#include "cmdlineargs.h" +#include "Surface.h" +#include "EndianSwap.h" + +#ifdef _LINUX +#ifndef __APPLE__ +#include <linux/limits.h> +#endif +#include <string.h> +#include "XFileUtils.h" +#include "PlatformDefs.h" +#include "xwinapi.h" +#define WIN32_FIND_DATAA WIN32_FIND_DATA +#else +#define XBMC_FILE_SEP '\\' +#endif + +// Debug macros +#if defined(_DEBUG) && defined(_MSC_VER) +#include <crtdbg.h> +#define TRACE0(f) _RPT0(_CRT_WARN, f) +#define TRACE1(f, a) _RPT1(_CRT_WARN, f, a) +#define TRACE2(f, a, b) _RPT2(_CRT_WARN, f, a, b) +#define TRACE3(f, a, b, c) _RPT3(_CRT_WARN, f, a, b, c) +#define TRACE4(f, a, b, c, d) _RPT4(_CRT_WARN, f, a, b, c, d) +#define TRACE5(f, a, b, c, d, e) _RPT_BASE((_CRT_WARN, NULL, 0, NULL, f, a, b, c, d, e)) + +#else + +#define TRACE0(f) +#define TRACE1(f, a) +#define TRACE2(f, a, b) +#define TRACE3(f, a, b, c) +#define TRACE4(f, a, b, c, d) +#define TRACE5(f, a, b, c, d, e) +#endif + +extern "C" void SHA1(const BYTE* buf, DWORD len, BYTE hash[20]); + +CBundler Bundler; + +UINT UncompressedSize; +UINT CompressedSize; +UINT TotalSrcPixels; +UINT TotalDstPixels; + +#pragma pack(push,1) +struct RGBCOLOUR +{ + BYTE b; + BYTE g; + BYTE r; + BYTE a; +}; +#pragma pack(pop) + +void PrintImageInfo(const CSurface::ImageInfo& info) +{ + printf("%4dx%-4d ", info.width, info.height); + fputs("->", stdout); +} + +void PrintAnimInfo(const CAnimatedGifSet& Anim) +{ + printf("%4dx%-4d (%5df)->", Anim.FrameWidth, Anim.FrameHeight, Anim.GetImageCount()); +} + +#define CheckHR(hr) if (FAILED(hr)) { printf("ERROR: %08x\n", hr); if (pCompSurf) pCompSurf->Release(); if (pDstSurf) pDstSurf->Release(); return false; } + +struct XPRFile_t +{ + // the following are pointers into our headerBuf + DWORD* flags; + struct AnimInfo_t { + DWORD nLoops; + DWORD RealSize; + } *AnimInfo; + D3DPalette* D3DPal; + struct Texture_t { + D3DTexture D3DTex; + DWORD RealSize; + } *Texture; + + int nImages; +}; + +BYTE *headerBuf = NULL; +DWORD headerSize = 0; + +BYTE *imageData = NULL; +DWORD imageSize = 0; + +static XPRFile_t XPRFile; + +enum XPR_FLAGS +{ + XPRFLAG_PALETTE = 0x00000001, + XPRFLAG_ANIM = 0x00000002 +}; + +#undef CheckHR + +void CommitXPR(const char* Filename) +{ + if (!XPRFile.nImages) + return; + + // Conversion for big-endian systems + // flags is used/updated in different places + // so swap it only before to call AddFile + *XPRFile.flags = Endian_SwapLE32(*XPRFile.flags); + + const void* Buffers[2] = { headerBuf, imageData }; + DWORD Sizes[2] = { headerSize, imageSize }; + if (!Bundler.AddFile(Filename, 2, Buffers, Sizes)) + printf("ERROR: Unable to compress data (out of memory?)\n"); + + // free our image memory + free(imageData); + imageData = NULL; + imageSize = 0; +} + +void WriteXPRHeader(DWORD* pal, int nImages, DWORD nLoops = 0) +{ + // compute how large our header requires + headerSize = sizeof(DWORD); + if (nImages > 1) // need AnimInfo header + headerSize += sizeof(XPRFile_t::AnimInfo_t); + if (pal) // need D3DPal header + headerSize += sizeof(D3DPalette); + headerSize += nImages * sizeof(XPRFile_t::Texture_t); + + // align to 128 byte boundary + headerSize = (headerSize + 127) & ~127; + + // allocate space for our header + headerBuf = (BYTE *)realloc(headerBuf, headerSize); + memset(headerBuf, 0, headerSize); + + // setup our header + unsigned int offset = 0; + XPRFile.flags = (DWORD *)&headerBuf[offset]; + offset += sizeof(DWORD); + if (nImages > 1) + { + XPRFile.AnimInfo = (XPRFile_t::AnimInfo_t *)&headerBuf[offset]; + offset += sizeof(XPRFile_t::AnimInfo_t); + } + else + XPRFile.AnimInfo = NULL; + if (pal) + { + XPRFile.D3DPal = (D3DPalette *)&headerBuf[offset]; + offset += sizeof(D3DPalette); + } + else + XPRFile.D3DPal = NULL; + XPRFile.Texture = (XPRFile_t::Texture_t *)&headerBuf[offset]; + XPRFile.nImages = 0; + + *XPRFile.flags = nImages << 16; + + if (nImages > 1) + { + *XPRFile.flags |= XPRFLAG_ANIM; + XPRFile.AnimInfo->nLoops = nLoops; + } + + if (pal) + { + // commit memory for palette + imageData = (BYTE*)realloc(imageData, 1024); + + *XPRFile.flags |= XPRFLAG_PALETTE; + XPRFile.D3DPal->Common = Endian_SwapLE32(1 | (3 << 16)); + XPRFile.D3DPal->Data = 0; + XPRFile.D3DPal->Lock = 0; + memcpy(imageData, pal, 1024); + imageSize += 1024; + } +} + +void AppendXPRImage(CSurface &surface, XB_D3DFORMAT fmt) +{ + UINT Size = ((surface.Pitch() * surface.Height()) + 127) & ~127; // must be 128-byte aligned for any following images + + // reallocate enough data for our image + imageData = (BYTE*)realloc(imageData, imageSize + Size); + memset(imageData + imageSize, 0, Size); + + CSurfaceRect rect; + if (!surface.Lock(&rect)) + return; + + if (IsSwizzledFormat(fmt)) + { + // Swizzle for xbox + SwizzleRect(rect.pBits, 0, imageData + imageSize, surface.Width(), surface.Height(), surface.BPP()); + } + else + { + // copy + BYTE* src = rect.pBits; + BYTE* dst = imageData + imageSize; + for (UINT y = 0; y < surface.Height(); ++y) + { + memcpy(dst, src, surface.Pitch()); + src += rect.Pitch; + dst += surface.Pitch(); + } + } + + surface.Unlock(); + + SetTextureHeader(surface.Width(), surface.Height(), 1, 0, fmt, + &XPRFile.Texture[XPRFile.nImages].D3DTex, imageSize, surface.Pitch()); + if (!(*XPRFile.flags & XPRFLAG_ANIM)) + XPRFile.Texture[XPRFile.nImages].RealSize = Endian_SwapLE32((surface.Info().width & 0xffff) | ((surface.Info().height & 0xffff) << 16)); + ++XPRFile.nImages; + + imageSize += Size; + CompressedSize += Size; +} + +void AppendXPRImageLink(int iLinkedImage) +{ + memcpy(&XPRFile.Texture[XPRFile.nImages].D3DTex, &XPRFile.Texture[iLinkedImage].D3DTex, sizeof(D3DTexture)); + ++XPRFile.nImages; +} + +void WriteXPR(const char* Filename, CSurface &surface, XB_D3DFORMAT fmt, DWORD* pal) +{ + WriteXPRHeader(pal, 1); + AppendXPRImage(surface, fmt); + CommitXPR(Filename); +} + +#undef CheckHR +#define CheckHR(hr) if (FAILED(hr)) { printf("ERROR: %08x\n", hr); if (pDstSurf) pDstSurf->Release(); return false; } + +// Converts to P8 format is colours <= 256 +bool ConvertP8(CSurface &source, CSurface &dest, DWORD* pal) +{ + // note: This routine assumes the source is 32 bpp + if (source.BPP() != 4) + { + printf("ERROR: ConvertP8 called on a source that's not 32bpp\n"); + return false; + } + + // convert to p8 + if (!dest.Create(source.Info().width, source.Info().height, CSurface::FMT_PALETTED)) + return false; + + CSurfaceRect sr, dr; + if (!dest.Lock(&dr) || !source.Lock(&sr)) + return false; + + DWORD* src = (DWORD*)sr.pBits; + BYTE* dst = (BYTE*)dr.pBits; + int n = 0, i; + for (UINT y = 0; y < source.Info().height; ++y) + { + for (UINT x = 0; x < source.Info().width; ++x) + { + for (i = 0; i < n; ++i) + { + if (pal[i] == *src) + break; + } + if (i == n) + { + if (n >= 256) + { + TRACE0(" Too many colours for P8\n"); + source.Unlock(); + dest.Unlock(); + return false; + } + pal[n++] = *src; + } + *dst++ = i; + ++src; + } + for (UINT x = source.Info().width; x < dest.Width(); ++x) + { + *dst++ = 0; // we don't care about the colour outside of our real image + ++src; + } + } + for (UINT y = source.Info().height; y < dest.Height(); ++y) + { + for (UINT x = 0; x < dest.Width(); ++x) + { + *dst++ = 0; // we don't care about the colour outside of our real image + ++src; + } + } + for (int i = n; i < 256; i++) + pal[i] = 0; + + TRACE1(" Colours Used: %d\n", n); + + dest.Unlock(); + source.Unlock(); + + return true; +} + +// Converts any fully transparent pixels to transparent black to make textures better compressable +void FixTransparency(CSurface &surface) +{ + CSurfaceRect rect; + + if (!surface.Lock(&rect)) + return; + + DWORD* pix = (DWORD*)rect.pBits; + for (UINT y = 0; y < surface.Width(); ++y) + { + for (UINT x = 0; x < surface.Height(); ++x) + { + if (!(*pix & 0xff000000)) + *pix = 0; + ++pix; + } + } + + surface.Unlock(); +} + + +#undef CheckHR +#define CheckHR(hr) if (FAILED(hr)) { printf("ERROR: %08x\n", hr); return; } + +void ConvertFile(const char* Dir, const char* Filename) +{ + CSurface surface; + char OutFilename[52]; + if (Dir) + _snprintf(OutFilename, 52, "%s\\%s", Dir, Filename); + else + _snprintf(OutFilename, 52, "%s", Filename); + OutFilename[51] = 0; + + printf("%s: ", OutFilename); + TRACE1("%s:\n", OutFilename); + int n = strlen(OutFilename); + if (n < 40) + printf("%*c", 40-n, ' '); + + CSurface srcSurface; + if (!srcSurface.CreateFromFile(Filename, CSurface::FMT_ARGB)) + { + printf("Error creating surface size %u by %u\n", srcSurface.Width(), srcSurface.Height()); + return; + } + + // fix up the transparency (allows better compression) + FixTransparency(srcSurface); + + // Use a paletted texture if possible as it's lossless + only 4 bytes per pixel (guaranteed smaller) +#ifdef _XBOX + CSurface tempSurface; + DWORD pal[256]; + if (ConvertP8(srcSurface, tempSurface, pal)) + { + float Waste = 100.f * (float)(srcSurface.Width() * srcSurface.Height() - srcSurface.Info().width * srcSurface.Info().height) / (float)(srcSurface.Width() * srcSurface.Height()); + printf("P8 %4dx%-4d (%5.2f%% waste)\n", srcSurface.Width(), srcSurface.Height(), Waste); + TRACE0(" Selected Format: P8\n"); + + WriteXPR(OutFilename, tempSurface, XB_D3DFMT_P8, pal); + return; + } +#endif + // we are going to use a 32bit texture, so work out what type to use + // test linear format versus non-linear format + // Linear format requires 64 pixel aligned width, whereas + // Non-linear format requires power of 2 width and height + bool useLinearFormat(false); +#ifdef _XBOX + UINT linearWidth = (srcSurface.Info().width + 0x3f) & ~0x3f; + if (linearWidth * srcSurface.Info().height < srcSurface.Width() * srcSurface.Height()) +#endif + useLinearFormat = true; + + // Use A8R8G8B8 + if (useLinearFormat) + { + // create the linear version as well + // correct sizing information + UncompressedSize += srcSurface.Width() * srcSurface.Height() * 4; + TotalSrcPixels += srcSurface.Info().width * srcSurface.Info().height; + TotalDstPixels += srcSurface.Width() * srcSurface.Height(); + float Waste = 100.f * (float)(srcSurface.Width() - srcSurface.Info().width) / (float)(srcSurface.Width()); + + CSurface linearSurface; + if (!linearSurface.CreateFromFile(Filename, CSurface::FMT_LIN_ARGB)) + return; + + printf("LIN_A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", srcSurface.Width(), srcSurface.Height(), Waste); + TRACE0(" Selected Format: LIN_A8R8G8B8\n"); + WriteXPR(OutFilename, linearSurface, XB_D3DFMT_LIN_A8R8G8B8, NULL); + } + else + { + UncompressedSize += srcSurface.Width() * srcSurface.Height() * 4; + TotalSrcPixels += srcSurface.Info().width * srcSurface.Info().height; + TotalDstPixels += srcSurface.Width() * srcSurface.Height(); + + float Waste = 100.f * (float)(srcSurface.Width() * srcSurface.Height() - srcSurface.Info().width * srcSurface.Info().height) / (float)(srcSurface.Width() * srcSurface.Height()); + printf("A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", srcSurface.Width(), srcSurface.Height(), Waste); + TRACE0(" Selected Format: A8R8G8B8\n"); + WriteXPR(OutFilename, srcSurface, XB_D3DFMT_A8R8G8B8, NULL); + } +} + +// only works for gifs or other 256-colour anims +void ConvertAnim(const char* Dir, const char* Filename) +{ + char OutFilename[52]; + if (Dir) + _snprintf(OutFilename, 52, "%s\\%s", Dir, Filename); + else + _snprintf(OutFilename, 52, "%s", Filename); + OutFilename[51] = 0; + + printf("%s: ", OutFilename); + TRACE1("%s:\n", OutFilename); + int n = strlen(OutFilename); + if (n < 40) + printf("%*c", 40-n, ' '); + + // Load up the file + CAnimatedGifSet Anim; + int nImages = Anim.LoadGIF(Filename); + if (!nImages) + { + puts("ERROR: Unable to load gif (file corrupt?)"); + return; + } + if (nImages > 65535) + { + printf("ERROR: Too many frames in gif (%d > 65535)\n", nImages); + return; + } + + PrintAnimInfo(Anim); + + UINT Width = PadPow2(Anim.FrameWidth); + UINT Height = PadPow2(Anim.FrameHeight); + + PALETTEENTRY pal[256]; + memcpy(pal, Anim.m_vecimg[0]->Palette, 256 * sizeof(PALETTEENTRY)); + for (int i = 0; i < 256; i++) + pal[i].peFlags = 0xff; // alpha + if (Anim.m_vecimg[0]->Transparency && Anim.m_vecimg[0]->Transparent >= 0) + memset(&pal[Anim.m_vecimg[0]->Transparent], 0, sizeof(PALETTEENTRY)); + + // setup xpr header + WriteXPRHeader((DWORD*)pal, nImages); + if (nImages > 1) + { + XPRFile.AnimInfo->RealSize = Endian_SwapLE32((Anim.FrameWidth & 0xffff) | ((Anim.FrameHeight & 0xffff) << 16)); + XPRFile.AnimInfo->nLoops = Endian_SwapLE32(Anim.nLoops); + } + + int nActualImages = 0; + + TotalSrcPixels += Anim.FrameWidth * Anim.FrameHeight * nImages; + TotalDstPixels += Width * Height * nImages; + float Waste = 100.f * (float)(Width * Height - Anim.FrameWidth * Anim.FrameHeight) / (float)(Width * Height); + + // alloc hash buffer + BYTE (*HashBuf)[20] = new BYTE[nImages][20]; + + for (int i = 0; i < nImages; ++i) + { + printf("%3d%%\b\b\b\b", 100 * i / nImages); + + UncompressedSize += Width * Height; + CAnimatedGif* pGif = Anim.m_vecimg[i]; + + if (nImages > 1) + XPRFile.Texture[i].RealSize = Endian_SwapLE32(pGif->Delay); + + // generate sha1 hash + SHA1((BYTE*)pGif->Raster, pGif->BytesPerRow * pGif->Height, HashBuf[i]); + + // duplicate scan + int j; + for (j = 0; j < i; ++j) + { + if (!memcmp(HashBuf[j], HashBuf[i], 20)) + { + // duplicate image! + TRACE2(" %03d: Duplicate of %03d\n", i, j); + AppendXPRImageLink(j); + break; + } + } + if (j < i) + continue; + + ++nActualImages; + + // P8 for animgifs + CSurface surface; + if (!surface.Create(Anim.FrameWidth, Anim.FrameHeight, CSurface::FMT_PALETTED)) + return; + + CSurfaceRect rect; + if (!surface.Lock(&rect)) + return; + + memcpy(rect.pBits, pGif->Raster, pGif->Height * rect.Pitch); + memset(rect.pBits + pGif->Height * rect.Pitch, pGif->Transparent, (Height - pGif->Height) * rect.Pitch); + + surface.Unlock(); + + TRACE1(" %03d: Selected Format: P8\n", i); + AppendXPRImage(surface, XB_D3DFMT_P8); + } + + delete [] HashBuf; + + printf("(%5df) %4dx%-4d (%5.2f%% waste)\n", nActualImages, Width, Height, Waste); + + CommitXPR(OutFilename); +} + +// returns true for png, bmp, tga, jpg and dds files, otherwise returns false +bool IsGraphicsFile(char *strFileName) +{ + int n = (int)strlen(strFileName); + if (n<4) + return false; + if (strnicmp(&strFileName[n-4], ".png", 4) && + strnicmp(&strFileName[n-4], ".bmp", 4) && + strnicmp(&strFileName[n-4], ".tga", 4) && + strnicmp(&strFileName[n-4], ".jpg", 4)) + return false; + return true; +} + +// returns true if it's a ".gif" otherwise returns false +bool IsGraphicsAnim(char *strFileName) +{ + int n = (int)strlen(strFileName); + if (n<4 || strnicmp(&strFileName[n-4], ".gif", 4)) + return false; + return true; +} + +void ConvertDirectory(const char *strFullPath, char *strRelativePath) +{ + // Set our current directory + if (strFullPath) + SetCurrentDirectory(strFullPath); + // Get our current pathname + char strCurrentPath[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, strCurrentPath); + + // Now run through our directory, and find all subdirs + WIN32_FIND_DATAA FindData; + char Filename[4] = "*.*"; + HANDLE hFind = FindFirstFile(Filename, &FindData); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + // Check if we've found a subdir + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + // ignore any directory starting with a '.' + if (strnicmp(FindData.cFileName,".",1)) + { + char strNewFullPath[MAX_PATH]; + char strNewRelativePath[MAX_PATH]; + sprintf(strNewFullPath, "%s%c%s", strCurrentPath, XBMC_FILE_SEP, FindData.cFileName); + if (strRelativePath) + sprintf(strNewRelativePath, "%s%c%s", strRelativePath, XBMC_FILE_SEP, FindData.cFileName); + else + sprintf(strNewRelativePath, "%s", FindData.cFileName); + // Recurse into the new directory + ConvertDirectory(strNewFullPath, strNewRelativePath); + // Restore our current directory + SetCurrentDirectory(strCurrentPath); + } + } + else + { // just files - check if it's an allowed graphics file + if (IsGraphicsFile(FindData.cFileName)) + { // got a graphics file + ConvertFile(strRelativePath,FindData.cFileName); + } + if (IsGraphicsAnim(FindData.cFileName)) + { // got a .gif anim + ConvertAnim(strRelativePath,FindData.cFileName); + } + } + } + while (FindNextFile(hFind, &FindData)); + FindClose(hFind); + } +} + +void Usage() +{ + puts("Usage:"); + puts(" -help Show this screen."); + puts(" -input <dir> Input directory. Default: current dir"); + puts(" -output <dir> Output directory/filename. Default: Textures.xpr"); + puts(" -quality <qual> Quality setting (min, low, normal, high, max). Default: normal"); + puts(" -noprotect XPR contents viewable at full quality in skin editor"); +} + +int main(int argc, char* argv[]) +{ + int NoProtect = 0; + bool valid = false; + + CmdLineArgs args(argc, (const char**)argv); + + if (args.size() == 1) + { + Usage(); + return 1; + } + + const char* InputDir = NULL; + const char* OutputFilename = "Textures.xpr"; + + for (unsigned int i = 1; i < args.size(); ++i) + { + if (!stricmp(args[i], "-help") || !stricmp(args[i], "-h") || !stricmp(args[i], "-?")) + { + Usage(); + return 1; + } + else if (!stricmp(args[i], "-input") || !stricmp(args[i], "-i")) + { + InputDir = args[++i]; + valid = true; + } + else if (!stricmp(args[i], "-output") || !stricmp(args[i], "-o")) + { + OutputFilename = args[++i]; + valid = true; +#ifdef _LINUX + char *c = NULL; + while ((c = (char *)strchr(OutputFilename, '\\')) != NULL) *c = '/'; +#endif + } + else if (!stricmp(args[i], "-noprotect") || !stricmp(args[i], "-p")) + { + NoProtect = 1; + valid = true; + } + else + { + printf("Unrecognised command line flag: %s\n", args[i]); + } + } + + if (!valid) + { + Usage(); + return 1; + } + + // Initialize the graphics device + if (!g_device.Create()) + return 1; + + char HomeDir[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, HomeDir); + + Bundler.StartBundle(); + + // Scan the input directory (or current dir if false) for media files + ConvertDirectory(InputDir, NULL); + + free(headerBuf); + + SetCurrentDirectory(HomeDir); + DWORD attr = GetFileAttributes(OutputFilename); + if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_DIRECTORY)) + { + SetCurrentDirectory(OutputFilename); + OutputFilename = "Textures.xpr"; + } + + printf("\nWriting bundle: %s", OutputFilename); + int BundleSize = Bundler.WriteBundle(OutputFilename, NoProtect); + if (BundleSize == -1) + { + printf("\nERROR: %08x\n", GetLastError()); + return 1; + } + + printf("\nUncompressed texture size: %6dkB\nCompressed texture size: %8dkB\nBundle size: %8dkB\n\nWasted Pixels: %u/%u (%5.2f%%)\n", + (UncompressedSize + 1023) / 1024, (((CompressedSize + 1023) / 1024) + 3) & ~3, (BundleSize + 1023) / 1024, + TotalDstPixels - TotalSrcPixels, TotalDstPixels, 100.f * (float)(TotalDstPixels - TotalSrcPixels) / (float)TotalDstPixels); + + return 0; +} + diff --git a/tools/XBMCTex/XBMCTex.exe b/tools/XBMCTex/XBMCTex.exe Binary files differnew file mode 100644 index 0000000000..dfb8c9ae99 --- /dev/null +++ b/tools/XBMCTex/XBMCTex.exe diff --git a/tools/XBMCTex/XBMCTex.sln b/tools/XBMCTex/XBMCTex.sln new file mode 100644 index 0000000000..8589f8722d --- /dev/null +++ b/tools/XBMCTex/XBMCTex.sln @@ -0,0 +1,27 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XBMCTex", "XBMCTex.vcproj", "{AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Debug SDL = Debug SDL + Release = Release + Release SDL = Release SDL + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}.Debug.ActiveCfg = Debug|Win32 + {AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}.Debug.Build.0 = Debug|Win32 + {AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}.Debug SDL.ActiveCfg = Debug SDL|Win32 + {AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}.Debug SDL.Build.0 = Debug SDL|Win32 + {AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}.Release.ActiveCfg = Release|Win32 + {AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}.Release.Build.0 = Release|Win32 + {AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}.Release SDL.ActiveCfg = Release SDL|Win32 + {AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}.Release SDL.Build.0 = Release SDL|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/tools/XBMCTex/XBMCTex.vcproj b/tools/XBMCTex/XBMCTex.vcproj new file mode 100644 index 0000000000..3d384a3ee7 --- /dev/null +++ b/tools/XBMCTex/XBMCTex.vcproj @@ -0,0 +1,291 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="XBMCTex" + ProjectGUID="{AF7F7513-4425-4A27-B5B9-4CF68F01B5C6}" + Keyword="Win32Proj"> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + MinimalRebuild="TRUE" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="FALSE" + DebugInformationFormat="4"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="D3D8.lib D3DX8.lib" + OutputFile="$(OutDir)/XBMCTex.exe" + LinkIncremental="2" + IgnoreDefaultLibraryNames="libci.lib,libm.lib,libirc.lib,libc" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(OutDir)/XBMCTex.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + OptimizeForProcessor="2" + OptimizeForWindowsApplication="TRUE" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + RuntimeLibrary="2" + EnableEnhancedInstructionSet="0" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="FALSE" + DebugInformationFormat="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="D3D8.lib D3DX8.lib" + OutputFile="$(OutDir)/XBMCTex.exe" + LinkIncremental="1" + IgnoreDefaultLibraryNames="libci.lib,libm.lib,libirc.lib,libc.lib" + GenerateDebugInformation="FALSE" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Debug SDL|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;HAS_SDL" + MinimalRebuild="TRUE" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="FALSE" + DebugInformationFormat="4"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="SDL.lib SDLmain.lib SDL_image.lib" + OutputFile="$(OutDir)/XBMCTex.exe" + LinkIncremental="2" + IgnoreDefaultLibraryNames="libci.lib,libm.lib,libirc.lib,libc" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(OutDir)/XBMCTex.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release SDL|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + OptimizeForProcessor="2" + OptimizeForWindowsApplication="TRUE" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;HAS_SDL" + RuntimeLibrary="2" + EnableEnhancedInstructionSet="0" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="FALSE" + DebugInformationFormat="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="SDL.lib SDLmain.lib SDL_image.lib" + OutputFile="$(OutDir)/XBMCTex.exe" + LinkIncremental="1" + IgnoreDefaultLibraryNames="libci.lib,libm.lib,libirc.lib,libc.lib" + GenerateDebugInformation="FALSE" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + <File + RelativePath=".\AnimatedGif.cpp"> + </File> + <File + RelativePath=".\Bundler.cpp"> + </File> + <File + RelativePath="..\..\xbmc\lib\liblzo\lzo.lib"> + </File> + <File + RelativePath=".\sha.c"> + </File> + <File + RelativePath=".\Surface.cpp"> + </File> + <File + RelativePath=".\SurfaceSDL.cpp"> + </File> + <File + RelativePath=".\XBMCTex.cpp"> + </File> + <File + RelativePath=".\xbox.cpp"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + <File + RelativePath=".\AnimatedGif.h"> + </File> + <File + RelativePath=".\Bundler.h"> + </File> + <File + RelativePath=".\cmdlineargs.h"> + </File> + <File + RelativePath="..\..\xbmc\lib\liblzo\Lzo1x.h"> + </File> + <File + RelativePath="..\..\xbmc\lib\liblzo\Lzoconf.h"> + </File> + <File + RelativePath=".\stdint_win.h"> + </File> + <File + RelativePath=".\Surface.h"> + </File> + <File + RelativePath=".\SurfaceSDL.h"> + </File> + <File + RelativePath=".\xbox.h"> + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> + </Filter> + <File + RelativePath=".\ReadMe.txt"> + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/tools/XBMCTex/XFileUtils.cpp b/tools/XBMCTex/XFileUtils.cpp new file mode 100644 index 0000000000..f27af32211 --- /dev/null +++ b/tools/XBMCTex/XFileUtils.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" +#include "PlatformInclude.h" +#include "XFileUtils.h" +#include "XTimeUtils.h" +#include "Util.h" +#include "XHandle.h" + +#ifdef _LINUX + +#include <sys/types.h> +#include <sys/stat.h> +#ifndef __APPLE__ +#include <sys/vfs.h> +#else +#include <sys/param.h> +#endif +#include <regex.h> +#include <dirent.h> +#include <errno.h> + + +HANDLE FindFirstFile(LPCSTR szPath,LPWIN32_FIND_DATA lpFindData) { + if (lpFindData == NULL || szPath == NULL) + return NULL; + + CStdString strPath(szPath); + + if (strPath.empty()) + return INVALID_HANDLE_VALUE; + + strPath.Replace("\\","/"); + + // if the file name is a directory then we add a * to look for all files in this directory + DIR *testDir = opendir(szPath); + if (testDir) { + strPath += "/*"; + closedir(testDir); + } + + int nFilePos = strPath.ReverseFind(XBMC_FILE_SEP); + + CStdString strDir = "."; + CStdString strFiles = strPath; + + if (nFilePos > 0) { + strDir = strPath.substr(0,nFilePos); + strFiles = strPath.substr(nFilePos + 1); + } + + if (strFiles == "*.*") + strFiles = "*"; + + strFiles = CStdString("^") + strFiles + "$"; + strFiles.Replace(".","\\."); + strFiles.Replace("*",".*"); + strFiles.Replace("?","."); + + strFiles.MakeLower(); + + int status; + regex_t re; + if (regcomp(&re, strFiles, REG_EXTENDED|REG_NOSUB) != 0) { + return(INVALID_HANDLE_VALUE); + } + + struct dirent **namelist = NULL; + int n = scandir(strDir, &namelist, 0, alphasort); + + CXHandle *pHandle = new CXHandle(CXHandle::HND_FIND_FILE); + pHandle->m_FindFileDir = strDir; + + while (n-- > 0) { + CStdString strComp(namelist[n]->d_name); + strComp.MakeLower(); + + status = regexec(&re, strComp.c_str(), (size_t) 0, NULL, 0); + if (status == 0) { + pHandle->m_FindFileResults.push_back(namelist[n]->d_name); + } + free(namelist[n]); + } + + if (namelist) + free(namelist); + + regfree(&re); + + if (pHandle->m_FindFileResults.size() == 0) { + delete pHandle; + return INVALID_HANDLE_VALUE; + } + + FindNextFile(pHandle, lpFindData); + + return pHandle; +} + +BOOL FindNextFile(HANDLE hHandle, LPWIN32_FIND_DATA lpFindData) { + if (lpFindData == NULL || hHandle == NULL || hHandle->GetType() != CXHandle::HND_FIND_FILE) + return FALSE; + + if ((unsigned int) hHandle->m_nFindFileIterator >= hHandle->m_FindFileResults.size()) + return FALSE; + + CStdString strFileName = hHandle->m_FindFileResults[hHandle->m_nFindFileIterator++]; + CStdString strFileNameTest = hHandle->m_FindFileDir + '/' + strFileName; + + struct stat64 fileStat; + if (stat64(strFileNameTest, &fileStat) != 0) + return FALSE; + + bool bIsDir = false; + DIR *testDir = opendir(strFileNameTest); + if (testDir) { + bIsDir = true; + closedir(testDir); + } + + memset(lpFindData,0,sizeof(WIN32_FIND_DATA)); + + lpFindData->dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + strcpy(lpFindData->cFileName, strFileName.c_str()); + + if (bIsDir) + lpFindData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + + if (strFileName[0] == '.') + lpFindData->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN; + + if (access(strFileName, R_OK) == 0 && access(strFileName, W_OK) != 0) + lpFindData->dwFileAttributes |= FILE_ATTRIBUTE_READONLY; + + TimeTToFileTime(fileStat.st_ctime, &lpFindData->ftCreationTime); + TimeTToFileTime(fileStat.st_atime, &lpFindData->ftLastAccessTime); + TimeTToFileTime(fileStat.st_mtime, &lpFindData->ftLastWriteTime); + + lpFindData->nFileSizeHigh = (DWORD)(fileStat.st_size >> 32); + lpFindData->nFileSizeLow = (DWORD)fileStat.st_size; + + return TRUE; +} + +BOOL FindClose(HANDLE hFindFile) { + return CloseHandle(hFindFile); +} + +int _stat64( const char *path, struct __stat64 *buffer ) { + if (buffer == NULL || path == NULL) + return -1; + + return stat64(path, buffer); +} + +DWORD GetFileAttributes(LPCTSTR lpFileName) +{ + if (lpFileName == NULL) { + return 0; + } + + DWORD dwAttr = FILE_ATTRIBUTE_NORMAL; + DIR *tmpDir = opendir(lpFileName); + if (tmpDir) { + dwAttr |= FILE_ATTRIBUTE_DIRECTORY; + closedir(tmpDir); + } + + if (lpFileName[0] == '.') + dwAttr |= FILE_ATTRIBUTE_HIDDEN; + + if (access(lpFileName, R_OK) == 0 && access(lpFileName, W_OK) != 0) + dwAttr |= FILE_ATTRIBUTE_READONLY; + + return dwAttr; +} + +#endif + diff --git a/tools/XBMCTex/XFileUtils.h b/tools/XBMCTex/XFileUtils.h new file mode 100644 index 0000000000..5bf2a767d6 --- /dev/null +++ b/tools/XBMCTex/XFileUtils.h @@ -0,0 +1,46 @@ +#ifndef __X_FILE_UTILS_ +#define __X_FILE_UTILS_ + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PlatformDefs.h" +#include "XHandlePublic.h" + +#ifdef _LINUX +#define XBMC_FILE_SEP '/' +#else +#define XBMC_FILE_SEP '\\' +#endif + +HANDLE FindFirstFile(LPCSTR,LPWIN32_FIND_DATA); + +BOOL FindNextFile(HANDLE,LPWIN32_FIND_DATA); +BOOL FindClose(HANDLE hFindFile); + +int _stat64(const char *path, struct __stat64 *buffer); +int _stati64(const char *path,struct _stati64 *buffer); + +DWORD GetFileAttributes(LPCTSTR lpFileName); + +#define ERROR_ALREADY_EXISTS EEXIST + +#endif diff --git a/tools/XBMCTex/XHandle.cpp b/tools/XBMCTex/XHandle.cpp new file mode 100644 index 0000000000..abe769985b --- /dev/null +++ b/tools/XBMCTex/XHandle.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include <SDL/SDL.h> + +#include "XHandle.h" + +int CXHandle::m_objectTracker[10] = {0}; + +CXHandle::CXHandle() +{ + Init(); + m_objectTracker[m_type]++; +} + +CXHandle::CXHandle(HandleType nType) +{ + Init(); + m_type=nType; + m_objectTracker[m_type]++; +} + +CXHandle::~CXHandle() +{ + + m_objectTracker[m_type]--; + + if (RecursionCount > 0) { + assert(false); + } + + if (m_nRefCount > 1) { + assert(false); + } + + if (m_hSem) { + SDL_DestroySemaphore(m_hSem); + } + + if (m_hMutex) { + SDL_DestroyMutex(m_hMutex); + } + + if (m_internalLock) { + SDL_DestroyMutex(m_internalLock); + } + + if (m_hCond) { + SDL_DestroyCond(m_hCond); + } + + if (m_threadValid) { + pthread_join(m_hThread,NULL); + } + + if ( fd != 0 ) { + close(fd); + } + +} + +void CXHandle::Init() +{ + fd=0; + m_hSem=NULL; + m_hMutex=NULL; + m_threadValid=false; + m_hCond=NULL; + m_type = HND_NULL; + RecursionCount=0; + OwningThread=0; + m_bManualEvent=FALSE; + m_bEventSet=FALSE; + m_nFindFileIterator=0 ; + m_nRefCount=1; + m_tmCreation = time(NULL); + m_internalLock = SDL_CreateMutex(); +#ifdef __APPLE__ + m_machThreadPort = 0; +#endif +} + +void CXHandle::ChangeType(HandleType newType) { + m_objectTracker[m_type]--; + m_type = newType; + m_objectTracker[m_type]++; +} + +bool CloseHandle(HANDLE hObject) { + if (!hObject) + return false; + + if (hObject == INVALID_HANDLE_VALUE || hObject == (HANDLE)-1) + return true; + + bool bDelete = false; + SDL_LockMutex(hObject->m_internalLock); + if (--hObject->m_nRefCount == 0) + bDelete = true; + SDL_UnlockMutex(hObject->m_internalLock); + + if (bDelete) + delete hObject; + + return true; +} + diff --git a/tools/XBMCTex/XHandle.h b/tools/XBMCTex/XHandle.h new file mode 100644 index 0000000000..96a1ed1a83 --- /dev/null +++ b/tools/XBMCTex/XHandle.h @@ -0,0 +1,88 @@ +#ifndef __X_HANDLE__ +#define __X_HANDLE__ + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#ifndef _WIN32 + +#include "../../guilib/StdString.h" +#include <SDL/SDL_mutex.h> +#include <pthread.h> + +#include "PlatformDefs.h" +#include "StringUtils.h" + +struct CXHandle { + +public: + typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_THREAD, HND_FIND_FILE } HandleType; + + CXHandle(); + CXHandle(HandleType nType); + + virtual ~CXHandle(); + void Init(); + inline HandleType GetType() { return m_type; } + void ChangeType(HandleType newType); + + SDL_sem *m_hSem; + pthread_t m_hThread; + bool m_threadValid; + SDL_cond *m_hCond; + +#ifdef __APPLE__ + // Save the Mach thrad port, I don't think it can be obtained from + // the pthread_t. We'll use it for querying timer information. + // + mach_port_t m_machThreadPort; +#endif + + // simulate mutex and critical section + SDL_mutex *m_hMutex; + int RecursionCount; // for mutex - for compatibility with WIN32 critical section + pthread_t OwningThread; + int fd; + bool m_bManualEvent; + time_t m_tmCreation; + CStdStringArray m_FindFileResults; + int m_nFindFileIterator; + CStdString m_FindFileDir; + off64_t m_iOffset; + bool m_bCDROM; + bool m_bEventSet; + int m_nRefCount; + SDL_mutex *m_internalLock; + +protected: + HandleType m_type; + static int m_objectTracker[10]; + +}; + +#define HANDLE CXHandle* + +bool CloseHandle(HANDLE hObject); + +#endif + +#endif + diff --git a/tools/XBMCTex/XTimeUtils.cpp b/tools/XBMCTex/XTimeUtils.cpp new file mode 100644 index 0000000000..6a1c71fa54 --- /dev/null +++ b/tools/XBMCTex/XTimeUtils.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" +#include "XTimeUtils.h" +#include <errno.h> +#include <time.h> +#include <unistd.h> +#include <sys/times.h> + +#ifdef __APPLE__ +#include <mach/mach.h> +#include <mach/clock.h> +#include <mach/mach_error.h> +#endif + +#define WIN32_TIME_OFFSET ((unsigned long long)(369 * 365 + 89) * 24 * 3600 * 10000000) + + +#ifdef _LINUX + +BOOL TimeTToFileTime(time_t timeT, FILETIME* lpLocalFileTime) { + + if (lpLocalFileTime == NULL) + return false; + + ULARGE_INTEGER result; + result.QuadPart = (unsigned long long) timeT * 10000000; + result.QuadPart += WIN32_TIME_OFFSET; + + lpLocalFileTime->dwLowDateTime = result.u.LowPart; + lpLocalFileTime->dwHighDateTime = result.u.HighPart; + + return true; +} + +#endif + diff --git a/tools/XBMCTex/XTimeUtils.h b/tools/XBMCTex/XTimeUtils.h new file mode 100644 index 0000000000..10b944744e --- /dev/null +++ b/tools/XBMCTex/XTimeUtils.h @@ -0,0 +1,30 @@ +#ifndef __X_TIME_UTILS_ +#define __X_TIME_UTILS_ + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PlatformDefs.h" + +BOOL TimeTToFileTime(time_t timeT, FILETIME* lpLocalFileTime); + +#endif + diff --git a/tools/XBMCTex/cmdlineargs.h b/tools/XBMCTex/cmdlineargs.h new file mode 100644 index 0000000000..a9f5891722 --- /dev/null +++ b/tools/XBMCTex/cmdlineargs.h @@ -0,0 +1,123 @@ +#ifndef CMDLINEARGS_H +#define CMDLINEARGS_H + +#ifdef _LINUX +#include "PlatformDefs.h" +#include "xwinapi.h" +typedef LPSTR PSZ; +#define _snprintf snprintf +#else +#include <windows.h> +#endif +#include <vector> +#include <string> + +class CmdLineArgs : public std::vector<char*> +{ +public: + CmdLineArgs () + { + // Save local copy of the command line string, because + // ParseCmdLine() modifies this string while parsing it. + PSZ cmdline = GetCommandLine(); + m_cmdline = new char [strlen (cmdline) + 1]; + if (m_cmdline) + { + strcpy (m_cmdline, cmdline); + ParseCmdLine(); + } else { +#ifdef _LINUX + delete[] cmdline; +#endif + } + } + + CmdLineArgs (const int argc, const char **argv) + { + std::string cmdline; + for (int i = 0 ; i<argc ; i++) + { + cmdline += std::string(argv[i]); + if ( i != (argc-1) ) + { + cmdline += " "; + } + } + m_cmdline = new char [cmdline.length() + 1]; + if (m_cmdline) + { + strcpy(m_cmdline, cmdline.c_str()); + ParseCmdLine(); + } + } + + ~CmdLineArgs() + { + delete[] m_cmdline; + } + +private: + PSZ m_cmdline; // the command line string + + //////////////////////////////////////////////////////////////////////////////// + // Parse m_cmdline into individual tokens, which are delimited by spaces. If a + // token begins with a quote, then that token is terminated by the next quote + // followed immediately by a space or terminator. This allows tokens to contain + // spaces. + // This input string: This "is" a ""test"" "of the parsing" alg"o"rithm. + // Produces these tokens: This, is, a, "test", of the parsing, alg"o"rithm + //////////////////////////////////////////////////////////////////////////////// + void ParseCmdLine () + { + enum { TERM = '\0', + QUOTE = '\"' }; + + bool bInQuotes = false; + PSZ pargs = m_cmdline; + + while (*pargs) + { + while (isspace (*pargs)) // skip leading whitespace + pargs++; + + bInQuotes = (*pargs == QUOTE); // see if this token is quoted + + if (bInQuotes) // skip leading quote + pargs++; + + push_back (pargs); // store position of current token + + // Find next token. + // NOTE: Args are normally terminated by whitespace, unless the + // arg is quoted. That's why we handle the two cases separately, + // even though they are very similar. + if (bInQuotes) + { + // find next quote followed by a space or terminator + while (*pargs && + !(*pargs == QUOTE && (isspace (pargs[1]) || pargs[1] == TERM))) + pargs++; + if (*pargs) + { + *pargs = TERM; // terminate token + if (pargs[1]) // if quoted token not followed by a terminator + pargs += 2; // advance to next token + } + } + else + { + // skip to next non-whitespace character + while (*pargs && !isspace (*pargs)) + pargs++; + if (*pargs && isspace (*pargs)) // end of token + { + *pargs = TERM; // terminate token + pargs++; // advance to next token or terminator + } + } + } // while (*pargs) + } // ParseCmdLine() +}; // class CmdLineArgs + + +#endif // CMDLINEARGS_H diff --git a/tools/XBMCTex/sha.c b/tools/XBMCTex/sha.c new file mode 100644 index 0000000000..809c4235cd --- /dev/null +++ b/tools/XBMCTex/sha.c @@ -0,0 +1,111 @@ +#include <string.h> +#ifdef _LINUX +#include <stdint.h> +#else +#include "stdint_win.h" +#endif + +typedef unsigned long u32; +typedef unsigned char u8; + +#ifdef _LINUX +#include <string.h> +#define __forceinline inline +#define __int64 int64_t +#endif + +__forceinline static u32 rol(u32 x, u8 n) +{ + return (x << n) | (x >> (32-n)); +} + +static void bswapcpy(void* dst, const void* src, u32 n) +{ + uint32_t d, b0, b1, b2, b3; + uint32_t *nDst = (uint32_t *)dst; + uint32_t *nSrc = (uint32_t *)src; + n >>= 2; + while (n != 0) + { + d = *nSrc; + b0 = d >> 24; + b1 = (d >> 8) & 0x0000ff00; + b2 = (d << 8) & 0x00ff0000; + b3 = (d << 24); + *nDst = b3 | b2 | b1 | b0; + --n; + ++nSrc; + ++nDst; + } +} + +void SHA1(const u8* buf, u32 len, u8 hash[20]) +{ + u32 a, b, c, d, e; + u32 h[5] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; + u32 w[80]; + u32 n = len; + int t; + int done = 0; + + while (done != 2) + { + if (n >= 64) + { + bswapcpy(w, buf, 64); + buf += 64; + n -= 64; + } + else + { + u8 tmpbuf[64]; + memcpy(tmpbuf, buf, n); + memset(tmpbuf+n, 0, 64-n); + if (!done) + tmpbuf[n] = 0x80; + bswapcpy(w, tmpbuf, 64); + if (n <= 55) + { + u32 bitlen = len * 8; + w[14] = *(((u32*)&bitlen)+1); + w[15] = *((u32*)&bitlen); + done = 2; + } + else + done = 1; + n = 0; + } + + for (t = 16; t < 80; ++t) + { + w[t] = rol(w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16], 1); + } + + a = h[0]; b = h[1]; c = h[2]; d = h[3]; e = h[4]; + + for (t = 0; t < 20; ++t) + { + u32 temp = rol(a, 5) + ((b & c) | ((~b) & d)) + e + w[t] + 0x5A827999; + e = d; d = c; c = rol(b, 30); b = a; a = temp; + } + for ( ; t < 40; ++t) + { + u32 temp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ED9EBA1; + e = d; d = c; c = rol(b, 30); b = a; a = temp; + } + for ( ; t < 60; ++t) + { + u32 temp = rol(a, 5) + ((b & c) | (b & d) | (c & d)) + e + w[t] + 0x8F1BBCDC; + e = d; d = c; c = rol(b, 30); b = a; a = temp; + } + for ( ; t < 80; ++t) + { + u32 temp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xCA62C1D6; + e = d; d = c; c = rol(b, 30); b = a; a = temp; + } + + h[0] += a; h[1] += b; h[2] += c; h[3] += d; h[4] += e; + } + + bswapcpy(hash, h, 20); +} diff --git a/tools/XBMCTex/stdint_win.h b/tools/XBMCTex/stdint_win.h new file mode 100644 index 0000000000..7e200dc6fc --- /dev/null +++ b/tools/XBMCTex/stdint_win.h @@ -0,0 +1,222 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include <limits.h> + +// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if (_MSC_VER < 1300) && defined(__cplusplus) + extern "C++" { +#endif +# include <wchar.h> +#if (_MSC_VER < 1300) && defined(__cplusplus) + } +#endif + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef int intptr_t; + typedef unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/tools/XBMCTex/xbox.cpp b/tools/XBMCTex/xbox.cpp new file mode 100644 index 0000000000..852c9e9693 --- /dev/null +++ b/tools/XBMCTex/xbox.cpp @@ -0,0 +1,145 @@ +#include "xbox.h" +#include "Surface.h" +#include "EndianSwap.h" + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +bool IsPowerOf2(UINT number) +{ + return (number & (~number+1)) == number; +} + +int GetLog2(UINT Number) +{ + int power = 0; + while (Number) + { + Number >>= 1; + power++; + } + return power-1; +} + +BOOL IsPaletted(XB_D3DFORMAT format) +{ + switch (format) + { + case XB_D3DFMT_P8: + return true; + default: + return false; + } +} + +void SetTextureHeader(UINT Width, UINT Height, UINT Levels, UINT Usage, XB_D3DFORMAT Format, D3DTexture *pTexture, UINT Data, UINT Pitch) +{ + // TODO: No idea what most of this is. + // Byte swapping to convert the header on big-endian system + memset(pTexture, 0, sizeof(D3DTexture)); + pTexture->Common = Endian_SwapLE32(D3DCOMMON_TYPE_TEXTURE + 1); // what does the 1 give?? + pTexture->Format |= (Format & 0xFF) << 8; + pTexture->Format |= 0x10029; // no idea why + pTexture->Data = Endian_SwapLE32(Data); // offset of texture data + if (IsPowerOf2(Width) && IsPowerOf2(Height)) + { + pTexture->Format |= (GetLog2(Width) & 0xF) << 20; + pTexture->Format |= (GetLog2(Height) & 0xF) << 24; + } + else + { + pTexture->Size |= (Width - 1) & 0xfff; + pTexture->Size |= ((Height - 1) & 0xfff) << 12; + pTexture->Size |= (((Pitch >> 6) & 0xff) - 1) << 24; + } + pTexture->Format = Endian_SwapLE32(pTexture->Format); + pTexture->Size = Endian_SwapLE32(pTexture->Size); +} + +BOOL IsSwizzledFormat(XB_D3DFORMAT format) +{ + switch (format) + { + case XB_D3DFMT_A8R8G8B8: + case XB_D3DFMT_P8: + return true; + default: + return false; + } +} + +DWORD BytesPerPixelFromFormat(XB_D3DFORMAT format) +{ + switch (format) + { + case XB_D3DFMT_A8R8G8B8: + case XB_D3DFMT_LIN_A8R8G8B8: + case XB_D3DFMT_DXT1: + case XB_D3DFMT_DXT4: + return 4; + case XB_D3DFMT_P8: + return 1; + default: + break; + } + return 0; +} + +// Swizzle. +// Format is: + +// 00 01 04 05 +// 02 03 06 07 +// 08 09 12 13 +// 10 11 14 15 ... + +// Currently only works for 32bit and 8bit textures, with power of 2 width and height +void Swizzle(const void *src, unsigned int depth, unsigned int width, unsigned int height, void *dest) +{ + for (UINT y = 0; y < height; y++) + { + UINT sy = 0; + if (y < width) + { + for (int bit = 0; bit < 16; bit++) + sy |= ((y >> bit) & 1) << (2*bit); + sy <<= 1; // y counts twice + } + else + { + UINT y_mask = y % width; + for (int bit = 0; bit < 16; bit++) + sy |= ((y_mask >> bit) & 1) << (2*bit); + sy <<= 1; // y counts twice + sy += (y / width) * width * width; + } + BYTE *s = (BYTE *)src + y * width * depth; + for (UINT x = 0; x < width; x++) + { + UINT sx = 0; + if (x < height * 2) + { + for (int bit = 0; bit < 16; bit++) + sx |= ((x >> bit) & 1) << (2*bit); + } + else + { + int x_mask = x % (2*height); + for (int bit = 0; bit < 16; bit++) + sx |= ((x_mask >> bit) & 1) << (2*bit); + sx += (x / (2 * height)) * 2 * height * height; + } + BYTE *d = (BYTE *)dest + (sx + sy)*depth; + for (unsigned int i = 0; i < depth; ++i) + *d++ = *s++; + } + } +} + + +VOID SwizzleRect(LPCVOID pSource, DWORD Pitch, LPVOID pDest, DWORD Width, DWORD Height, DWORD BytesPerPixel) +{ + // knows nothing about Pitch + Swizzle(pSource, BytesPerPixel, Width, Height, pDest); +} diff --git a/tools/XBMCTex/xbox.h b/tools/XBMCTex/xbox.h new file mode 100644 index 0000000000..ba72e88694 --- /dev/null +++ b/tools/XBMCTex/xbox.h @@ -0,0 +1,161 @@ +// Some XBox specific stuff + +#pragma once + +#ifdef _LINUX +#include "PlatformDefs.h" +typedef struct tagPALETTEENTRY { + BYTE peRed; + BYTE peGreen; + BYTE peBlue; + BYTE peFlags; +} PALETTEENTRY; +#else +typedef unsigned long DWORD; +typedef unsigned int UINT; +typedef int BOOL; +typedef const void* LPCVOID; +typedef void* LPVOID; +typedef unsigned char BYTE; +#endif + +struct D3DTexture +{ + DWORD Common; + DWORD Data; + DWORD Lock; + + DWORD Format; // Format information about the texture. + DWORD Size; // Size of a non power-of-2 texture, must be zero otherwise +}; + +struct D3DPalette +{ + DWORD Common; + DWORD Data; + DWORD Lock; + +}; + +typedef enum _XB_D3DFORMAT +{ + XB_D3DFMT_UNKNOWN = 0xFFFFFFFF, + + /* Swizzled formats */ + + XB_D3DFMT_A8R8G8B8 = 0x00000006, + XB_D3DFMT_X8R8G8B8 = 0x00000007, + XB_D3DFMT_R5G6B5 = 0x00000005, + XB_D3DFMT_R6G5B5 = 0x00000027, + XB_D3DFMT_X1R5G5B5 = 0x00000003, + XB_D3DFMT_A1R5G5B5 = 0x00000002, + XB_D3DFMT_A4R4G4B4 = 0x00000004, + XB_D3DFMT_A8 = 0x00000019, + XB_D3DFMT_A8B8G8R8 = 0x0000003A, + XB_D3DFMT_B8G8R8A8 = 0x0000003B, + XB_D3DFMT_R4G4B4A4 = 0x00000039, + XB_D3DFMT_R5G5B5A1 = 0x00000038, + XB_D3DFMT_R8G8B8A8 = 0x0000003C, + XB_D3DFMT_R8B8 = 0x00000029, + XB_D3DFMT_G8B8 = 0x00000028, + + XB_D3DFMT_P8 = 0x0000000B, + + XB_D3DFMT_L8 = 0x00000000, + XB_D3DFMT_A8L8 = 0x0000001A, + XB_D3DFMT_AL8 = 0x00000001, + XB_D3DFMT_L16 = 0x00000032, + + XB_D3DFMT_V8U8 = 0x00000028, + XB_D3DFMT_L6V5U5 = 0x00000027, + XB_D3DFMT_X8L8V8U8 = 0x00000007, + XB_D3DFMT_Q8W8V8U8 = 0x0000003A, + XB_D3DFMT_V16U16 = 0x00000033, + + XB_D3DFMT_D16_LOCKABLE = 0x0000002C, + XB_D3DFMT_D16 = 0x0000002C, + XB_D3DFMT_D24S8 = 0x0000002A, + XB_D3DFMT_F16 = 0x0000002D, + XB_D3DFMT_F24S8 = 0x0000002B, + + /* YUV formats */ + + XB_D3DFMT_YUY2 = 0x00000024, + XB_D3DFMT_UYVY = 0x00000025, + + /* Compressed formats */ + + XB_D3DFMT_DXT1 = 0x0000000C, + XB_D3DFMT_DXT2 = 0x0000000E, + XB_D3DFMT_DXT3 = 0x0000000E, + XB_D3DFMT_DXT4 = 0x0000000F, + XB_D3DFMT_DXT5 = 0x0000000F, + + /* Linear formats */ + + XB_D3DFMT_LIN_A1R5G5B5 = 0x00000010, + XB_D3DFMT_LIN_A4R4G4B4 = 0x0000001D, + XB_D3DFMT_LIN_A8 = 0x0000001F, + XB_D3DFMT_LIN_A8B8G8R8 = 0x0000003F, + XB_D3DFMT_LIN_A8R8G8B8 = 0x00000012, + XB_D3DFMT_LIN_B8G8R8A8 = 0x00000040, + XB_D3DFMT_LIN_G8B8 = 0x00000017, + XB_D3DFMT_LIN_R4G4B4A4 = 0x0000003E, + XB_D3DFMT_LIN_R5G5B5A1 = 0x0000003D, + XB_D3DFMT_LIN_R5G6B5 = 0x00000011, + XB_D3DFMT_LIN_R6G5B5 = 0x00000037, + XB_D3DFMT_LIN_R8B8 = 0x00000016, + XB_D3DFMT_LIN_R8G8B8A8 = 0x00000041, + XB_D3DFMT_LIN_X1R5G5B5 = 0x0000001C, + XB_D3DFMT_LIN_X8R8G8B8 = 0x0000001E, + + XB_D3DFMT_LIN_A8L8 = 0x00000020, + XB_D3DFMT_LIN_AL8 = 0x0000001B, + XB_D3DFMT_LIN_L16 = 0x00000035, + XB_D3DFMT_LIN_L8 = 0x00000013, + + XB_D3DFMT_LIN_V16U16 = 0x00000036, + XB_D3DFMT_LIN_V8U8 = 0x00000017, + XB_D3DFMT_LIN_L6V5U5 = 0x00000037, + XB_D3DFMT_LIN_X8L8V8U8 = 0x0000001E, + XB_D3DFMT_LIN_Q8W8V8U8 = 0x00000012, + + XB_D3DFMT_LIN_D24S8 = 0x0000002E, + XB_D3DFMT_LIN_F24S8 = 0x0000002F, + XB_D3DFMT_LIN_D16 = 0x00000030, + XB_D3DFMT_LIN_F16 = 0x00000031, + + XB_D3DFMT_VERTEXDATA = 100, + XB_D3DFMT_INDEX16 = 101, + + XB_D3DFMT_FORCE_DWORD =0x7fffffff +} XB_D3DFORMAT; + +#define D3DCOMMON_TYPE_MASK 0x0070000 +#define D3DCOMMON_TYPE_TEXTURE 0x0040000 + +// XPR header +struct XPR_FILE_HEADER +{ + DWORD dwMagic; + DWORD dwTotalSize; + DWORD dwHeaderSize; +}; + +#define XPR_MAGIC_HEADER_VALUE (('0' << 24) | ('R' << 16) | ('P' << 8) | 'X') + +DWORD BytesPerPixelFromFormat(XB_D3DFORMAT format); +BOOL IsSwizzledFormat(XB_D3DFORMAT format); +void SetTextureHeader(UINT Width, UINT Height, UINT Levels, UINT Usage, XB_D3DFORMAT Format, D3DTexture *pTexture, UINT Data, UINT Pitch); +void SwizzleRect(LPCVOID pSource, DWORD Pitch, LPVOID pDest, DWORD Width, DWORD Height, DWORD BytesPerPixel); + +DWORD inline PadPow2(DWORD x) +{ + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return ++x; +} diff --git a/tools/XBMCTex/xwinapi.cpp b/tools/XBMCTex/xwinapi.cpp new file mode 100644 index 0000000000..ea5955c837 --- /dev/null +++ b/tools/XBMCTex/xwinapi.cpp @@ -0,0 +1,81 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include "xwinapi.h" +#ifdef __APPLE__ +#include "OSXGNUReplacements.h" +#endif + +// I hope this doesn't need to handle unicode... +LPTSTR GetCommandLine() { + pid_t pid = 0; + char procFile[32], + *cmdline = NULL; + FILE *fp = NULL; + size_t cmdlinelen = 0; + int i; + + pid = getpid(); + sprintf(procFile, "/proc/%u/cmdline", pid); + if((fp = fopen(procFile, "r")) == NULL) + return NULL; + + // getline() allocates memory so be sure to free it + // after calling GetCommandLine() + if (getline(&cmdline, &cmdlinelen, fp) == -1) + { + fclose(fp); + return NULL; + } + + fclose(fp); + fp = NULL; + + for (i = 0; i < (int)cmdlinelen; i++) { + if (cmdline[i] == 0x00) { + if (cmdline[i + 1] == 0x00) + break; + cmdline[i] = ' '; + } + } + + cmdline = (char *)realloc(cmdline, strlen(cmdline) + 1); + return cmdline; +} + +DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer) { + bool bSizeTest = (nBufferLength == 0 && lpBuffer == NULL); + if (getcwd(lpBuffer, nBufferLength) == NULL) { + if (errno == ERANGE) { + LPTSTR tmp = NULL; + if (getcwd(tmp, 0) == NULL ) + nBufferLength = 0; + else + nBufferLength = strlen(tmp) + 1; + + free(tmp); + return nBufferLength; + } + return 0; + } + if (bSizeTest) { + nBufferLength = strlen(lpBuffer) + 1; + free(lpBuffer); + lpBuffer = NULL; + return nBufferLength; + } + return strlen(lpBuffer); +} + +BOOL SetCurrentDirectory(LPCTSTR lpPathName) { + return (chdir(lpPathName) == 0); +} + +DWORD GetLastError( ) { + return errno; +} + diff --git a/tools/XBMCTex/xwinapi.h b/tools/XBMCTex/xwinapi.h new file mode 100644 index 0000000000..be97e4c00a --- /dev/null +++ b/tools/XBMCTex/xwinapi.h @@ -0,0 +1,11 @@ +#ifndef XWINAPI_H__ +#define XWINAPI_H__ + +#include "PlatformDefs.h" + +LPTSTR GetCommandLine(); +DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer); +BOOL SetCurrentDirectory(LPCTSTR lpPathName); +DWORD GetLastError(); +#endif // XWINAPI_H__ + diff --git a/tools/XprPack/XprPack.cpp b/tools/XprPack/XprPack.cpp new file mode 100644 index 0000000000..adf05aff02 --- /dev/null +++ b/tools/XprPack/XprPack.cpp @@ -0,0 +1,80 @@ +// XprPack.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "../../xbmc/lib/liblzo/lzo1x.h" + +#pragma comment(lib, "../../xbmc/lib/liblzo/lzo.lib") + +int main(int argc, char* argv[]) +{ + if (argc < 2) + { + puts("Usage: XprPack xprfile"); + return 1; + } + + printf("Compressing %s: ", argv[1]); + + HANDLE hFile = CreateFile(argv[1], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if (hFile == INVALID_HANDLE_VALUE) + { + printf("Unable to open file: %x\n", GetLastError()); + return 1; + } + + DWORD n; + DWORD XprHeader[3]; // "XPR0", totalsize, headersize + if (!ReadFile(hFile, XprHeader, 12, &n, 0) || n != 12) + { + printf("Unable to read header: %x\n", GetLastError()); + return 1; + } + + SetFilePointer(hFile, XprHeader[2], 0, FILE_BEGIN); + + lzo_uint SrcSize = XprHeader[1] - XprHeader[2]; + lzo_byte* src = (lzo_byte*)VirtualAlloc(0, SrcSize, MEM_COMMIT, PAGE_READWRITE); + + if (!ReadFile(hFile, src, SrcSize, &n, 0) || n != SrcSize) + { + printf("Unable to read data: %x\n", GetLastError()); + return 1; + } + + lzo_uint DstSize; + lzo_byte* dst = (lzo_byte*)VirtualAlloc(0, SrcSize, MEM_COMMIT, PAGE_READWRITE); + + lzo_voidp tmp = VirtualAlloc(0, LZO1X_999_MEM_COMPRESS, MEM_COMMIT, PAGE_READWRITE); + if (lzo1x_999_compress(src, SrcSize, dst + 4, &DstSize, tmp) != LZO_E_OK) + { + printf("Compression failure\n"); + return 1; + } + + lzo_uint s; + lzo1x_optimize(dst + 4, DstSize, src, &s, NULL); + + SetFilePointer(hFile, XprHeader[2], 0, FILE_BEGIN); + + *((lzo_uint*)dst) = SrcSize; + if (!WriteFile(hFile, dst, DstSize + 4, &n, 0) || n != DstSize + 4) + { + printf("Unable to write data: %x\n", GetLastError()); + return 1; + } + SetEndOfFile(hFile); + + SetFilePointer(hFile, 0, 0, FILE_BEGIN); + + XprHeader[1] = XprHeader[2] + DstSize + 4; + if (!WriteFile(hFile, XprHeader, 12, &n, 0) || n != 12) + { + printf("Unable to write data: %x\n", GetLastError()); + return 1; + } + + printf("%.1f:1\n", double(SrcSize) / double(DstSize)); + + return 0; +}
\ No newline at end of file diff --git a/tools/XprPack/XprPack.sln b/tools/XprPack/XprPack.sln new file mode 100644 index 0000000000..a8059fccc1 --- /dev/null +++ b/tools/XprPack/XprPack.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XprPack", "XprPack.vcproj", "{D22B9076-1BD3-4A79-91EB-FE437DBB718D}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {D22B9076-1BD3-4A79-91EB-FE437DBB718D}.Debug.ActiveCfg = Debug|Win32 + {D22B9076-1BD3-4A79-91EB-FE437DBB718D}.Debug.Build.0 = Debug|Win32 + {D22B9076-1BD3-4A79-91EB-FE437DBB718D}.Release.ActiveCfg = Release|Win32 + {D22B9076-1BD3-4A79-91EB-FE437DBB718D}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/tools/XprPack/XprPack.vcproj b/tools/XprPack/XprPack.vcproj new file mode 100644 index 0000000000..c7a92a81bc --- /dev/null +++ b/tools/XprPack/XprPack.vcproj @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="XprPack" + ProjectGUID="{D22B9076-1BD3-4A79-91EB-FE437DBB718D}" + Keyword="Win32Proj"> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + MinimalRebuild="TRUE" + BasicRuntimeChecks="3" + RuntimeLibrary="5" + UsePrecompiledHeader="3" + WarningLevel="3" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="4"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/XprPack.exe" + LinkIncremental="2" + IgnoreDefaultLibraryNames="libc" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(OutDir)/XprPack.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + RuntimeLibrary="4" + UsePrecompiledHeader="3" + WarningLevel="3" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="3"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/XprPack.exe" + LinkIncremental="1" + GenerateDebugInformation="TRUE" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + <File + RelativePath=".\stdafx.cpp"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1"/> + </FileConfiguration> + </File> + <File + RelativePath=".\XprPack.cpp"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + <File + RelativePath=".\stdafx.h"> + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> + </Filter> + <File + RelativePath=".\ReadMe.txt"> + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/tools/XprPack/stdafx.cpp b/tools/XprPack/stdafx.cpp new file mode 100644 index 0000000000..12ebb76034 --- /dev/null +++ b/tools/XprPack/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// XprPack.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/tools/XprPack/stdafx.h b/tools/XprPack/stdafx.h new file mode 100644 index 0000000000..da1eb595a8 --- /dev/null +++ b/tools/XprPack/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define _WIN32_WINNT 0x500 // Win 2k/XP REQUIRED! +#include <windows.h> + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <malloc.h> diff --git a/tools/osx/org.xbmc.helper.plist b/tools/osx/org.xbmc.helper.plist new file mode 100644 index 0000000000..206918e563 --- /dev/null +++ b/tools/osx/org.xbmc.helper.plist @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>Label</key> + <string>org.xbmc.helper</string> + <key>ProgramArguments</key> + <array> + <string>${PATH}</string> + <string>${ARG1}</string> + </array> + <key>RunAtLoad</key> + <true/> +</dict> +</plist> diff --git a/tools/osx/preflight b/tools/osx/preflight new file mode 100755 index 0000000000..4c249a62dd --- /dev/null +++ b/tools/osx/preflight @@ -0,0 +1,198 @@ +#!/usr/bin/perl + +die("No home set, cannot install defaults.\n") + if !$ENV{HOME}; + +sub get_home { + return $ENV{'HOME'} if defined $ENV{'HOME'}; +} + +sub get_extras { + # XBMC_HOME is assumed to be always setup + return $ENV{'XBMC_HOME'}."/extras/" if get_os() eq "osx"; + return; +} + +sub get_xbmc_home { + my $os = get_os(); + my $home = get_home(); + return if !defined $home; + if ( $os eq "osx" ) { + return $home."/Library/Application Support/XBMC"; + } + elsif ( $os eq "linux" ) { + return $home."/.xbmc"; + } + return; +} + +sub get_os { + if ( defined $ENV{'OSTYPE'} && $ENV{'OSTYPE'} =~ /linux/ ) { + return "linux"; + } + return "osx"; +} + +sub get_userdata_path { + my $xhome = get_xbmc_home(); + return if !defined $xhome; + return "$xhome/userdata"; +} + +sub setup_sources { + my $xbmchome = get_xbmc_home(); + my $userdata = get_userdata_path(); + if (!$userdata) { + print STDERR "Unable to obtain userdata path\n"; + exit; + } + + my $sources = $userdata."/sources.xml"; + + # create userdata directory if it doesn't exist + `mkdir -p "$userdata"`; + + # check whether a sources.xml already exists, and if it does back it up + if ( -f $sources ) { + print STDERR "sources.xml found at \"$sources\", backing up\n"; + my $backup_sources = $sources.".".time().".xml"; + `cp -f \"$sources\" \"$backup_sources\"`; + } + + # construct a sources.xml string + my $sources_xml = get_sources_xml( get_default_sources() ); + if ( $sources_xml ) { + open SOURCES, ">$sources" || exit; + print SOURCES get_sources_xml( get_default_sources() ); + close SOURCES; + } +} + +sub get_sources_xml { + my $sources = shift; + my ($sourcetype, $source); + + return if !defined $sources; + + my $xml = "<sources>\n"; + while ( ($sourcetype, $source) = each ( %$sources ) ) { + $xml .= (" " x 4)."<$sourcetype>\n"; + $xml .= (" " x 8)."<default></default>\n"; + my ($name, $path); + while ( ($name, $path) = each( %{ $source } ) ) { + $xml .= (" " x 8)."<source>\n"; + $xml .= (" " x 12)."<name>$name</name>\n"; + if ( $path =~ /(.*)\^\^(.*)/ ) { + $xml .= (" " x 12)."<path>".$1."</path>\n"; + $xml .= (" " x 12)."<thumbnail>".$2."</thumbnail>\n"; + } + else { + $xml .= (" " x 12)."<path>".$path."</path>\n"; + } + $xml .= (" " x 8)."</source>\n"; + } + $xml .= (" " x 4)."</$sourcetype>\n"; + } + $xml .= "</sources>\n"; + return $xml; +} + +sub get_default_sources { + my $sources = {}; + my $home = get_home(); + my $xbmchome = get_xbmc_home(); + return if !defined $xbmchome; + + $sources->{'programs'} = {}; + $sources->{'video'} = {}; + $sources->{'music'} = {}; + $sources->{'pictures'} = {}; + $sources->{'files'} = {}; + + if ( get_os() eq "osx" ) { + + # Default sources for OS X + for my $key ( keys %$sources ) { + $sources->{$key}->{'Volumes'} = "/Volumes"; + $sources->{$key}->{'Home'} = "$home"; + $sources->{$key}->{'Desktop'} = "$home/Desktop"; + } + + $sources->{'music'}->{'Music'} = $home."/Music"; + $sources->{'music'}->{'Music Playlists'} = "special://musicplaylists"; + $sources->{'video'}->{'Movies'} = $home."/Movies"; + $sources->{'video'}->{'Video Playlists'} = "special://videoplaylists"; + $sources->{'pictures'}->{'Pictures'} = $home."/Pictures"; + + my $plugindir = "$xbmchome/plugins/"; + + # iPhoto + if ( -f "$plugindir/pictures/iPhoto/default.py" ) { + $sources->{'pictures'}->{'iPhoto'} = + "plugin://pictures/iPhoto/^^$plugindir/pictures/iPhoto/default.tbn"; + } + + # iTunes + if ( -f "$plugindir/music/iTunes/default.py" ) { + $sources->{'music'}->{'iTunes'} = + "plugin://music/iTunes/^^$plugindir/music/iTunes/default.tbn"; + } + + # AMT + if ( -f "$plugindir/video/Apple Movie Trailers II/default.py" ) { + $sources->{'video'}->{'Apple Movie Trailers'} = + "plugin://video/Apple Movie Trailers II/^^$plugindir/video/Apple Movie Trailers II/default.tbn"; + } + } + elsif ( get_os() eq "linux" ) { + + # Default source for Linux + for my $key ( keys %$sources ) { + $sources->{$key}->{'Media'} = "/media"; + $sources->{$key}->{'Home'} = "$home"; + $sources->{$key}->{'Desktop'} = "$home/Desktop"; + $sources->{$key}->{'Root'} = "/"; + } + } + return $sources; +} + +sub first_xbmc_run() { + my $home = get_xbmc_home(); + if ( ! -f "$home/.setup_complete" ) { + return 1; + } + return; +} + +sub first_xbmc_version_run() { + my $home = get_xbmc_home(); + if ( ! -f "$home/.setup_complete" ) { + return 1; + } + return; +} + +sub setup_default_xbmc() { + my $extras = get_extras(); + my $xhome = get_xbmc_home(); + + die("No home or extras :(\n") if !$xhome || !$extras; + + # copy extra stuff to xbmc's app data directory + `cp -fRv "$extras/user/" "$xhome/"`; + setup_sources(); + `touch -f "$xhome/.setup_complete"`; +} + +sub setup_version_xbmc() { + #TODO +} + +if (first_xbmc_run()) { + setup_default_xbmc(); +} + +if (first_xbmc_version_run()) { + setup_version_xbmc(); +} |