diff --git a/dev-libs/libfreenect/Manifest b/dev-libs/libfreenect/Manifest new file mode 100644 index 0000000000000000000000000000000000000000..fe46aa8f45de9476390d4f6869e88fff9294644c --- /dev/null +++ b/dev-libs/libfreenect/Manifest @@ -0,0 +1,3 @@ +AUX fwfetcher.py 19779 SHA256 aa5dcd4a0a4668443a12f4e43e77fb1ea9b56dce0d078781e84d860e2c958a7a SHA512 b6e995605aad2dbe6d945b3e5b7dd7d962bbeacd52bcd83308d4212d61a29553a8e6a3d635e521c121e91b251529b0933a477cad74c6a8568cb43b5e86a7cf7d WHIRLPOOL c123fa023fb0a874fbec1fae55ae6fe0cb762c979ce8a3c527f1c60ae73dd978824ce528bd8dd3cba2bcd6bf9ee3f9f4c01ac1e809590e2e3bbcfae06d0aced6 +DIST libfreenect-0.5.0.tar.gz 1172310 SHA256 34697e37637730778e2c4aed1f583f7f31e759e165b370a6b1c49fa3a533073c SHA512 25538287d5c2fbdc27e6ac546a40413a70c7fb80cd7de6bc47e56350fa43e9daa60280c478e48182a806010ead071755731114de5fac3c4fdbc90119ec89751c WHIRLPOOL 1cd5375973ee440586788db60ee9fa0b700b2e0c02e2ba9b76620bd24cd875d843dd9ba64986c65bedd4f1219f309a449d3162f4f36f7cce5b6fe5c80a84099e +EBUILD libfreenect-0.5.0.ebuild 2265 SHA256 465f2604dd089a67228564bf9a9d3152b810285dffaa1bbbe9b0a52d4160f68e SHA512 7edb4efa2c1d2e5e471bf3e77760465ad773c90c8ba0e6a3d2aac49baa2a22c5a3158a9aa996a46b6ff6182363f94cdfd1f2d31789aadadf54be0def6106a896 WHIRLPOOL dc531fadd20d3291433287d20526878733c539a00560fb51a911e9a7b9b77ecce22694faca09320219fecfd98df04b4096606f4801f44d14d06c8ddaa4057bc1 diff --git a/dev-libs/libfreenect/files/fwfetcher.py b/dev-libs/libfreenect/files/fwfetcher.py new file mode 100644 index 0000000000000000000000000000000000000000..250b8ee7b2d30e1c87a0dd6b9b2d58c6d4750055 --- /dev/null +++ b/dev-libs/libfreenect/files/fwfetcher.py @@ -0,0 +1,573 @@ +#!/usr/bin/env python2 + +from urllib2 import Request, urlopen, URLError +import hashlib +import os +import StringIO +import struct +import sys +import time +import zipfile + +# fwfetcher.py - a program to extract the Kinect audio firmware from an Xbox360 +# system update. This program includes substantial portions of extract360.py, +# which is copyright Rene Ladan and others as noted below and provided under +# the BSD 2-clause license. + +"""Program to extract typical XBox 360 files. + It can handle LIVE/PIRS, CON (partially), FMIM, and XUIZ files. + + What about CRA (aka .arc) files? (Dead Rising demo) + + Copyright (c) 2007, 2008, Rene Ladan , 2-claused BSD + license. Portions from various contributors as mentioned in-source. + + Note that it dumps UTF-16 characters in text strings as-is. +""" + +################################################################################ + +def check_size(fsize, minsize): + """Ensure that the filesize is at least minsize bytes. + + @param fsize the filesize + @param minsize the minimal file size + @return fsize >= minsize + """ + + if fsize < minsize: + print "Input file too small: %i instead of at least %i bytes." % \ + (fsize, minsize) + return fsize >= minsize + +################################################################################ + +def nice_open_file(filename): + """Checks if the output file with the given name already exists, + and if so, asks for overwrite permission. + + @param filename name of the output file to open + @return overwrite permission + """ + + if os.path.isfile(filename): + print filename, "already exists, overwrite? (y/n)", + answer = raw_input("") + return len(answer) > 0 and answer[0] in ["Y", "y"] + else: + return True + +################################################################################ + +def nice_open_dir(dirname): + """Checks if the output directory with the given name already exists, + and if so, asks for overwrite permission. This means that any file + in that directory might be overwritten. + + @param dirname name of the output directory to open + @return overwrite permission + """ + + if os.path.isdir(dirname): + print dirname, "already exists, ok to overwrite files in it? (y/n)", + answer = raw_input("") + return len(answer) > 0 and answer[0] in ["Y", "y"] + else: + return True + +################################################################################ + +def do_mkdir(dirname): + """Version of os.mkdir() which does not throw an exception if the directory + already exists. + + @param dirname name of the directory to create + """ + + try: + os.mkdir(dirname) + except OSError, (errno): + if errno == 17: + pass # directory already exists + +################################################################################ + +def strip_blanks(instring): + """Strip the leading and trailing blanks from the input string. + Blanks are: 0x00 (only trailing) space \t \n \r \v \f 0xFF + + @param instring the input string + @return stripped version of instring + """ + + rstr = instring.rstrip("\0 \t\n\r\v\f\377") + return rstr.lstrip(" \t\n\r\v\f\377") + +################################################################################ + +def open_info_file(infile): + """Open the informational text file. + The name is based on that of the input file. + + @param infile pointer to the input file + @return pointer to the informational text file or None if there was no + overwrite permission + """ + + txtname = os.path.basename(infile.name) + ".txt" + if nice_open_file(txtname): + print "Writing information file", txtname + txtfile = open(txtname, "w") + return txtfile + else: + return None + +################################################################################ + +def dump_png(infile, pnglen, maxlen, pngid): + """Dump the embedded PNG file from the archive file to an output file. + + @param infile pointer to the archive file + @param pnglen size of the PNG file in bytes + @param maxlen maximum size of the PNG file in bytes + @param pngid indicates if this is the first or second PNG file. + """ + + # dump PNG icon + if pnglen <= maxlen: + outname = os.path.basename(infile.name) + "_" + pngid + ".png" + if nice_open_file(outname): + buf = infile.read(pnglen) + print "Writing PNG file", outname + outfile = open(outname, "wb") + print >> outfile, buf, + outfile.close() + else: + print "PNG image %s too large (%i instead of maximal %i bytes), " \ + "file not written." % (pngid, pnglen, maxlen) + +################################################################################ + +def dump_info(infile, txtfile, what): + """Dumps the 9 information strings from the input file. + + @param infile pointer to the input file + @param txtfile pointer to the resulting text file + @param what indicates if the information consists of titles or + descriptions + """ + + print >> txtfile, "\n", what, ":" + for i in xrange(9): + info = strip_blanks(infile.read(0x100)) + if len(info) > 0: + print >> txtfile, lang[i], ":", info + +################################################################################ + +def mstime(intime): + """Convert the time given in Microsoft format to a normal time tuple. + + @param intime the time in Microsoft format + @return the time tuple + """ + + num_d = (intime & 0xFFFF0000L) >> 16 + num_t = intime & 0x0000FFFFL + # format below is : year, month, day, hour, minute, second, + # weekday (Monday), yearday (unused), DST flag (guess) + return ((num_d >> 9) + 1980, (num_d >> 5) & 0x0F, num_d & 0x1F, + (num_t & 0xFFFF) >> 11, (num_t >> 5) & 0x3F, (num_t & 0x1F) * 2, + 0, 0, -1) + +################################################################################ + +def do_utime(targetname, atime, mtime): + """Set the access and update date/time of the target. + Taken from tarfile.py (builtin lib) + + @param targetname name of the target + @param atime the desired access date/time + @param mtime the desired update date/time + """ + + if not hasattr(os, "utime"): + return + if not (sys.platform == "win32" and os.path.isdir(targetname)): + # Using utime() on directories is not allowed on Win32 according to + # msdn.microsoft.com + os.utime(targetname, + (time.mktime(mstime(atime)), time.mktime(mstime(mtime)))) + +################################################################################ + +def check_sha1(sha1, entry, infile, start, end): + """Check the SHA1 value of the specified range of the input file. + + @param sha1 the reported SHA1 value + @param entry the id of the hash + @param infile the input file to check + @param start the start position + @param end the end position + @return string reporting if the hash is correct + """ + + infile.seek(start) + found_sha1 = hashlib.sha1(infile.read(end - start)) + found_digest = found_sha1.digest() + # SHA1 hashes are 20 bytes (160 bits) long + ret = "SHA1 " + hex(entry) + " " + if found_digest == sha1: + return ret + "ok (" + found_sha1.hexdigest() + ")" + else: + hexdig = "" + for i in sha1: + if ord(i) < 10: + val = "0" + else: + val = "" + val += hex(ord(i))[2:] + hexdig += val + return ret + "wrong (should be " + hexdig + " actual " + \ + found_sha1.hexdigest() + ")" + +################################################################################ + +def get_cluster(startclust, offset): + """get the real starting cluster""" + rst = 0 + # BEGIN wxPirs + while startclust >= 170: + startclust //= 170 + rst += (startclust + 1) * offset + # END wxPirs + return rst + +################################################################################ + +def fill_directory(infile, txtfile, contents, firstclust, makedir, start, + offset): + """Fill the directory structure with the files contained in the archive. + + @param infile pointer to the archive + @param txtfile pointer to the resulting information text file + @param contents contains the directory information + @param firstclust address of the starting cluster of the first file in + infile (in 4kB blocks, minus start bytes) + @param makedir flag if directory should be filled, useful if only return + is wanted + @param start start of directory data + @param offset increment for calculating real starting cluster + """ + + # dictionary which holds the directory structure, + # patch 0xFFFF is the 'root' directory. + paths = {0xFFFF:""} + + oldpathind = 0xFFFF # initial path, speed up file/dir creation + + for i in xrange(0x1000 * firstclust // 64): + cur = contents[i * 64:(i + 1) * 64] + if ord(cur[40]) == 0: + # if filename length is zero, we're done + break + (outname, namelen, clustsize1, val1, clustsize2, val2, startclust, + val3) = struct.unpack("<40sBHBHBHB", cur[0:50]) + # sizes and starting cluster are 24 bits long + clustsize1 += val1 << 16 + clustsize2 += val2 << 16 + startclust += val3 << 16 + (pathind, filelen, dati1, dati2) = struct.unpack(">HLLL", cur[50:64]) + + if not makedir: + continue + + nlen = namelen & ~0xC0 + if nlen < 1 or nlen > 40: + print "Filename length (%i) out of range, skipping file." % nlen + continue + outname = outname[0:nlen] # strip trailing 0x00 from filename + + if txtfile != None: + if namelen & 0x80 == 0x80: + print >> txtfile, "Directory", + else: + print >> txtfile, "File", + print >> txtfile, "name:", outname + if namelen & 0x40 == 0x40: + print >> txtfile, "Bit 6 of namelen is set." + + if clustsize1 != clustsize2: + print "Cluster sizes don't match (%i != %i), skipping file." % \ + (clustsize1, clustsize2) + continue + if startclust < 1 and namelen & 0x80 == 0: + print "Starting cluster must be 1 or greater, skipping file." + continue + if filelen > 0x1000 * clustsize1: + print "File length (%i) is greater than the size in clusters " \ + "(%i), skipping file." % (filelen, clustsize1) + continue + + if pathind != oldpathind: + # working directory changed + for _ in xrange(paths[oldpathind].count("/")): + os.chdir("..") # go back to root directory + os.chdir(paths[pathind]) + oldpathind = pathind + if namelen & 0x80 == 0x80: + # this is a directory + paths[i] = paths[pathind] + outname + "/" + do_mkdir(outname) + else: + # this is a file + # space between files is set to 0x00 + adstart = startclust * 0x1000 + start + if txtfile != None: + print >> txtfile, "Starting: advertized", hex(adstart) + + # block reading algorithm originally from wxPirs + buf = "" + while filelen > 0: + realstart = adstart + get_cluster(startclust, offset) + infile.seek(realstart) + buf += infile.read(min(0x1000, filelen)) + startclust += 1 + adstart += 0x1000 + filelen -= 0x1000 + outfile = open(outname, "wb") + print >> outfile, buf, + outfile.close() + + do_utime(outname, dati2, dati1) + + # pop directory + for _ in xrange(paths[oldpathind].count("/")): + os.chdir("..") + +################################################################################ + +def write_common_part(infile, txtfile, png2stop, start): + """Writes out the common part of PIRS/LIVE and CON files. + + @param infile pointer to the PIRS/LIVE or CON file + @param txtfile pointer to the resulting text file + @param png2stop location where the second PNG image stops + (PIRS/LIVE : 0xB000, CON : 0xA000) + @param start start of directory data, from wxPirs + """ + + infile.seek(0x32C) + mhash = infile.read(20) # xbox180 : SHA1 hash of 0x0344-0xB000, + # CON : 0x0344 - 0xA000 (i.e. png2stop) + (mentry_id, content_type) = struct.unpack(">LL", infile.read(8)) + + if txtfile != None: + print >> txtfile, "\nMaster SHA1 hash :", \ + check_sha1(mhash, mentry_id, infile, 0x0344, png2stop) + print >> txtfile, "\nContent type", hex(content_type), ":", + # content type list partially from V1kt0R + # su20076000_00000000 has type 0x000b0000, + # i.e. "Full game demo" & "Theme" ... + if content_type == 0: + print >> txtfile, "(no type)" + elif content_type & 0x00000001: + print >> txtfile, "Game save" + elif content_type & 0x00000002: + print >> txtfile, "Game add-on" + elif content_type & 0x00030000: + print >> txtfile, "Theme" + elif content_type & 0x00090000: + print >> txtfile, "Video clip" + elif content_type & 0x000C0000: + print >> txtfile, "Game trailer" + elif content_type & 0x000D0000: + print >> txtfile, "XBox Live Arcade" + elif content_type & 0x00010000: + print >> txtfile, "Gamer profile" + elif content_type & 0x00020000: + print >> txtfile, "Gamer picture" + elif content_type & 0x00040000: + print >> txtfile, "System update" + elif content_type & 0x00080000: + print >> txtfile, "Full game demo" + else: + print >> txtfile, "(unknown)" + + print >> txtfile, "\nDirectory data at (hex)", hex(start) + infile.seek(0x410) + dump_info(infile, txtfile, "Titles") + dump_info(infile, txtfile, "Descriptions") + print >> txtfile, "\nPublisher:", strip_blanks(infile.read(0x80)), "\n" + print >> txtfile, "\nFilename:", strip_blanks(infile.read(0x80)), "\n" + infile.seek(0x1710) + (val1, png1len, png2len) = struct.unpack(">HLL", infile.read(10)) + if txtfile != None: + print >> txtfile, "Value:", val1 + + if png1len > 0: + dump_png(infile, png1len, 0x571A - 0x171A, "1") + + if png2len > 0: + infile.seek(0x571A) + dump_png(infile, png2len, png2stop - 0x571A, "2") + + # entries are 64 bytes long + # unused entries are set to 0x00 + infile.seek(start + 0x2F) + (firstclust, ) = struct.unpack("> txtfile + infile.seek(png2stop) + buf = infile.read(start - png2stop) + numempty = 0 + for i in xrange(len(buf) // 24): + entry = buf[i * 24: i * 24 + 24] + if entry.count("\0") < 24: + if numempty > 0: + print >> txtfile, "\nEmpty entries:", numempty + numempty = 0 + print >> txtfile, "Hash (hex):", + for j in xrange(20): + print >> txtfile, hex(ord(entry[j])), + (j, ) = struct.unpack(">L", entry[20:24]) + print >> txtfile, "\nEntry id:", hex(j) + else: + numempty += 1 + + print >> txtfile, "\nTrailing data (hex):", + for i in buf[len(buf) - (len(buf) % 24):]: + print >> txtfile, hex(ord(i)), + print >> txtfile + + txtfile.close() + +################################################################################ + +def handle_live_pirs(infile, fsize): + """LIVE and PIRS files are archive files. + They contain a certificate, payload, SHA1 checksums, + 2 icons, textual information, and the files themselves. + + @param infile pointer to the archive file + @param fsize size of infile + """ + + print "Handling LIVE/PIRS file." + + if not check_size(fsize, 0xD000): + return + + txtfile = open_info_file(infile) + if txtfile != None: + print >> txtfile, "Certificate (hex):", + cert = infile.read(0x100) + for i in cert: + print >> txtfile, hex(ord(i)), + + print >> txtfile, "\n\nData (hex):", + data = infile.read(0x228) + for i in data: + print >> txtfile, hex(ord(i)), + print >> txtfile + + ### BEGIN wxPirs ### + infile.seek(0xC032) # originally 4 bytes at 0xC030 + (pathind, ) = struct.unpack(">H", infile.read(2)) + if pathind == 0xFFFF: + start = 0xC000 + else: + start = 0xD000 + ### END wxPirs ### + write_common_part(infile, txtfile, 0xB000, start) + +################################################################################ + +# End of code taken from extract360.py. + +def getFileOrURL(filename, url): + # Check if a file named filename exists on disk. + # If so, return its contents. If not, download it, save it, and return its contents. + try: + f = open(filename) + print "Found", filename, "cached on disk, using local copy" + retval = f.read() + return retval + except IOError, e: + pass + print "Downloading", filename, "from", url + req = Request(url) + try: + response = urlopen(req) + except URLError, e: + if hasattr(e, 'reason'): + print "Failed to reach download server. Reason:", e.reason + elif hasattr(e, 'code'): + print "The server couldn't fulfill the request. Error code:", e.code + print "Reading response..." + retval = response.read() + # Save downloaded file to disk + f = open(filename, "wb") + f.write(retval) + f.close() + print "done, saved to", filename + return retval + +def extractPirsFromZip(systemupdate): + print "Extracting $SystemUpdate/FFFE07DF00000001 from system update file..." + updatefile = StringIO.StringIO(systemupdate) + z = zipfile.ZipFile(updatefile) + #print z.namelist() + pirs = z.open("$SystemUpdate/FFFE07DF00000001").read() + print "done." + return pirs + +if __name__ == "__main__": + target = "audios.bin" + if len(sys.argv) == 2: + target = sys.argv[1] + if not os.path.isfile(target): + fw = getFileOrURL("SystemUpdate.zip", "http://www.xbox.com/system-update-usb") + pirs = extractPirsFromZip(fw) + + lang = ["English", "Japanese", "German", "French", "Spanish", "Italian", + "Korean", "Chinese", "Portuguese"] + sio = StringIO.StringIO(pirs) + basename = "FFFE07DF00000001" + sio.name = basename + pwd = os.getcwd() + handle_live_pirs(sio, len(pirs)-4) + + os.chdir(pwd) + print "Moving audios.bin to current folder" + os.rename(os.path.join(basename + ".dir", "audios.bin"), target) + + print "Cleaning up" + os.unlink(basename + ".txt") + for root, dirs, files in os.walk(basename + ".dir"): + for name in files: + os.remove(os.path.join(root, name)) + for name in dirs: + os.rmdir(os.path.join(root, name)) + os.rmdir(root) + os.unlink("SystemUpdate.zip") + print "Done!" + else: + print "Already have audios.bin" diff --git a/dev-libs/libfreenect/libfreenect-0.5.0.ebuild b/dev-libs/libfreenect/libfreenect-0.5.0.ebuild new file mode 100644 index 0000000000000000000000000000000000000000..917ee576b6318a8a0e66688dca54830079840823 --- /dev/null +++ b/dev-libs/libfreenect/libfreenect-0.5.0.ebuild @@ -0,0 +1,80 @@ +# Copyright 1999-2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI="5" + +inherit cmake-utils multilib python + +[[ ${PV} = *9999* ]] && VCS_ECLASS="git-2" || VCS_ECLASS="" + +DESCRIPTION="Core library for accessing the Microsoft Kinect." +HOMEPAGE="https://github.com/OpenKinect/${PN}" +if [[ ${PV} == *9999* ]] ; then + EGIT_REPO_URI="git://github.com/OpenKinect/${PN}.git" + KEYWORDS="" +else + SRC_URI="https://github.com/OpenKinect/libfreenect/archive/v${PV}.tar.gz -> ${P}.tar.gz" + KEYWORDS="~amd64 ~x86" +fi + +LICENSE="Apache-2.0 GPL-2" +SLOT="0" +IUSE="bindist +c_sync +cpp doc examples fakenect opencv openni2 python" + +PYTHON_DEPEND="!bindist? 2" + +COMMON_DEP="virtual/libusb:1 + examples? ( media-libs/freeglut + virtual/opengl + x11-libs/libXi + x11-libs/libXmu ) + opencv? ( media-libs/opencv ) + python? ( dev-python/numpy )" + +RDEPEND="${COMMON_DEP}" +DEPEND="${COMMON_DEP} + dev-util/cmake + virtual/pkgconfig + doc? ( app-doc/doxygen ) + python? ( dev-python/cython )" + + +src_configure() { + local mycmakeargs=( + $(cmake-utils_use_build bindist REDIST_PACKAGE) + $(cmake-utils_use_build c_sync C_SYNC) + $(cmake-utils_use_build cpp CPP) + $(cmake-utils_use_build examples EXAMPLES) + $(cmake-utils_use_build fakenect FAKENECT) + $(cmake-utils_use_build opencv CV) + $(cmake-utils_use_build openni2 OPENNI2_DRIVER) + $(cmake-utils_use_build python PYTHON) + ) + cmake-utils_src_configure +} + +src_install() { + cmake-utils_src_install + + # udev rules + insinto /lib/udev/rules.d/ + doins "${S}"/platform/linux/udev/51-kinect.rules + + # documentation + dodoc README.md + if use doc; then + cd doc + doxygen || ewarn "doxygen failed" + dodoc -r html || ewarn "dodoc failed" + cd - + fi +} + +pkg_postinst() { + if ! use bindist; then + ewarn "The bindist USE flag is disabled. Resulting binaries may not be legal to re-distribute." + fi + elog "Make sure your user is in the 'video' group" + elog "Just run 'gpasswd -a video', then have re-login." +}